Tramp 是 Emacs 中用来编辑远端文件的模块,全称为『Transparent Remote (file) Access, Multiple Protocol』,类似于 VSCode 的 Remote Development,只不过比它年长 20 岁而已😄。 这篇文章就来介绍下 tramp 的使用方式与注意事项。
使用方式
在使用 find-file
打开文件时,使用下面的语法,即可打开远端的文件:
|
|
比如, /ssh:[email protected]:/etc/hosts
即可通过 SSH 协议以 vagrant 用户登录 192.168.31.92 机器,并且打开 /etc/hosts
文件。
/ssh::
会连接到 localhost,一般用来测试 tramp 的功能。在 Windows 系统中,PuTTY 是一个常用的 SSH 客户端,需要用 plink 协议: /plink:user@host:/path/to/file
。
借助于 SSH 的功能,可以通过下面的配置来简化(免密码)tramp 的使用:
|
|
这样只需输入 /ssh:devhost:/etc/hosts
即可。通过配置 tramp 默认协议为 SSH,可以进一步简化为: /-:devhost:/etc/hosts
|
|
另外,也可以通过配置 directory-abbrev-alist,达到简化目的:
|
|
输入 /dev
后,按 TAB,即会自动打开 /-:dev:/etc
。
SSH ControlMaster
ControlMaster 是 SSH 进行多路复用的机制,这样用户只需要在第一次登录时需要输入密码信息,后续 SSH 登录同一主机时,会复用之前的 TCP 连接。
ControlMaster 的主要缺点是第一次建立连接的 SSH 会话必须一直保留着,如果 logout 这个主会话,其他的 SSH 会话则会“卡住”。也因为这个原因,tramp 使用 SSH 时,默认用 tramp-ssh-controlmaster-options
覆盖掉 SSH config 中 ControlMaster 的行为,默认值为:
|
|
没有进行持久化。如果想要使用 SSH config 中的配置,则需配置:
|
|
与其他模块结合
在 Emacs 中,shell.el、eshell.el、compile.el、gud.el(gdb)这几个内置模块都与 tramp 做了完美整合,执行相应命令时会通过相应协议在远端执行。
多级跳跃 multiple hops
出于安全考虑,公司会禁止开发同学直接登录生产机器,需要通过一跳板机来登录生产机器 ,这时就需要多次跳跃。tramp 支持通过下面的语法,级联登录多个机器
|
|
上面命令会先用 bird 用户登录堡垒机 bastion,之后再在堡垒机上以 admin 用户登录 production 打开 /path
。
如果要在多级跳跃时使用 ControlMaster,中转的机器需要配置如下:
|
|
以 sudo 方式打开文件
一般来说,登录远端机器时都是非 root 用户,有时会需要用 sudo 来打开某些文件,tramp 通过下面的语法支持这类操作:
|
|
sudo::
的方式在 Emacs 27 上运行没有问题,其他低版本可能需要输入完整的命令:
|
|
注意事项
Tramp 打开的远端文件和本地的文件没什么区别,会被记录在 backup、autosave、recentf 等中。在今后重启 Emacs 时,如果这时无法连接远端机器,Emacs 可能会卡住,这是因为 tramp 会对之前打开的文件进行检查,可以通过下面的一些配置来绕过 tramp,让 backup 等机制不对 tramp 打开的文件起作用:
|
|
如果用了 emacs-dashboard 来展示 project.el 中的项目,Emacs 启动时会检查这些项目,因此也需要跳过那些远端项目,不要持久化保存:
|
|
添加上面的配置后,还需要检查下之前是否已经有 tramp 的文件被记录,如有手动删除即可。
如果打开 Emacs 还是有卡顿的问题,可以通过调整 tramp-verbose 来进行调试:
|
|
设置之后再重启时,会在 *debug-tramp*
内打印出详细日志。下图堆栈为笔者调试因 project.el 卡住时的截图:
下面的堆栈是在调试 docker-tramp
导致的卡住问题时,通过开启 (toggle-debug-on-error)
后得到的:
|
|
file-truename
file-truename
作用在 tramp 打开的 buffer 上时,也会进行远程连接。笔者之前配置时,曾出现过下面这个错误信息:
|
|
主要原因就是在配置中使用了 file-truename
。
Docker/Vagrant
SSH 是 tramp 中常用的协议,除此之外,tramp 还支持非常多的协议,比如:ftp、smb、adb(连接 Android 手机)等,具体可参考文档:TRAMP Inline methods。社区内也有一些插件支持 Docker,Vagrant。use-package 配置如下:
|
|
vagrant-tramp 原作者貌似已经不维护了,有些小问题,笔者已经提交了 Pull Request,在作者合并前,读者可使用 fork 的版本。不仅单实例模式正常工作,在 Multi-Machine 模式下也没有问题。
Update:2022-06-27 上述 PR 已经合并