Emacs:Tramp无法使用

44

我尝试通过Tramp在Emacs中打开远程文件。

(require 'tramp)
(setq tramp-default-method "ssh")

我从Emacs收到了一条消息

Tramp: 等待来自远程shell的提示

之后Emacs卡住了,没有对任何操作作出响应

Emacs已安装在Windows上; 远程文件位于Linux机器上。


你在Windows机器上使用哪个ssh客户端? - phils
1
如果您成功解决了这个问题,请确保发布您的解决方案。作为长期在Windows上使用Emacs的用户,我一直无法使tramp可靠地工作,即使按照各种维基说明进行操作。 - James Sulak
C-g可以帮助停止挂起的Emacs。 - Afsin Toparlak
6个回答

71
如果你要连接的账户使用了一些奇怪的高级 shell 提示符,那么很可能这就是导致 Tramp 失败的原因。
以 root 用户身份登录,然后输入:
PS1="> "

这是一个普通的、标准的shell(ZSH、BASH等)提示符,tramp会理解它。然后切换到用户帐户,并启动emacs -q(确保您的.emacs文件不会引起问题),尝试C-x C-f /sudo:root@localhost:/etc/hosts,看看发生了什么。

您也可以(不建议)自定义正则表达式来定义tramp的预期:

M-x customize-variable RET tramp-terminal-prompt-regexp

我的做法:

  1. 确保变量tramp-terminal-type的值为"dumb"

M-x customize-variable RET tramp-terminal-type

  1. 在你的.*shrc中测试并提供正确的提示:
case "$TERM" in
"dumb")
    PS1="> "
    ;;
xterm*|rxvt*|eterm*|screen*)
    PS1="my fancy multi-line \n prompt > "
    ;;
*)
    PS1="> "
    ;;
esac

5
谢谢!这可能是许多人问题的根源,但他们并没有意识到。修复了我认为已经无法解决的Tramp错误。 - emish
3
值得注意的是,你可以自定义 tramp 期望的提示符 (M-x customize-variable "tramp-login-prompt-regexp"),但我的建议是让你的提示符兼容 tramp (https://github.com/xaccrocheur/kituu/blob/master/.bashrc),而不是相反。 - yPhil
4
我希望所有这些都能自动化。远程主机的提示模式应该自动检测。我们如何实现这一点? - Nordlöw
1
没有人提到我遇到的阻碍:如果 shell 不是交互式的,则 ~/.bashrc 文件会立即返回(在 Gentoo 中默认情况下)。应该删除 "return" 命令。 - avp
1
我之前写过一篇关于这个问题的文章在这里,因为我曾经遇到了很多麻烦,无法确定问题所在。 - Bounga
显示剩余5条评论

18

在这里,你的Windows SSH客户端是关键,而“ssh” Tramp方法几乎肯定是错误的。

如果您使用的是Cygwin,则需要使用“sshx”方法,并且可能需要使用ssh-agent来处理身份验证。详情请参见: 在EmacsW32和Cygwin中使用Tramp是否可行?

我想同样适用于不需要完整Cygwin安装但使用Cygwin DLL的任何独立SSH客户端。(我提到这一点,因为我相当确定我记得看到这样的东西。)

如果您使用的是PuTTY,则需要使用“plink”方法,正如Alex Ott所指出的那样。如果维基无法满足要求,在这里搜索可能会找到配置此方法的解决方案。

我可以建议的其他替代方案:

  1. 使用Cygwin本地Emacs。虽然比NTEmacs慢,但Tramp似乎与“ssh”方法很好地配合使用,并且密码提示也有效。

  2. 在Windows机器上托管Linux虚拟机,并在其中运行Emacs。这是一个相当大的障碍,但这是我在Windows中使用Tramp的首选方式


4

嗯,这是tramp的一个缺陷。

真正的解决方法是在使用tramp时防止加载.bashrc。(因为现在是PS1,但它可以是PATH,或者您的.bashrc会做任何其他让tramp不满意的事情……)。

这可以通过请求ssh设置环境变量并在.bashrc中进行测试来实现:

将以下内容添加到~/.emacs:

(require 'tramp-sh nil t) (setf tramp-ssh-controlmaster-options (concat "-o SendEnv TRAMP=yes " tramp-ssh-controlmaster-options))

将以下内容添加到~/.bashrc开头:

if [ ! -z ${TRAMP-x} ] ; then return fi

另一个tramp的默认值是它没有一个变量来传递随机参数给ssh命令,我们必须利用tramp-ssh-controlmaster-options


我喜欢这里的解释,但是这种方法不是与最受欢迎的答案中的方法类似吗?除了您发送自定义环境变量而不是加载bash(似乎合理),而那个答案则检查TERM环境变量并在Tramp的情况下加载简单提示(也很合理)?在尝试一种方法之前,只是想确认我的理解。 - Jesse W. Collins

3

您是否查看了Emacs维基上的解决方案?ssh是否在PATH中?建议在Windows系统上使用plink -请参阅Tramp文档中的"内联方法"部分。


Alex:谢谢,但不幸的是文档中缺少一个例子。这里是:C-x C-f /plink:user@host:/path/to/file - avp

3

如果问题出在远程 shell 中的炫酷自定义提示符,一个简单的解决方法是添加以下内容到你的.bashrc或相应文件中:

if [[ $TERM == "dumb" ]]; then
    export PS1="$ "
fi

在你定义了 PS1 之后。
注:此建议来自于 ChasingLogic,这是他们在该线程中的建议。

1
先前的技术(仅为完整起见): https://blog.karssen.org/2016/03/02/fixing-emacs-tramp-mode-when-using-zsh/原始的Emacs Wiki条目: https://www.emacswiki.org/emacs/TrampMode#h5o-9 - M-x

0
顺便说一下 - 如果您需要使用tramp来执行sudo - 您实际上可以使用sudoedit 无需tramp进行操作。
目前,我正在使用此bash函数:
erf () { SUDO_EDITOR="emacsclient -a emacs" sudoedit $@; }

Tramp 的主要用途不是 sudo。 - damd
3
是的,我应该把它发表为评论而不是答案——但我当时年轻愚蠢。 - Adobe
@Adobe,你的名字是一个软件公司的名字。只是这么说而已。 - vdegenne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接