带SSH passphrase的用户在三台服务器间嵌套执行ssh命令报错如何解决
问题根因
- 报错
Pseudo-terminal will not be allocated because stdin is not a terminal是因为嵌套执行SSH命令时,默认不会为远程会话分配伪终端,导致第二层SSH调用缺少交互输入所需的终端环境。 - 报错
Permission denied (publickey)核心原因是默认SSH连接服务器B时,不会将本地服务器A上ssh-agent存储的已解锁带passphrase的密钥凭证转发到B的会话中,B上执行SSH连接C时无有效验证凭证,所以验证失败。
临时单次执行方案
- 首先在本地服务器A上执行
ssh-add ~/.ssh/你的私钥文件路径,输入一次密钥的passphrase完成解锁,解锁状态在ssh-agent运行期间持续有效。 - 执行命令时增加两个参数即可正常运行:
ssh -A -t B "ssh C run_a_script_here"
参数说明:
-A:开启SSH Agent转发功能,将本地A上已解锁的密钥凭证转发到B的会话中,B访问C时可直接使用该凭证完成验证-t:强制为远程会话分配伪终端,解决TTY分配错误的问题
永久配置方案
如果需要频繁执行嵌套SSH操作,可以修改服务器A上的SSH客户端配置,避免每次手动加参数:
- 编辑A上的
~/.ssh/config文件(不存在则新建),添加如下配置:
Host B # 替换为服务器B的实际IP/域名 HostName 服务器B的地址 # 替换为你登录B的用户名 User 登录B的用户名 ForwardAgent yes RequestTTY yes
- 保存配置后,原命令无需加任何参数即可直接运行:
ssh B "ssh C run_a_script_here"
注意事项
- 仅在你完全信任服务器B的前提下开启Agent转发,避免B被入侵后你的SSH密钥凭证被窃取。
- 开启Agent转发的场景下,需要将服务器A的SSH公钥添加到C的
~/.ssh/authorized_keys文件中,无需B的公钥在C上配置。 - 如果需要持久化保存密钥解锁状态,避免每次重启终端都要重新执行
ssh-add输入passphrase,可以使用keychain工具:- 安装:Debian/Ubuntu系列执行
apt install keychain,CentOS/RHEL系列执行yum install keychain - 编辑A上的shell配置文件(
~/.bashrc或~/.zshrc等,根据你用的shell选择),添加两行配置:
keychain --quiet ~/.ssh/你的私钥文件路径 source ~/.keychain/$HOSTNAME-sh- 重启终端后仅需首次输入一次passphrase,后续所有终端会话都可以直接使用解锁后的密钥。
- 安装:Debian/Ubuntu系列执行
内容的提问来源于stack exchange,提问作者Philip Shangguan
相关产品推荐
相关产品推荐

