更好的 TRAMP 自动登陆的方法
介绍
如果你不知道TRAMP,那么我告诉你,TRAMP是Emacs的杀手级应用程序之一。它是一个包,允许通过各种协议与远程系统交互。
这些交互包括打开shell和浏览远程文件树,就好像它们挂载在本地一样。 你甚至可以透明地在几台机器之间跳转(这种行为叫做 multi-hops)。
但是有一件事可以破坏这些无缝交互:登录提示。
Authinfo 的解决方案
为了消除登陆提示,emacs通过 auth-source
包来为Gnus Authinfo和.netrc 提供了原生支持:
(require 'dash) (use-package auth-source :demand :no-require t :config (setq auth-sources (-filter #'file-exists-p '("~/.authinfo.gpg" "~/.authinfo" "~/.netrc"))))
Now you can just create a ~/.authinfo
like this:
现在你可以创建一个 ~/.authinfo
文件,就像这样的:
machine raspi login pi password raspberry
然后执行 C-x f /ssh:pi@raspi:/
,它就会自动连接了,耶!
…只是,这种方法慢死了。
使用SSH密钥来解决
事实上密码登陆太慢了。消耗大把时间。当有大量的远程主机需要连接时更是如此。
SSH密钥(又名身份文件、证书)是一种更智能(而且在大多数情况下更安全)的处理方式。
如果你有一个主密钥来连接你所有的机器,只需进入 ~/.ssh/config
填入下面内容:
Host * User eigen IdentityFile ~/.ssh/eigen-identity
然后你就可以连接到任何服务器了,对于用户 eigen
都会使用指定的密钥。
疯狂的尝试(使用elisp搞定所有事情)
另一个跨平台的解决方案是用纯elisp来实现的。
这里的技巧是使用与identity file选项(-i
)对应的额外参数来对 tramp-methods
进行补充。
因此,我们需要一些工具来更改那些方法定义。
;; ------------------------------------------------------------------------ ;; DEPS (require 'tramp) (require 'dash) ;; ------------------------------------------------------------------------ ;; TRAMP METHODS ARGS (defun prf/tramp/method/def/some-args/with-cert (some-args cert-arg cert) "Returns enriched tramp def SOME-ARGS with certificate arg. SOME-ARGS can be of type `tramp-login-args' or `tramp-copy-args'" (let ((args-type (car some-args)) (args (car (cdr some-args)))) (add-to-list 'args `(,cert-arg ,(concat """ cert """))) `(,args-type ,args))) (defun prf/tramp/method/def/with-cert-in-some-args (tramp-method-def args-type cert-arg cert) "Returns copy of TRAMP-METHOD-DEF with certificate arg added to ARGS-TYPE. ARGS-TYPE can be `tramp-login-args' or `tramp-copy-args'." (let ((method-name (car tramp-method-def)) (method-def-args (cdr tramp-method-def))) (cons method-name (-map-when (lambda (e) (equal (car e) args-type)) (lambda (e) (prf/tramp/method/def/args/with-cert e cert-arg cert)) method-def-args)))) ;; ------------------------------------------------------------------------ ;; TRAMP METHODS (defun prf/tramp/method/def/with-cert-in-args (tramp-method-def cert-arg cert) "Returns copy of TRAMP-METHOD-DEF enriched with certificate arg. Certificate arg gets added to both 'tramp-login-args and 'tramp-copy-args." (-> tramp-method-def (prf/tramp/method/def/with-cert-in-some-args 'tramp-login-args cert-arg cert) (prf/tramp/method/def/with-cert-in-some-args 'tramp-copy-args cert-arg cert)))
然后我们可以覆盖方法定义:
;; PuTTY (let ((cert-path "~/my-cert.ppk") (putty-methods '("pscp" "plink" "plinkx" "psftp"))) (setq tramp-methods (-map-when (lambda (e) (member (car e) putty-methods)) (lambda (e) (prf/tramp/method/def/with-cert-in-args e "-i" cert-path)) tramp-methods))) ;; SSH (let ((cert-path "~/.ssh/id_dsa") (ssh-methods '("ssh" "sshx"))) (setq tramp-methods (-map-when (lambda (e) (member (car e) ssh-methods)) (lambda (e) (prf/tramp/method/def/with-cert-in-args e "-i" cert-path)) tramp-methods)))
这样做的好处是,如果远程主机不知道你的密钥,它仍然会提示你输入密码而不会失败。
代码可以在prf-tramp-method包中找到。