> Make it foolproof by putting it at the very top of your .zshrc and adding a return to ensure that nothing later in your .zshrc re-enables PS1:
> [[ $TERM == "dumb" ]] && unsetopt zle && PS1='$ ' && return
TRAMP (Transparent Remote Access, Multiple Protocols) is a package for editing remote files, similar to AngeFtp or efs. Whereas the others use FTP to connect to the remote host and to transfer the files, TRAMP uses a remote shell connection (rlogin, telnet, ssh). It can transfer the files using rcp or a similar program, or it can encode the file contents (using uuencode or base64) and transfer them right through the shell connection.
Tramp was formerly called RCP or rcp.el.
It allows you transparent access to files on remote access. “Transparent” means that usually the user doesn’t have to worry about anything. All that changes is the filename convention to indicate that the file resides on a remote system.
A good alternative to Tramp that doesn’t do anything at the Emacs level is sshfs. Sshfs allows mounting on the fly a remote filesystem via ssh on a local mount point and to copy from it (see https://wiki.archlinux.org/index.php/Sshfs). It could be as simple (under emacs): ‘sshfs host: localmountpoint’ or, if username, id and gid are different as complex as ‘sshfs usernameathost@host: localmountpoint -o idmapfile,uidfile=uid,gidfile=gid’.
TrampMode is a part of Emacs starting with version 22.1.
You can get it from here:
Faster than the default scp
(setq tramp-default-method "ssh")
For GNU Emacs
C-x C-f /remotehost:filename RET (or /method:user@remotehost:filename)
XEmacs use the syntax
C-x C-f /[method/user@remotehost]/filename
You can also edit local files as root with either of the following (note the double colon, which is required)
C-x C-f /su::/etc/hosts C-x C-f /sudo::/etc/hosts
<fsbot>  emacs syntax: /<user>@<host>:/path/to/file or /<protocol>:<user>@<host>:/path/to/file, <fsbot>  xemacs syntax: /[<protocol>/<user>@<host>]/path/to/file or /<user>@<host>]/path/to/file, <fsbot>  /su::/etc/hosts to edit /etc/hosts as root, <fsbot>  note double : when using su to be root
If you do something like this
C-x C-f /sudo::/etc/sysconfig/iptables
with a default install of Tramp (well the one bundled with Emacs23) and have SELinux enabled then Tramp will overwrite the SELinux context with “user_u:object_r:tmp_t” from whatever it was. In the case of iptables having a system context it will prevent your firewall from restarting!
This is likely to be due to intermediate tmp files (guessing here) with the Tramp/sudo interaction. Not sure how one might configure around this.
If you’re wondering why tramp just hangs then check that ssh hasn’t just suddenly died. This may be due to pppd, routers or whatever. In any case neither ssh on the client nor sshd on the server notice that the connection has disappeared. When the next command is sent, however, ssh notices that the line has been dropped and exits. And now you have a problem - however, just hitting C-g and then attempting the save/get/whatever operation again should just work (until the next time ssh is dropped).
Another thing that can cause tramp to hang (I saw this with Solaris at the remote end) is using an ancient /bin/sh as the remote shell. Switching to bash fixed it.
I had a hang when I saw “Sending the Perl
‘mime-encode’ implementations.” Setting my default method to “scp” fixed it (though now it’s slower).
If Tramp hangs with Solaris at the local end, try using “scpx” as your default tramp method. Also check that the hostname you are invoking Tramp with, matches what is in the
~/.ssh/known_hosts file; e.g. if the known_hosts file specifies the host with an IP, use an IP in the Tramp invocation.
If you’re using SVN or DARCS (or likely other things) with VC, see below for problem descriptions.
If you are a victim of the following:
tramp: Waiting for remote host to process data...
It could be a problem with sending large chunks to the remote host. Please type
C-h v tramp-chunksize RET and follow the instructions shown there.
You could also
(setq tramp-chunksize 500) to see if that helps.
If you use zsh and Tramp hangs every time you try to connect, try placing this in your .zshrc:
[[ $TERM == "dumb" ]] && unsetopt zle && PS1='$ '
Make it foolproof by putting it at the very top of your .zshrc and adding a return to ensure that nothing later in your .zshrc re-enables PS1:
[[ $TERM == "dumb" ]] && unsetopt zle && PS1='$ ' && return
Alternatively, I had success using the following in my .zshrc:
I’ve noticed that preexec and precmd call also be noxious if they do fancy stuff. I’ve ended up with:
if [[ "$TERM" == "dumb" ]] then unsetopt zle unsetopt prompt_cr unsetopt prompt_subst unfunction precmd unfunction preexec PS1='$ ' fi
None of the above worked for me so I decided to just change the SHELL environment variable. There is no added benefit from running zsh inside tramp anyway.
(eval-after-load 'tramp '(setenv "SHELL" "/bin/bash"))
To connect to a very old system I had to switch the remote, default LANG to a non-utf8 one (in
/etc/sysconfig/i18n) Otherwise tramp would hang right after sending
exec /bin/sh. Tracing showed any utf8 LANG to somehow output extra CRs characters, causing tramp to wait the prompt forever. This could be locale bug.
If you have Control-j mapped in your
~/.inputrc to something e.g. like this:
it can cause tramp to never finish recognizing the shell prompt.
If you are using a customised prompt in your shell, tramp can hang if it doesn’t recognise the remote shell prompt. The obvious symptom is that tramp hangs with the message “Waiting for prompts from remote shell”, but it can also hang or freeze up after this, before successfully opening the requested file.
To detect the remote prompt, tramp first tries the variable shell-prompt-pattern; if that fails, it tries tramp-shell-prompt pattern. You should try modifying tramp-shell-prompt-pattern first.
The default for tramp-shell-prompt-pattern in some recent tramps is:
\\(?:^\\|\r\\)[^]#$%>\n]*#?#$%>] *\\(^[\\[[0-9;]*[a-zA-Z] *\\)*"
(Note that the ^[ is a real control-[, and the \r may be a control-m.)
My system (NixOS?) recently made fancy coloured prompts the default. An ANSI escape sequence immediately follows the $, which breaks the default expression. Adding
.* to tramp-shell-prompt-pattern is an easy fix:
\\(?:^\\|\r\\)[^]#$%>\n]*#?#$%>].* *\\(^[\\[[0-9;]*[a-zA-Z] *\\)*"
Note that some of the Tips and tricks below still refer to the old
multi: syntax, which was removed in Emacs 23 (in Emacs 23 you must configure proxies manually to facilitate multi-hops).
As of Emacs 24.3, an analog of the old
multi: 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-h i g (tramp) Ad-hoc multi-hops RET
With the new syntax, each ‘hop’ is separated by
|. The example in the manual is:
C-x C-f /ssh:bird@bastion|ssh:you@remotehost:/path
Which connects firstly as
bird@bastion, and from there to
You can also use this syntax to sudo/su to root (or of course any other user) on a remote host:
C-x C-f /ssh:you@remotehost|sudo:remotehost:/path/to/file RET
Important: be sure to specify the hostname explicitly:
sudo:remotehost: rather than
sudo:: (see below).
As this still uses the proxy mechanism underneath,
‘tramp-default-proxies-alist’ should now include the value
("remotehost" "root" "/ssh:you@remotehost:")
Meaning that the proxy
/ssh:you@remotehost: is going to be used whenever you request a file as
root is the default user for these methods, but you can of course also change to a non-root user with:
C-x C-f /ssh:you@remotehost|sudo:them@remotehost:/path/to/file RET
You are probably used to using
su:: and omitting the hostname. If you are staying on the localhost then this is still fine, but if you are hopping to a remote server then you must specify the hostname for every hop – even if it is the same as for the previous hop. Always use
su:hostname: with remote hosts.
The trap here is that
sudo:: does actually appear to work – however when you do that the HOST for the dynamic proxy entry will be the hostname you originated from rather than the host you connected to. This will not only look confusing (as the wrong host will be displayed in the file paths), but it will also mean that any subsequent attempt to use
sudo:: on your localhost will instead be proxied to the remote server! (and the proxy would also presumably be clobbered if you did the same thing on a second server, causing further issues).
In short, don’t use
:: when you multi-hop!
C-x C-f /su::/etc/hosts RET
Please note the double :
One lazy afternoon, one “sudo vi foo” too many (or rather “udo vi foo”, while my term was blocked because of the stupid ^S handling), I came up with this and was, subsequently, happy:
It may be worth knowing that the sudo method and tail.el doesn’t get along. At least on bkhl’s machine, opening stuff with /sudo: wont work if tail.el is loaded.
(defvar find-file-root-prefix (if (featurep 'xemacs) "/[sudo/root@localhost]" "/sudo:root@localhost:" ) "*The filename prefix used to open a file with `find-file-root'.") (defvar find-file-root-history nil "History list for files found using `find-file-root'.") (defvar find-file-root-hook nil "Normal hook for functions to run after finding a \"root\" file.") (defun find-file-root () "*Open a file as the root user. Prepends `find-file-root-prefix' to the selected file name so that it maybe accessed via the corresponding tramp method." (interactive) (require 'tramp) (let* ( ;; We bind the variable `file-name-history' locally so we can ;; use a separate history list for "root" files. (file-name-history find-file-root-history) (name (or buffer-file-name default-directory)) (tramp (and (tramp-tramp-file-p name) (tramp-dissect-file-name name))) path dir file) ;; If called from a "root" file, we need to fix up the path. (when tramp (setq path (tramp-file-name-localname tramp) dir (file-name-directory path))) (when (setq file (read-file-name "Find file (UID = 0): " dir path)) (find-file (concat find-file-root-prefix file)) ;; If this all succeeded save our new history list. (setq find-file-root-history file-name-history) ;; allow some user customization (run-hooks 'find-file-root-hook)))) (global-set-key [(control x) (control r)] 'find-file-root)
This rebinds C-x C-r. I don’t have any use for find-file-read-only, so I guess that’s the closest to C-x C-f you can come, QWERTY-keymap-wise. (-; --AndreasFuchs
You’ll be pleased to note that it’s good Dvorak-wise too :D --ErikBourget
Great stuff Andreas! I edited the above suggestion to improve the handling of history list and added a “find-file-root-hook”. The latter is very useful for doing some system file specific things. For example, the following can help to discourage careless editing of system files:
(defface find-file-root-header-face '((t (:foreground "white" :background "red3"))) "*Face use to display header-lines for files opened as root.") (defun find-file-root-header-warning () "*Display a warning in header line of the current buffer. This function is suitable to add to `find-file-root-hook'." (let* ((warning "WARNING: EDITING FILE AS ROOT!") (space (+ 6 (- (window-width) (length warning)))) (bracket (make-string (/ space 2) ?-)) (warning (concat bracket warning bracket))) (setq header-line-format (propertize warning 'face 'find-file-root-header-face)))) (add-hook 'find-file-root-hook 'find-file-root-header-warning)
(defun find-file-hook-root-header-warning () (when (and buffer-file-name (string-match "root@localhost" buffer-file-name)) (find-file-root-header-warning))) (add-hook 'find-file-hook 'find-file-hook-root-header-warning)
Using find-file-hook is better, I think. – rubikitch
The code above depends on function
tramp-file-name-path, which appears to me not to be defined anywhere in the current release of TRAMP (2.1.13) nor in any of four random earlier releases I downloaded and checked. No luck on google (some usages, no definition), koders or krugle either.
tramp-file-name-path has been replaced by
tramp-file-name-localname in CVS on 2003-02-15. I updated the above snippets. From the commit message:
‘localname’ unless it is used for a search path. In GNU, the word
‘path’ is reserved for search paths.[…]
And the following can help us maintain a record of any changes we make to system files:
(defvar find-file-root-log "~/system/root-log" "*ChangeLog in which to log changes to system files.") (defun find-file-root-log-do-it() "Add an entry for the current buffer to `find-file-root-log'." (let ((add-log-mailing-address "root@localhost") (add-log-full-name "") (add-log-file-name-function 'identity) (add-log-buffer-file-name-function (lambda () ;; strip tramp prefix (tramp-file-name-localname (tramp-dissect-file-name (or buffer-file-name default-directory))) ))) (add-change-log-entry nil find-file-root-log 'other-window))) (defun find-file-root-log-on-save () "*Prompt for a log entry in `find-file-root-log' after saving a root file. This function is suitable to add to `find-file-root-hook'." (add-hook 'after-save-hook 'find-file-root-log-do-it 'append 'local)) (add-hook 'find-file-root-hook 'find-file-root-log-on-save)
Or we may just have some personal preferences:
(defun my-find-file-root-hook () "Some personal preferences." ;; Turn auto save off and simplify backups (my version of tramp ;; barfs unless I do this:-) (setq buffer-auto-save-file-name nil) (set (make-local-variable 'backup-by-copying) nil) (set (make-local-variable 'backup-directory-alist) '((".")))) (add-hook 'find-file-root-hook 'my-find-file-root-hook)
I often view or edit file remotely and extended the above procedure to handle files already open with tramp. The code is a bit ugly but it is working. It is meant to replace toggle-read-only function. I have only tested it on Emacs.
(defun really-toggle-read-only (&optional force) "Change whether this buffer is visiting its file read-only by really trying to acquire the rights with sudo (and tramp)" (interactive "P") (let* ((currentfilename buffer-file-name) (newfilename ;; We first check that the buffer is linked to a file (if (not currentfilename) ;; If not, we just toggle the read-only mark nil ;; What is the current state (if buffer-read-only ;; The buffer is read-only, we should acquire rights to edit it (if (and (not force) (file-writable-p currentfilename)) ;; The file is writable, we don't need to acquire rights nil (if (buffer-modified-p) (error "Buffer is read-only and has been modified. Don't know what to do.") ;; To acquire rights, we need to use sudo ;; Do we have a tramp file name ? (if (eq (string-match tramp-file-name-regexp currentfilename) 0) ;; Yes, we add sudo to it (let* ((v (tramp-dissect-file-name currentfilename)) (l (tramp-file-name-localname v))) (if (or (string= "sudo" (let ((m (tramp-file-name-method v))) (if (not (stringp m)) (car (last (append m nil))) m))) (eq (string-match "^sudo::" l) 0)) (error "This file is already opened with sudo") ;; We add sudo (let ((toarray (lambda (a) (if (and (not (stringp a)) (arrayp a)) a (vector a))))) (tramp-make-tramp-file-name "multi" (vconcat (apply toarray (list (tramp-file-name-method v))) ["sudo"]) (vconcat (apply toarray (list (tramp-file-name-user v))) ["root"]) (vconcat (apply toarray (list (tramp-file-name-host v))) ["localhost"]) l)))) ;; It is not a tramp file-name (tramp-make-tramp-file-name nil "sudo" nil "" currentfilename)))) ;; The buffer is not read-only, we must drop rights (if (buffer-modified-p) (error "Buffer is modified, save it first first.") (if (eq (string-match tramp-file-name-regexp currentfilename) 0) ;; We should remove sudo (let* ((v (tramp-dissect-file-name currentfilename)) (l (tramp-file-name-localname v)) (m (tramp-file-name-method v))) ;; Two cases, either sudo is in local file name part or in the methods (if (eq (string-match "^sudo::" l) 0) ;; Necessary, we have a multi (otherwise, sudo would not have been ;; in the localname) ;; Do we have more than one method left ? (if (> (length m) 1) ;; Yes, still multi (tramp-make-tramp-file-name "multi" m (tramp-file-name-user v) (tramp-file-name-host v) (progn (string-match "^sudo::\\(.*\\)$" l) (match-string 1 l))) ;; We don't need multi anymore (tramp-make-tramp-file-name nil (car (append m nil)) (car (append (tramp-file-name-user v) nil)) (car (append (tramp-file-name-host v) nil)) (progn (string-match "^sudo::\\(.*\\)$" l) (match-string 1 l)))) ;; sudo should be in the methods (if (and (stringp m) (string= m "sudo")) l (if (and (not (stringp m)) (string= (car (last (append m nil))) "sudo")) ;; Do we still need multi ? (if (> (length m) 2) (tramp-make-tramp-file-name "multi" (apply 'vector (butlast (append m nil))) (apply 'vector (butlast (append (tramp-file-name-user v) nil))) (apply 'vector (butlast (append (tramp-file-name-host v) nil))) l) (tramp-make-tramp-file-name nil (car (append m nil)) (car (append (tramp-file-name-user v) nil)) (car (append (tramp-file-name-host v) nil)) l)) ;; No sudo found nil)))) ;; This is not a tramp file nil)))))) (if newfilename (find-alternate-file newfilename) (toggle-read-only))))
There are some bugs: for example, you need to always use the former user@host (and not just host). This is because tramp-make-tramp-file-name with multi as the first paremeter does not accept nil as one of the member of the user vector.
I use ido, it’s very handy. So I always open the file use ido-find-file and then open it with TRAMP:
(defun find-alternative-file-with-sudo () (interactive) (when buffer-file-name (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name)))) (global-set-key (kbd "C-x C-r") 'find-alternative-file-with-sudo)
I really like the above. It doesn’t work when you run it more than once on a buffer, so made it toggle. Also it works on dired buffers.
(defun find-alternative-file-with-sudo () (interactive) (let ((fname (or buffer-file-name dired-directory))) (when fname (if (string-match "^/sudo:root@localhost:" fname) (setq fname (replace-regexp-in-string "^/sudo:root@localhost:" "" fname)) (setq fname (concat "/sudo:root@localhost:" fname))) (find-alternate-file fname))))
To get this to work, here are some of the things I noticed,
With putty, this finally seems to work.
vbscript way to launch emacs from a shortcut (don’t need to be in cygwin prompt or putty) and still work:
WScript.CreateObject("WScript.Shell").Run "c:\cygwin\bin\bash -l -c /usr/local/emacs/22.2/bin/emacs", 0, false
One fair warning is that it may not work with every env. I have an office notebook that wonÃ¢ÂÂt work with the above method. However, that is because it also wonÃ¢ÂÂt work even if I start emacs from cygwin command prompt. It must be that particular cygwin installation that is causing the problem. YMMV – WeyHan?
Could both recipes be made clearer? What is meant by “you have to create your keys and stuff” and “put them in memory”? What is puttygen and how to use it? How to start paegant and load keys? – DrewAdams
I tried using the nqmacs build (21.3.50, from 2004/07/26) on Windows XP, which apparently uses Tramp, not ange-ftp, by default. I wasn’t successful connecting to Linux with Tramp. Advice on what to check (at both ends: Linux and Windows)? I tried with
‘tramp-default-method’ as “ssh” and as “sshx”. I tried starting Emacs from a Cygwin shell also. – DrewAdams
The following commands, from the cygwin shell, have worked for me with ntemacs-21.2, winXP-SP2, tramp-2.1.3:
$ eval `ssh-agent` $ ssh-add $ (/cygdrive/c/emacs-21.2/bin/emacs &)
The most common problem with ntemacs and cygwins openssh is the following: “Pseudo-terminal will not be allocated because stdin is not a terminal.” This is solved by adding:
(setq tramp-default-method "ssh") (nconc (cadr (assq 'tramp-login-args (assoc "ssh" tramp-methods))) '(("bash" "-i"))) (setcdr (assq 'tramp-remote-sh (assoc "ssh" tramp-methods)) '("bash -i"))
The above also helped me solve that /bin/sh doesn’t expand tilde (~) correctly in Solaris. Either set it to bash like above (which might or might not be installed), or ksh. – HenrikHolmboe?
Getting tramp to work on windows 2000 was a pain! So, I wrote a tutorial. Hope it helps.
FWIW, here is my Windows shortcut target for launching Emacs via Cygwin, and having it inherit Cygwin’s environment variables. %APPDATA% is the Windows equivalent of $HOME, and is where NTEmacs would look for .emacs etc by default when launching outside of cygwin, so this keeps things consistent.
C:\cygwin\bin\bash.exe --login -c "env HOME=\"`cygpath '%APPDATA%'`\" /cygdrive/c/emacs/emacs-23.1/bin/runemacs.exe"
If your cygwin bash profile manages your ssh-agent for you, then this approach makes TRAMP via the sshx method pretty seamless.
Tramp-mode can be made to operate within the cygwin/X environment as an alternative to NTEmacs. In this approach, emacs is installed as a cygwin package and can be run in the cmd bash shell, rxvt, or under X-windows. In order for tramp-mode to function, the following should be added to your .emacs file:
;; tramp support (add-to-list 'load-path "/usr/local/share/emacs/site-lisp/") (require 'tramp) (setq tramp-default-method "sshx")
This was tested on Windows XP using:
GNU Emacs 21.2.1 (i686-pc-cygwin, X toolkit) of 2004-03-23 on cm-test CYGWIN_NT-5.1 diogenes 1.5.19(0.150/4/2) 2006-01-20 13:28 i686 Cygwin
I’m trying to use tramp on a Windows box to connect to an AIX machine (“porco”) via telnet because I can’t install ssh on porco, and I’m having to use “plink -telnet” because the default telnet client is broken - both “telnet” and “plink -telnet” work when I run them in DOS or 4NT windows, but “telnet” exits immediately when invoked inside a “M-x shell” buffer…
This is a log from an M-x shell buffer, with hostnames and usernames changed to protect me from sysadmin paranoia:
[c:\edrx\edrx]plink -telnet porco
AIX Version 4 (C) Copyrights by IBM and by others 1982, 1996. login: aixuser aixuser's Password: ***************************************************************************** * * * Welcome to AIX Version 4.3! * * * * Please see the README file in /usr/lpp/bos for information pertinent to * * this release of the AIX Operating System. * * * ***************************************************************************** Last unsuccessful login: Mon Dec 12 19:12:33 GRNLNDST 2005 on /dev/pts/2 from bla.bla.net.br Last login: Tue Dec 13 15:56:18 GRNLNDST 2005 on /dev/pts/36 from 10.0.0.22
Sending nohup output to nohup.out. $ echo $SHELL /bin/ksh $ /us1/ston/pro/edrx/usrc/bash-3.0/bash bash-3.00$
Shouldn’t the code below work? Am I missing something obvious?
(require 'tramp) (setq tramp-verbose 10) (setq tramp-default-method "plinkt") (setq tramp-debug-buffer t) (add-to-alist 'tramp-methods '("plinkt" (tramp-connection-function tramp-open-connection-telnet) (tramp-login-program "plink") (tramp-copy-program nil) ;; (tramp-remote-sh "/bin/sh") (tramp-remote-sh "/us1/ston/pro/edrx/usrc/bash-3.0/bash") (tramp-login-args ("-telnet")) (tramp-copy-args nil) (tramp-copy-keep-date-arg nil) (tramp-password-end-of-line "xy"))) (find-file "/aixuser@porco:/us1/")
The output in the buffer *tramp/plink aixuser@porco* is terribly brief: just
FATAL ERROR: Network error: Connection refused
Process *tramp/plink aixuser@porco* exited abnormally with code 1
Any hints on how to debug that? Thanks, cheers, EduardoOchs (2005-12-13)
By the way, I’m using nqmacs (“GNU Emacs 22.214.171.124 (i386-mingw-nt5.0.2195) of 2005-06-26”) on Windows 2000…
I get the plinkt work with 126.96.36.199 on windows XP. My configuration is almost the same as yours except: 1, (tramp-login-args ((”-telnet”) (”%h”))); 2, I didn’t configure tramp-password-end-of-line. – lgfang
Say I can ssh to node ‘secret’ only from ‘remote’, I’d use:
Can I set TrampMode up so that a method like:
would access the same file in the same manner? I.e., can I set it up to use an abbreviated path? – Dirk
This works in debian lenny (2009), which comes with emacs 22.2 and tramp 2.0.55:
/multi:ssh:me@localhost:ssh:other@localhost: # gets me to dired on other /multi:ssh:me@foo:ssh:me@bar:sudo:me@localhost: # edits
It is awesome!
Multi-hops seems like an obsolete format. The current documentation (May 2005) says stuff about proxies.
First set up a proxy triplet:
; host + user > proxy (add-to-list ‘tramp-default-proxies-alist ‘(”
’” nil “/ssh:proxy
Then use as normal:
C-x C-f /hidden.firewalled.site.edu:
I am also interested in being able to use prefixes/abbrebiations as Dirk asked. So I raise this question again in order to let this page pop up in RecentChanges, so that smart people will notice it ;-) – Jurijs Oniscuks
One way of doing this would be to define your own function to add to
‘FILE-NAME-HANDLER-ALIST’, to be invoked instead of tramp:
(defvar my-tramp-abbrevs '(("secret" . "some-long-method") ("host2" . "some-other-method"))) (defun my-file-name-handler (filename &rest rest) (setq filename (catch 'done (loop for (abbrev . name) in my-tramp-abbrevs if (string= abbrev (something-to-extract-filename)) (throw 'done (substitute-abbrev-with-full-name))) (throw 'done filename))) (let ((file-name-handler-alist (cdr file-name-handler-alist))) (find-file filename)))
This is rather rough, and most probably needs some serious testing, since it’s done without recourse to an Emacs installation.
Basically, you add your own handler to the front of file-name-handler-alist, then, check the filename to see if it matches one of the abbreviations you’ve defined. If yes, the abbreviation is substituted. Then, we reinvoke find-file, and let the other file-name-handlers kick in. – LawrenceMitchell
By the way, it might be worth asking on the tramp list to see if anyone else has a fully-fledged, and working, abbreviation scheme.
Here’s a method proposed by bojohan on #emacs, that involves using environment variables:
(setenv "SECRET" "/ssh:firstname.lastname@example.org:")
Then you only need to load:
I find using a bookmark works quite well: just open a frequently accessed file/directory using tramp and type C-x r m. Then you can give it as short a name as you like. See BookMarks for more details. --EmorySmith?
Why is multi:… an obsolete format? Was it deemed too easy or something? Why should I have to set up a proxy variable just to open a file once? I understand the desire to add more features (and the proxy thing looks like a useful feature) but not at the expense of existing simplicity.
I hope there’s a sensible explanation. I would love to be pointed to a logical explanation of why trying to open /multi:ssh:foo:ssh:bar: will cause the heat death of the universe but I fear there may be no such thing.
I get this in Subversion Output:
svn: '/sudo:root@localhost:/home/elements' is not a working copy
apply: Error running Subversion to check status of `shadow'
And in my .emacs I have:
(add-to-list 'vc-handled-backends 'SVN)
If you don’t need to use vc-svn at all - i use psvn (http://www.xsteve.at/prg/vc_svn/) exclusively - here’s a quick fix to effectively disable vc-svn entirely so that you can edit files with tramp/sudo.
Find the function
‘vc-svn-registered’ in vc-svn.el (should be around line 112) and replace it with the following:
;; hack to disable vc-svn (defun vc-svn-registered (file) nil)
I use this in my .emacs to disable vc-svn on files accessed with tramp:
(defadvice vc-svn-registered (around my-vc-svn-registered-tramp activate) "Don't try to use SVN on files accessed via TRAMP." (if (and (fboundp 'tramp-tramp-file-p) (tramp-tramp-file-p (ad-get-arg 0))) nil ad-do-it))
This is a similar advice for DVC mode (thanks to folks at ru_emacs):
(defadvice dvc-current-active-dvc (around dvc-current-active-dvc-no-tramp activate) "Don't try to use DVC on files accessed via TRAMP." (if (and (fboundp 'tramp-tramp-file-p) (tramp-tramp-file-p (dvc-uniquify-file-name default-directory))) nil ad-do-it))
Editing files not under DARCS version control via TRAMP doesn’t work when using Jorgen SchÃÂ¤fer’s vc-darcs.el v1.3 or earlier, please upgrade to 1.4. See VcDarcs
I guess the simplest way would be a hook, but I can’t figure out what the name of the Tramp hook is. tramp-mode-hook doesn’t seem to work – bkhl
try here: http://www.gnu.org/software/tramp/#Auto_002dsave-and-Backup --EmorySmith?
how about just overwriting tramp-auto-save ? – Gyom
(require 'tramp) (defun tramp-set-auto-save () (auto-save-mode -1))
(require 'tramp) (setq tramp-debug-buffer t) (setq tramp-verbose 10)
‘How to Customize Traces’ in the TRAMP info manual (
‘C-h i’). The tramp-debug-buffer variable seems to be missing and, I guess, deprecated in GNU Emacs 23.
Use the self-described “kludgy” hostname (see documentation for tramp-open-connection-rsh function):
C-x C-f /ssh:test@host#2222:/tmp
The kludge does not work with plink (at least with plink v.0.60 and tramp coming with emacs 22.2.1), since tramp uses the hard-coded argument -p to specify the port, while plink wants -P (upper case). Need to introduce a customizable variable to this end.
If you are using editing files remotely on CVS, and that CVS server is itself a remote machine requiring passphrase via ssh, try this trick. Add “-A” to your argument list for ssh. “-A” will forward your SSH keys to the remote machine (say remotemachine1), which can then use those keys for the authentication to the remote CVS server (say remotemachine2). Check this from the command line first:
$ ssh -A remotemachine1 $ cd <to-working-checkout-using-remotemachine2-as-repository> $ cvs log file
If this is working, you should not be prompted for a passphrase. (You will need to ensure your SSH key on your local machine is also on the remote CVS server remotemachine2).
To setup TRAMP to use these options: use “M-x customize-option tramp-methods”, then insert a “-A” in “ssh” in the “tramp-login-args” just before “-e” and “none”.
A simpler solution if you don’t mind all of your SSH commands forwarding the SSH keys (this has security implications, so be careful), is to add:
(Tested with Emacs from CVS 22.0.50 and Tramp 2.0.47).
Because tramp uses plink to login with all putty variants, and ssh to login with all openssh variants, its not possible to use psftp or sftp connection using Tramp. There’s not a way to override the tramp-login-program aspect of the alist tramp-methods. Unfortunately, nothing’s changed since 2004. Tramp can only do SFTP over SSH, and AngeFtp doesn’t currently support SFTP, and with no plans to handle it, since Tramp supports SFTP over SSH.
This is problematic with hosting accounts where access is only via sftp… other protocols (such as ssh) are disabled.
Does anyone have a working configuration that combines tramp and archive-mode? I can open the remote archive but when I try to open a file within the archive I get:
byte-code: Opening output file: no such file or directory, c:/archive.tmp4324x-f/arc-mode.4324xFU
This is using the following config:
; tramp ;(setq archive-tmpdir "/temp") (setq temporary-file-directory "/") ;(prefer-coding-system 'utf-8-unix) ;(add-untranslated-filesystem "/sshx:") (add-to-list 'load-path "~/src/emacs/tramp-2.1.14/lisp/") ;(setq vc-handled-backends nil) (require 'tramp) (setq tramp-default-method "scpwrapper") ; for tramp 2.2.14: (add-to-list 'tramp-methods '("scpwrapper" (tramp-login-program "ssh") (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p") ("-q") ("-e" "none" "-t" "-t" "/bin/sh"))) (tramp-remote-sh "/bin/sh") (tramp-copy-program "scpwrapper") (tramp-copy-args (("-p" "%k"))) (tramp-copy-keep-date t) (tramp-password-end-of-line nil) (tramp-gw-args (("-o" "GlobalKnownHostsFile=/dev/null") ("-o" "UserKnownHostsFile=/dev/null") ("-o" "StrictHostKeyChecking=no"))) (tramp-default-port 22)))
scpwrapper is just a script that converts arguments of the form
Fixed to make this question Windows/Cygwin-specific - in GNU Emacs 24.2, I can view /ssh:…:….zip (and also .tar.gz, which isn’t archive-mode) files, and view files inside them, out-of-the-box with no configuration, and I think this has been the case for some time. – DavidOShea
One of the neat things about using TRAMP via a remote shell, is that emacs will then automatically invoke other remote shell commands directly on that server. e.g. When viewing a remote file, try
M-x rgrep, etc…
I find the following shortcuts to be highly useful for quickly editing files as root; esp via emacsclient (i.e. as an alternative to sudo vi)
(eval-after-load "tramp" '(progn (defvar sudo-tramp-prefix "/sudo::" (concat "Prefix to be used by sudo commands when building tramp path ")) (defun sudo-file-name (filename) (concat sudo-tramp-prefix filename)) (defun sudo-find-file (filename &optional wildcards) "Calls find-file with filename with sudo-tramp-prefix prepended" (interactive "fFind file with sudo ") (let ((sudo-name (sudo-file-name filename))) (apply 'find-file (cons sudo-name (if (boundp 'wildcards) '(wildcards)))))) (defun sudo-reopen-file () "Reopen file as root by prefixing its name with sudo-tramp-prefix and by clearing buffer-read-only" (interactive) (let* ((file-name (expand-file-name buffer-file-name)) (sudo-name (sudo-file-name file-name))) (progn (setq buffer-file-name sudo-name) (rename-buffer sudo-name) (setq buffer-read-only nil) (message (concat "Set file name to " sudo-name))))) (global-set-key "\C-x+" 'sudo-find-file) (global-set-key "\C-x!" 'sudo-reopen-file)))
I fixed Stefan’s example to make sudo work with local and remote files with the following:
(set-default 'tramp-default-proxies-alist (quote ((".*" "\\`root\\'" "/ssh:%h:")))) (eval-after-load "tramp" '(progn (defvar sudo-tramp-prefix "/sudo:" (concat "Prefix to be used by sudo commands when building tramp path ")) (defun sudo-file-name (filename) (set 'splitname (split-string filename ":")) (if (> (length splitname) 1) (progn (set 'final-split (cdr splitname)) (set 'sudo-tramp-prefix "/sudo:") ) (progn (set 'final-split splitname) (set 'sudo-tramp-prefix (concat sudo-tramp-prefix "root@localhost:"))) ) (set 'final-fn (concat sudo-tramp-prefix (mapconcat (lambda (e) e) final-split ":"))) (message "splitname is %s" splitname) (message "sudo-tramp-prefix is %s" sudo-tramp-prefix) (message "final-split is %s" final-split) (message "final-fn is %s" final-fn) (message "%s" final-fn) ) (defun sudo-find-file (filename &optional wildcards) "Calls find-file with filename with sudo-tramp-prefix prepended" (interactive "fFind file with sudo ") (let ((sudo-name (sudo-file-name filename))) (apply 'find-file (cons sudo-name (if (boundp 'wildcards) '(wildcards)))))) (defun sudo-reopen-file () "Reopen file as root by prefixing its name with sudo-tramp-prefix and by clearing buffer-read-only" (interactive) (let* ((file-name (expand-file-name buffer-file-name)) (sudo-name (sudo-file-name file-name))) (progn (setq buffer-file-name sudo-name) (rename-buffer sudo-name) (setq buffer-read-only nil) (message (concat "File name set to " sudo-name))))) ;;(global-set-key (kbd "C-c o") 'sudo-find-file) (global-set-key (kbd "C-c o s") 'sudo-reopen-file)))
— Chris Allen
A simple version of the ones above. Designed to allow you to reopen an existing file with sudo, without needing to navigate to it or loose your place in the file. Also works on local or remote files.
(set-default 'tramp-default-proxies-alist (quote ((".*" "\\`root\\'" "/ssh:%h:")))) (require 'tramp) (defun sudo-edit-current-file () (interactive) (let ((position (point))) (find-alternate-file (if (file-remote-p (buffer-file-name)) (let ((vec (tramp-dissect-file-name (buffer-file-name)))) (tramp-make-tramp-file-name "sudo" (tramp-file-name-user vec) (tramp-file-name-host vec) (tramp-file-name-localname vec))) (concat "/sudo:root@localhost:" (buffer-file-name)))) (goto-char position)))
— Russell Sim
Hi. I had trouble getting the above to work with my emacs 24.3 with this new multi syntax for tramp. Always got the “sudo is only for local file” error. I also wanted to press s-return in dired mode to open file using sudo. So here is the modified above code which works for me.
(defun sudo-edit-current-file () (interactive) (let ((my-file-name) ; fill this with the file to open (position)) ; if the file is already open save position (if (equal major-mode 'dired-mode) ; test if we are in dired-mode (progn (setq my-file-name (dired-get-file-for-visit)) (find-alternate-file (prepare-tramp-sudo-string my-file-name))) (setq my-file-name (buffer-file-name); hopefully anything else is an already opened file position (point)) (find-alternate-file (prepare-tramp-sudo-string my-file-name)) (goto-char position)))) (defun prepare-tramp-sudo-string (tempfile) (if (file-remote-p tempfile) (let ((vec (tramp-dissect-file-name tempfile))) (tramp-make-tramp-file-name "sudo" (tramp-file-name-user nil) (tramp-file-name-host vec) (tramp-file-name-localname vec) (format "ssh:%s@%s|" (tramp-file-name-user vec) (tramp-file-name-host vec)))) (concat "/sudo:root@localhost:" tempfile))) (define-key dired-mode-map [s-return] 'sudo-edit-current-file)
— Stefan Eichberger