更好的 TRAMP 自动登陆的方法

发布于 2023-05-10 12:48:44 字数 4516 浏览 54 评论 0

如果你不知道 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 都会使用指定的密钥。

PuTTY 的困境

如果您使用的是 Windows,那么很有可能使用 PuTTY/plink 来代替 SSH。

TRAMP 也挺支持PuTTY的(通过 /pscp: 方法,这就是你所要的方法)。

PuTTY 通过 默认设置Pageant 提供了一种设置默认密钥的方法。

前一种方法只有当你将每台主机都保存为连接配置文件并使用 /plinkx:<PROFILE>: 来访问时才有效。

而后者似乎只有在启动 putty.exe(GUI 界面)时才会加载。

现在是疯狂冒险的时候了。

疯狂的尝试(使用 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包 中找到。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

歌入人心

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

eins

文章 0 评论 0

世界等同你

文章 0 评论 0

毒初莱肆砂笔

文章 0 评论 0

初雪

文章 0 评论 0

miao

文章 0 评论 0

qq_zQQHIW

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文