在Shell脚本中使用Expect向远程服务器发送if else语句的问题
解决Expect脚本执行SSH远程条件命令问题
问题描述
需要通过Expect工具SSH连接远程服务器,实现以下逻辑:检查指定目录是否存在,若不存在则创建该目录;若存在则生成带递增数字后缀的新目录。当前可成功连接服务器并发送单行命令,但无法执行if else类的多行条件语句,脚本连接后直接退出。
原脚本片段:
#!/usr/bin/expect -f set timeout 120 spawn ssh user@remoteIP expect "*?assword:" send "remote password" expect "$ " set name "b" send "if [ -d /path/to/remote/directory/$name ]; then set i 1 while [ -d /path/to/remote/directory/$name$i ]; do let i++ done set name $name$i fi" send -- "mkdir -p /path/to/remote/directory/$name\r" expect "$ " send -- "exit\r" expect eof
原脚本关键错误
- 发送密码后未添加
\r,导致密码未提交,SSH登录流程中断; - 未转义Expect特殊字符:
[ ]会被Expect当作内部命令解析,而非传给远程shell; - 多行命令未正确处理换行,远程shell无法识别完整逻辑;
- 本地Expect变量与远程shell变量混淆,导致变量替换错误。
修正后的脚本
#!/usr/bin/expect -f set timeout 120 spawn ssh user@remoteIP expect "*?assword:" # 发送密码后添加\r完成登录提交 send "remote password\r" expect "$ " # 用{}包裹完整shell逻辑,避免Expect解析特殊字符 send { name="b" if [ -d /path/to/remote/directory/$name ]; then i=1 while [ -d /path/to/remote/directory/$name$i ]; do let i++ done name="${name}${i}" fi mkdir -p /path/to/remote/directory/$name } "\r" # 等待命令执行完成,出现提示符后再退出 expect "$ " send "exit\r" expect eof
改动说明
- 密码提交:添加
\r确保密码被正确提交,完成SSH登录; - 特殊字符处理:用
{}包裹shell代码块,让Expect直接将内容原封不动传给远程shell,避免解析其中的[ ]和变量; - 逻辑整合:将变量定义、条件判断、目录创建逻辑整合为一个代码块,一次性发送,确保远程shell完整执行;
- 变量边界明确:远程shell中用
${name}${i}明确变量边界,避免命名歧义。
替代方案:单行命令发送
若偏好单行命令,可将逻辑用分号分隔,同时转义远程shell变量(避免被本地Expect替换):
send "name=b; if [ -d /path/to/remote/directory/\$name ]; then i=1; while [ -d /path/to/remote/directory/\$name\$i ]; do let i++; done; name=\$name\$i; fi; mkdir -p /path/to/remote/directory/\$name\r"
内容的提问来源于stack exchange,提问作者Abdullah KIRMAN
相关产品推荐
相关产品推荐

