TRAMP
Emacs' TRAMP feature (Transparent Remote file Access, Multiple Protocol) is an extremely powerful tool for editing files that exist on remote systems, or require access using a different user account from your main Emacs session, or both.
Description | Edit files on remote systems |
---|---|
Author | name of author |
Maintainer | name of maintainer |
Source | http://savannah.gnu.org/projects/tramp |
Part of Emacs | yes, since Emacs 22 |
Some of the things that TRAMP can do include:
- Editing files on a remote development server over SSH (e.g. /ssh:remote-user@remote.box:/path/to/my/file)
- Editing files on your local machine as root via sudo (e.g. /sudo::/etc/some/config/file)
- Editing files on a remote server as root via sudo over an SSH connection from another remote machine that exists within a DMZ (requires some configuration, see below)
TRAMP is included with Emacs and described in the manual.
Multiple hops
No config in Emacs24
As of Emacs 24, an analog of the old multi-hop syntax has been layered on top of the modern tramp-default-proxies-alist approach, meaning that you can once again perform multi-hops without any prior configuration. For details, see: [ C-hig] (tramp) Ad-hoc multi-hops RET
With the new syntax, each 'hop' is separated by | (pipe). In this instance, it would look like:
[ C-xC-f] /ssh:user@server|sudo:server:/home/user/file RET
As this still uses the proxy mechanism underneath,
[ C-hv] tramp-default-proxies-alist RET
should now include the value:
("server" "root" "/ssh:user@server:")
Meaning that the proxy /ssh:user@server:
is going to be used whenever you request a file as root@server
.
Something important to note here is that you usually don't need to specify server in the sudo:server part -- and indeed sudo:: will still work in a sense -- however if you do that then the dynamic proxy created will contain the hostname you originated from rather than the host you connected to, so I would recommend being explicit; otherwise it will not only look confusing (as the wrong host will be displayed in filenames), but it will also mean that subsequent attempts to use sudo:: on the localhost will be proxied to this remote server!
Configuration for all emacs versions
To set up multiple hop connections you will need to do a little bit of configuration.
As an example, let's assume that you want to edit a file located at /etc/httpd/conf/httpd.conf as root on a remote server at dev.example.com. You have a regular user account chris on the development sever, but you need to use sudo to gain root access before editing the file.
Put the following into your configuration files:
;; Guard to ensure that TRAMP is available
(if (locate-library "tramp")
(eval-after-load "tramp"
;; The actual TRAMP configuration
'(add-to-list 'tramp-default-proxies-alist
'("\\`dev\\.example\\.com\\'"
"\\`chris\\'"
"/ssh:%h:"))))
After this is evaluated, Emacs knows that the hostname dev.example.com must be accessed over SSH by a user called chris.
If you now try to find /sudo:dev.example.com:/etc/httpd/conf/httpd.conf Emacs will automatically create the SSH connection first, prompting you for your password if necessary. Then it will prompt you for your sudo password. Once this is all done you will be able to modify the buffer as necessary. Saving the buffer will do what you expect: it will update the file on the remote server.
It is also possible to configure partial domains, for instance in case you need an SSH connection before modifying anything on *.example.com.
Hops can be chained, making this feature extremely powerful.
A note for Windows users
TRAMP uses programs that are usually included with GNU/Linux systems under the hood. These are not usually available on a Windows system.
The plink method built into TRAMP can be used as a mostly drop-in replacement for SSH connections. It uses plink.exe from the PuTTY suite of tools, which must be installed separately.
Tips and tricks
Edit current file as root
Use the function below to open the current file as root:
(defun edit-current-file-as-root ()
"Edit the file that is associated with the current buffer as root"
(interactive)
(let ((filep (buffer-file-name)))
(if filep (find-file (concat "/sudo::" filep))
(message "Current buffer does not have an associated file."))))
Debugging
"Waiting for prompts from remote shell" message error
This problem (as many others) is due to a fancy shell prompt of the remote host that Tramp doesn't understand.
Try setting a normal one
set PS1="> "
and try again.
You could also change the prompt regexp that Tramp understands (M-x customize-variable RET tramp-terminal-prompt-regexp) but that is discouraged, or change the host prompt depending on the connection type (Tramp terminal shall be 'dumb', check the variable tramp-terminal-type):
case "$TERM" in
"dumb")
PS1="> "
;;
esac
See the original Stack Overflow answer.