如何在脚本中通过SSH执行sudo -Es及后续命令避免会话挂起?
解决SSH远程执行多命令卡住的问题
你的问题出在对SSH命令解析逻辑和sudo -Es作用的理解上,我来拆解并给出解决方案:
为什么原来的命令会卡住?
你写的命令:
ssh ubuntu@1.2.3.4 sudo -Es; chown -R root:root pki; mv pki /etc/kubernetes/
这里的分号;是被本地shell处理的,实际执行逻辑是:
- 先运行
ssh ubuntu@1.2.3.4 sudo -Es,远程启动一个交互式root shell - 只有等这个SSH会话手动退出后,才会在本地主机执行后面的
chown和mv命令
而sudo -Es会启动一个持续的交互式root环境,所以SSH会话会一直停在这里等待你输入命令,自然就"卡住"了,而且后续命令根本不会在远程主机执行。
正确的实现方式
下面几种方法都能满足你的自动化需求,按简洁度和可读性排序:
方法1:用单引号包裹所有远程命令
把需要在远程执行的命令整合成一个字符串,用单引号包裹,这样SSH会把整个命令串传到远程主机的shell执行:
ssh ubuntu@1.2.3.4 'sudo chown -R root:root pki && sudo mv pki /etc/kubernetes/'
- 用
&&连接命令,确保前一个命令执行成功后再执行下一个(比;更安全,避免前序命令失败后继续执行无效操作) - 如果你的ubuntu用户执行sudo需要输入密码,加上
-t参数强制分配伪终端,这样能看到密码提示:
ssh -t ubuntu@1.2.3.4 'sudo chown -R root:root pki && sudo mv pki /etc/kubernetes/'
方法2:用sudo sh -c批量执行命令
如果需要一次性切换到root后执行多个命令,可以用sudo sh -c包裹命令串,让sudo启动一个shell执行所有命令:
ssh -t ubuntu@1.2.3.4 'sudo sh -c "chown -R root:root pki && mv pki /etc/kubernetes/"'
双引号用来包裹需要root执行的命令串,确保它们被当作一个整体传给sh -c。
方法3:用Here-Doc编写清晰的多命令脚本
如果后续还要添加更多操作,用Here-Doc的方式可读性更好,就像在远程主机写脚本一样:
ssh -t ubuntu@1.2.3.4 << 'EOF' # 以root权限执行以下命令 sudo chown -R root:root pki sudo mv pki /etc/kubernetes/ EOF
<< 'EOF'表示这里面的内容会原封不动传到远程执行,不会被本地shell解析。
额外注意事项
- 权限配置:确保远程主机的ubuntu用户有sudo权限,如果需要免密执行,可以在远程主机的
/etc/sudoers文件中添加(注意安全):ubuntu ALL=(ALL) NOPASSWD:ALL - 路径准确性:确认
pki目录在远程主机的当前工作目录下,如果不是,要写绝对路径(比如/home/ubuntu/pki),避免出现找不到目录的错误。
内容的提问来源于stack exchange,提问作者Chris G.
相关产品推荐
相关产品推荐

