Expect脚本通过SSH执行远程命令失败问题排查
Expect脚本SSH执行pwd命令失败排查
问题背景
正在学习使用Expect工具编写脚本,尝试通过SSH登录远程主机执行pwd命令,但命令未成功输出结果。以下是相关信息,请求排查失败原因。
脚本内容
#!/usr/bin/expect spawn ssh ibmcoll@192.168.1.100 expect "Enter passphrase for key '/home/ibmcoll/.ssh/id_rsa': " send passphrase expect "*ibmcoll*" sleep 3 send "pwd\r" sleep 3 send "exit\r"
执行输出
expect ssh.exp spawn ssh ibmcoll@192.168.1.100 Enter passphrase for key '/home/ibmcoll/.ssh/id_rsa': Last login: Sat Feb 11 19:10:47 2023 from servername *(some welcome lines are here)* [ibmcoll@servername ~]$
调试关键日志
expect: does "\r\nLast login: Thu Feb 16 21:32:06 2023 from servername.domain\r\r\n************************************************************************************\r\n* This system should be used for conducting ####### business *\r\n* or for purposes authorized by ####### management it is mandatory *\r\n* to comply with all the requirements listed in the applicable security policy *\r\n* and only process or store the data classes approved for this *\r\n* asset type use is subject to audit at any time by ####### management *\r\n************************************************************************************\r\n\u001b]0;ibmcoll@servername:~\u0007\u001b[?1034h[ibmcoll@servername ~]$ " (spawn_id exp4) match glob pattern "*ibmcoll*"? **yes** expect: set expect_out(0,string) "\r\nLast login: Thu Feb 16 21:32:06 2023 from servername.domain\r\r\n************************************************************************************\r\n* This system should be used for conducting ####### business *\r\n* or for purposes authorized by ####### management it is mandatory *\r\n* to comply with all the requirements listed in the applicable security policy *\r\n* and only process or store the data classes approved for this *\r\n* asset type use is subject to audit at any time by ####### management *\r\n************************************************************************************\r\n\u001b]0;ibmcoll@servername:~\u0007\u001b[?1034h[ibmcoll@servername ~]$ " expect: set expect_out(spawn_id) "exp4" expect: set expect_out(buffer) "\r\nLast login: Thu Feb 16 21:32:06 2023 from servername.domain\r\r\n************************************************************************************\r\n* This system should be used for conducting ####### business *\r\n* or for purposes authorized by ####### management it is mandatory *\r\n* to comply with all the requirements listed in the applicable security policy *\r\n* and only process or store the data classes approved for this *\r\n* asset type use is subject to audit at any time by ####### management *\r\n************************************************************************************\r\n\u001b]0;ibmcoll@servername:~\u0007\u001b[?1034h[ibmcoll@servername ~]$ " send: sending "pwd\r" to { exp4 } send: sending "exit\r" to { exp4 }
问题分析
从调试日志可见,脚本确实发送了pwd\r和exit\r,但执行输出中无pwd结果,核心问题如下:
- 提示符匹配过于宽泛:
expect "*ibmcoll*"会匹配欢迎信息中的ibmcoll字符串,导致脚本在登录流程未完全就绪(命令提示符未出现)时就发送命令,存在时机偏差。 - 未等待命令执行结果:发送
pwd后仅靠sleep 3等待,随后直接退出会话,固定睡眠时间无法保证命令执行完成并输出结果,导致会话提前结束,看不到pwd输出。 - 密码发送不规范:
send passphrase未添加回车符\r,虽本次登录成功,但属于不规范写法,可能在其他环境下导致密码未正确提交。
修复方案
修改后的脚本如下:
#!/usr/bin/expect # 启动SSH会话 spawn ssh ibmcoll@192.168.1.100 # 等待密钥密码提示,发送密码并回车 expect "Enter passphrase for key '/home/ibmcoll/.ssh/id_rsa': " send "passphrase\r" # 等待精确的命令提示符,确保登录完成 expect "\[ibmcoll@servername ~\]$" # 发送pwd命令 send "pwd\r" # 等待pwd执行完成并输出结果,匹配新的提示符 expect "\[ibmcoll@servername ~\]$" # 退出SSH会话 send "exit\r" # 等待会话结束 expect eof
修改说明
- 密码发送添加
\r,确保输入完成并提交 - 使用精确的命令提示符匹配(
\[ibmcoll@servername ~\]$),避免误匹配欢迎信息 - 发送
pwd后等待新的提示符,确保命令执行完毕并输出结果 - 添加
expect eof等待SSH会话正常结束,避免提前退出
内容的提问来源于stack exchange,提问作者thebananek
相关产品推荐
相关产品推荐

