My self-documenting maintainance scripts, where I document how systems have been setup, I need to execute stuff as sudo/root and want the results automatically added to the document. But for safety reasons on the target system root has login disabled. I have to connect via an admin-user, which then can sudo stuff.

in my emacs init.el this adds bash execution:

;; allow org mode bash execution
;; --------------------------------------
(org-babel-do-load-languages 'org-babel-load-languages '( (shell . t ) ) )

Then in my document I have e.g. this bash / shell piece:

#+BEGIN_SRC bash :dir /sudo:adminuser@fresh_installed_computer:~/ :results output 
parted /dev/sda "unit GiB" "print free"
parted /dev/sda "unit s" "print free"

The error message is:

Host 'fresh_installed_computer' looks like a remote host, 'sudo' can only use the local host.

See Org-Mode Manual: 15 Working with Source Code

Using Debian Stretch with Emacs 24.5.1 on the local machine, the remote machine is about to become debian buster fresh install.


When executing

#+BEGIN_SRC bash :dir /ssh:adminuser@fresh_installed_computer|sudo:fresh_installed_computer:~/ :results output :session 
echo "user $USER" 

The status line holds "Opening connection for root@fresh_installed_computer using sudo... \" and then waits forever

Interestingly: when I add the actual IP address like this, it suddenly works as expected:

#+BEGIN_SRC bash :dir /ssh:adminuser@fresh_installed_computer|sudo:XXX.XXX.XXX.XXX:~/ :results output :session 
echo "user $USER" 
: user root 

ssh to adminuser@fresh_installed_computer and there pinging works, so name resolving is up.

ping fresh_installed_computer

Any explanation, or do I need to stick with magic number fixed ip adress in my document?


The issue with resolving hostname vs IP adress could be solved by clearing tramp proxy caches:

M-x tramp-cleanup-all-connections
M-: (setq tramp-default-proxies-alist nil)

Now all works fine! Thx

  • Welcome to emacs stack exchange! Please add emacs version and org-mode version to your question for troubleshooting. – Melioratus Mar 27 at 13:28
  • Does :dir /ssh:adminuser@fresh_installed_computer|sudo:localhost:~/ or :dir /ssh:adminuser@fresh_installed_computer|sudo:root@fresh_installed_computer:~/ work instead? – Melioratus Apr 1 at 18:45
  • It could be that tramp is waiting for a prompt. Does :dir /sshx:adminuser@fresh_installed_computer|sudo:fresh_installed_computer:~/ work? Note the extra x in sshx. – Melioratus Apr 1 at 18:48
  • 1
    Don't use ...|sudo:localhost: -- that's once again going to create a dangerous proxy on Emacs versions < 27. – phils Apr 1 at 20:15
  • 2
    I'm not sure why one of those approaches worked and the other didn't, but you might try M-x tramp-cleanup-all-connections and M-: (setq tramp-default-proxies-alist nil) and see whether that changes anything? (Mostly I'm wondering whether earlier attempts had left a dodgy proxy in place, such that it was trying to proxy root@fresh_installed_computer to somewhere else.) – phils Apr 1 at 20:28

Use TRAMP multi-hop syntax for :dir header.

4.4 Combining ssh or plink with su or sudo

If the su or sudo option shall be performed on another host, it could be comnbined with a leading ssh or plink option. That means, TRAMP connects first to the other host with non-administrative credentials, and changes to administrative credentials on that host afterwards. In a simple case, the syntax looks like /ssh:user@host|sudo:host:/path/to/file.

:dir /ssh:user@fresh_installed_computer|sudo:adminuser@fresh_installed_computer:~/

Tip: Adding :session header to code block can be helpful too.

#+BEGIN_SRC bash :dir /ssh:user@fresh_installed_computer|sudo:adminuser@fresh_installed_computer:~/ :results output :session 
parted /dev/sda "unit GiB" "print free"
parted /dev/sda "unit s" "print free"

Note: If the goal is to login as adminuser and then sudo to root user the tramp connection string would be updated this way instead.

:dir /ssh:adminuser@fresh_installed_computer|sudo:fresh_installed_computer:~/

#+BEGIN_SRC bash :dir /ssh:adminuser@fresh_installed_computer|sudo:fresh_installed_computer:~/ :results > output :session 
parted /dev/sda "unit GiB" "print free"
parted /dev/sda "unit s" "print free"

Thanks to NickD for pointing this out!

Don't use ...|sudo:localhost: -- that's once again going to create a dangerous proxy on Emacs versions < 27

Thanks to phils for pointing this out!

| improve this answer | |
  • 1
    I may be misunderstanding but I think he needs to login to the remote as adminuser and then sudo (to root) over there: :dir /ssh:adminuser@fresh_installed_computer|sudo::~/ – NickD Mar 27 at 14:40
  • Thanks @NickD - Good point! I'll update my answer with your example. – Melioratus Mar 27 at 15:29
  • 2
    @NickD Note that /ssh:user@host|sudo::~/ is wrong/dangerous on all version of Emacs < 27*. Anyone who uses -- or might use -- earlier versions of Emacs should make certain to specify the host in every hop when multi-hopping -- including sudo:host: instead of sudo::. I've edited this answer accordingly. Refer to stackoverflow.com/a/16408592 for more information. (* The version of Tramp in Emacs 27 handles sudo:: the way you wanted in this scenario.) – phils Mar 28 at 8:42
  • 2
    n.b. The Tramp manual you have linked to is for the latest version of Tramp available on GNU ELPA, rather than the version included in the Emacs distribution. (Emacs 26.3 has Tramp 2.3.4 for instance.) – phils Mar 28 at 8:51
  • 1
    @phils: thanks for the correction and the reference. I did not know that. – NickD Mar 28 at 15:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.