Bash/Expect:SSH登录后执行命令失效问题求助
我来帮你排查下这个Expect脚本的问题,你遇到的"command not found"大概率是这几个原因之一,对应解决方法如下:
命令参数传递不完整:你现在用
set command [lindex $argv 3]只能获取到第4个参数(因为argv从0开始计数),如果你的执行命令包含空格或者多个参数(比如ls -l /home),lindex只会拿到第一个单词ls,剩下的部分会被丢弃,自然会提示找不到命令。
解决方法:把这行改成set command [lrange $argv 3 end],这样就能把从第3个索引开始的所有参数都拼接成完整的命令。远程shell环境变量差异:手动登录VM时是交互式shell,会加载
~/.bashrc、/etc/profile这类配置文件,所以PATH等环境变量是完整的;但Expect脚本通过SSH登录时默认是非交互式shell,不会加载这些配置,导致一些命令因为不在默认PATH里而找不到。
解决方法:要么用命令的绝对路径(比如/usr/bin/ls代替ls),要么在执行目标命令前先加载环境配置,比如在send命令里先执行source ~/.bashrc &&再跟上你的命令。命令解析方式问题:如果你的命令包含管道、重定向或者特殊字符,直接
send "$command\r"可能会被远程shell错误解析,导致命令识别失败。
解决方法:用bash -c来包裹命令,确保bash完整解析整个命令,比如写成send "bash -c '$command'\r"。
给你一个修改后的完整示例脚本,你可以参考调整:
#!/usr/bin/expect -f set user [lindex $argv 0] set to [lindex $argv 1] set pass [lindex $argv 2] set command [lrange $argv 3 end] ;# 获取完整的命令参数 puts "$user, $to , $command and $pass ." # 建立SSH连接 spawn ssh $user@$to # 匹配密码提示,同时处理首次连接的信任提示 expect { "password:" { send "$pass\r" } "Are you sure you want to continue connecting" { send "yes\r"; exp_continue } } # 匹配远程主机的shell提示符,根据你的VM调整,比如#或者$ expect -re {\$ $} # 执行命令,用bash -c确保完整解析 send "bash -c '$command'\r" expect -re {\$ $} # 退出连接 send "exit\r" expect eof
另外别忘了给脚本加上可执行权限:chmod +x your_script.exp,执行的时候按照./your_script.exp 用户名 主机IP 密码 "要执行的命令"的格式传参,命令最好用引号包起来避免空格拆分。
内容的提问来源于stack exchange,提问作者sauumum

