views:

378

answers:

8

I'm trying to create shortcut keys for some commonly used sudo shell commands (for example, having C-c s run (shell-command "sudo /etc/init.d/apache2 restart")).

I tried using a straight-up shell-command call as above, but it just outputs the following to the *Shell Command Output* buffer:

[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

It doesn't actually ask for a password. I don't want to have to start up Emacs using sudo emacs, but I guess that's an option if nothing else will work.

The ideal solution would be a function from within Emacs (as opposed to OS jiggery-pokery to change the behaviour of the shell or the sudo command). Something like (sudo-shell-command "dostuff"), or (with-password-prompt (shell-command "sudo dostuff")).

+3  A: 

If you're running emacs22 or later, you can just start up a shell from emacs and run your sudo command there. It'll automatically pull you into the minibuffer window for your password:

M-x shell
sudo whoami

This should just ask for your password down at the bottom of the screen (without displaying it).

ramesh
eshell is also nice :)
rmk
A: 

Have you tried running it without the capital 'S'? I don't know if 'sudo' is case sensitive or not, but it's worth a shot.

Scott
A: 

Have you noticed that in minibuffer is asking the password?

Enrico Carlesso
It's not; that's pretty much the entire problem. An accaptable behavior is asking for my sudo password, but I don't get a prompt.
Inaimathi
+1  A: 

sudo attempts to open the terminal device (tty) to read the password. Your emacs process may not have a controlling terminal. sudo -S tells it to use the standard input for a password which should be coming from emacs.

msw
`(shell-command "sudo -S /etc/init.d/apache2 restart")` does the same thing (ie. it tries an arbitrary password 3 times, and sends the 3 unsuccessful attempts to the `*Shell Command Output*` buffer.
Inaimathi
And `(shell-command "echo password | sudo -S /etc/init.d/apache2 restart")`? (Not that it's a good solution to encode the password in the command.)
Dave Bacher
Yeah. I wouldn't want my root password in my code somewhere. That sounds like it might be worse than running `sudo emacs`. +1 for suggesting the -S approach (even if I did misunderstand it at first)
Inaimathi
+1  A: 

EDIT: Scott's answer above is vastly preferable to this hack. Use that.

A possible solution:

I found out that setting a default password-asking utility solves this problem.

What I had to do is add Defaults:ALL askpass=/usr/lib/openssh/gnome-ssh-askpass to my /etc/sudoers file (using sudo visudo, obviously).

Eval-ing (shell-command "sudo /etc/init.d/apache2 restart") now prompts me for a password instead of trying to guess it unsuccessfully.

I'm not accepting this answer unless it becomes clear that there's no better solution; ideally I'd like something that solves the problem internally to Emacs instead of requiring you to poke around your /etc directory.

Inaimathi
Better yet, if you have sudoers control, you can set it up so *you* are not prompted for a password for these programs that you run frequently.
Dave Bacher
+3  A: 

Workaround (rather than an emacs solution):

Set up a ssh key pair so that no password is necessary.

Procedure:

  1. run ssh-keygen to generate a pair of keys. Give them a useful name to keep them sorted out from all the others you'll make once you get use to this
  2. Copy the public one to $HOME/.ssh for the receiving account
  3. Keep the private one in $HOME/.ssh of the sending account (you could copy it to multiple sending accounts, but it might be better to make a separate keypair for every incoming machine)
  4. edit $HOME/.ssh/config on the sending machine to tell ssh what key to use
  5. Profit
dmckee
+1  A: 

I used the following to start nmap from emacs as root,

http://nakkaya.com/sudoEl.markdown

Hamza Yerlikaya
+4  A: 

How about:

(shell-command (concat "echo " (read-passwd "Password? ") " | sudo -S your_command_here"))
scottfrazer
Perfect. In other words, I could easily do something like `(defun sudo-shell-command (command) (shell-command (concat "echo " (read-passwd "Password: ") " | sudo -S " command)))`. Much better than actually writing the password in source-code too.
Inaimathi