我喜欢 eshell 的 TRAMP 集成。有了它,我可以cd /ssh:foo:/etc
通过 ssh 进入远程机器并访问它的/etc/
目录。我也可以
find-file motd
在我的本地 emacs 中打开这个文件。但是,如果我需要使用 sudo 来更改文件怎么办?我知道我可以给出完整的路径,如下所示:
find-file /sudo:foo:/etc/motd
但是有没有办法通过 TRAMPs sudo 支持打开文件,而无需输入完整路径?
我设法想出了以下适用于我的 eshell 别名:
alias sff 'find-file "${pwd}/$1"(:s/ssh/sudo/)'
它的作用应该是相当明显的。它预先添加了工作目录路径,但字符串ssh
替换为sudo
. 因此它只适用于通过 ssh 访问的远程文件。我很少在本地使用 sudo 编辑文件,所以这对我来说不是问题。但是,我们也可以让它适用于本地文件,但代价是复杂性:
alias sff 'find-file "${pwd}/$1"(:s,^,/sudo::,:s,::/ssh:,:,)'
也就是说,预先/sudo::
添加(这是对本地文件执行 sudo 的方法),然后::/ssh:
用:
. (我会刚刚删除:/ssh:
,但 eshell 的:s///
构造不接受空替换。)
我在EmacsWiki找到了一个非常有效的替代答案。使用它,您仍然可以find-file
像往常一样打开文件,但随后调用M-x sudo-edit-current-file
(如下所示)以使用 Tramp 以 root 身份重新打开文件。我认为这是一个非常优雅的解决方案,因为通常我最初只是想查看一个文件,然后发现我需要对其进行编辑。
这是函数,以防它从上面的页面中消失:
(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)))