Ответ 1
Как насчет:
(shell-command (concat "echo " (shell-quote-argument (read-passwd "Password? "))
" | sudo -S your_command_here"))
Я пытаюсь создать сочетания клавиш для некоторых обычно используемых команд sudo shell (например, C-c s
run (shell-command "sudo /etc/init.d/apache2 restart")
).
Я попытался использовать прямолинейный вызов командной оболочки, как указано выше, но он просто выводит следующее в буфер *Shell Command Output*
:
[sudo] password for Inaimathi:
Sorry, try again.
[sudo] password for Inaimathi:
Sorry, try again.
[sudo] password for Inaimathi:
Sorry, try again.
sudo: 3 incorrect password attempts
На самом деле он не запрашивает пароль. Я не хочу запускать Emacs с помощью sudo emacs
, но я думаю, что опция, если ничего не будет работать.
Идеальное решение было бы функцией из Emacs (в отличие от OS jiggery-pokery, чтобы изменить поведение оболочки или команды sudo
). Что-то вроде (sudo-shell-command "dostuff")
, или (with-password-prompt (shell-command "sudo dostuff"))
.
Как насчет:
(shell-command (concat "echo " (shell-quote-argument (read-passwd "Password? "))
" | sudo -S your_command_here"))
Я часто вызываю команды из Emacs, например aptitude update
. scottfrazer решение может быть не таким полезным. Синхронные команды заставляют меня ждать долгое время, и если вы выполняете неподдерживаемую программу (например, aptitude
, которая использует ncurses), вы повесите Emacs (C-g не поможет), а загрузка процессора будет на 100%. Переход на async-shell-command
разрешает это.
Но это также вводит новую проблему. Если ваша команда не удалась, ваш пароль окажется в буфере *Messages*
:
echo PASSWORD | sudo -S aptitude: exited abnormally with code 1.
Вот почему я предлагаю следующее решение:
(defun sudo-shell-command (command)
(interactive "MShell command (root): ")
(with-temp-buffer
(cd "/sudo::/")
(async-shell-command command)))
Здесь "M" в interactive
запрашивает имя программы в минибуфере, with-temp-buffer
создает буфер sham, в котором мы меняем каталог на /sudo::/
, чтобы использовать TRAMP для приглашения sudo.
Это решение Дэвида Каструп из команда sudo с приглашением пароля минибуфера @gnu.emacs.help.
Обратите внимание, что вы все равно не должны вызывать aptitude
напрямую, иначе подпроцесс будет там навсегда, пока вы не отправите sudo pkill aptitude
.
Если вы используете emacs22 или более позднюю версию, вы можете просто запустить оболочку из emacs и запустить там команду sudo. Он автоматически выведет вас в окно минибуфера для вашего пароля:
M-x shell
sudo whoami
Это нужно просто попросить пароль внизу в нижней части экрана (без отображения).
Обходной путь (а не решение emacs):
Настройте пару ключей ssh, чтобы не требовался пароль.
Процедура:
ssh-keygen
, чтобы сгенерировать пару ключей. Дайте им полезное имя, чтобы они были отсортированы из всех остальных, которые вы сделаете, когда сможете воспользоваться этим.$HOME/.ssh
для учетной записи получателя.$HOME/.ssh
отправляющей учетной записи (вы можете скопировать его на несколько отправляющих учетных записей, но может быть лучше сделать отдельную пару ключей для каждой входящей машины)$HOME/.ssh/config
на отправляющей машине, чтобы сообщить ssh, какой ключ использовать sudo
пытается открыть терминал (tty), чтобы прочитать пароль. Процесс emacs может не иметь управляющего терминала. sudo -S
сообщает ему использовать стандартный ввод для пароля, который должен поступать от emacs.
РЕДАКТИРОВАТЬ: ответ Скотта, который выше, намного предпочтительнее этого взлома. Используйте это.
Возможное решение:
Я выяснил, что настройка утилиты для запроса по умолчанию, разрешающей эту проблему, решает эту проблему.
Мне нужно было добавить Defaults:ALL askpass=/usr/lib/openssh/gnome-ssh-askpass
в мой /etc/sudoers
файл (используя sudo visudo
, очевидно).
Eval-ing (shell-command "sudo /etc/init.d/apache2 restart")
теперь запрашивает у меня пароль вместо попыток угадать его безуспешно.
Я не принимаю этот ответ, если не станет ясно, что лучшего решения нет; в идеале я хотел бы что-то, что решает проблему внутри Emacs, вместо того, чтобы требовать, чтобы вы ткнулись в свой каталог /etc
.
Я использовал следующее, чтобы запустить nmap из emacs как root,