You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

原脚本关键错误

  1. 发送密码后未添加\r,导致密码未提交,SSH登录流程中断;
  2. 未转义Expect特殊字符:[ ]会被Expect当作内部命令解析,而非传给远程shell;
  3. 多行命令未正确处理换行,远程shell无法识别完整逻辑;
  4. 本地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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 14:53:23