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

Expect脚本执行文件命令丢失问题排查与优化建议

问题描述

编写了Expect脚本用于逐行发送文件中的命令到终端,但执行后仅发送了2条release-subscriber-imsi命令(共4条),其余命令未执行。相关信息如下:

脚本代码

set saddress [lrange $argv 0 0]
spawn ssh Rd@$saddress
expect "password:"
send "AAAA\r"
#expect "#"
#send "terminal length 0\r"
set namafile [lindex $argv 1]
set f [ open "$namafile" ]
set commands [ split [read $f] "\n"]
close $f

foreach cmd $commands {
expect {
"#" { send -- "$cmd\r" }
"No]:" { send -- "Y\r" }
}
#sleep 2
}

expect "#"
send "logout\r"

待执行命令文件内容

==
conf t
xgw
pgw
release-subscriber-imsi 510092008527215
release-subscriber-imsi 510092008497549
release-subscriber-imsi 510092008497291
release-subscriber-imsi 510092008479295
end
write

执行命令

/usr/bin/expect kickuserxGW30.txt 172.31.201.98 userbandunginxgw30.txt > /resultkick/xGW30.txt &

结果日志

30#conf t
Enter configuration commands, one per line.  End with CTRL/Z.
30(config)#xgw
30(config-xgw)#pgw
30(config-xgw-pgw)#release-subscriber-imsi 510092008527215
Release online subscriber according to IMSI information. Are you sure to continue? [Yes/No]:Y
%Code 170002: Error, no user found! 

SPJKTZ030(config-xgw-pgw)#release-subscriber-imsi 510092008497291
Release online subscriber according to IMSI information. Are you sure to continue? [Yes/No]:Y
%Code 170002: Error, no user found! 

30(config-xgw-pgw)#end
30#write
Write DB OK!
Building configuration...
.[OK].
30#
问题原因分析
  1. 命令匹配逻辑漏洞:循环内的expect块同时监听#和No]:,当发送Y确认后,设备返回错误信息并回到#提示符,但脚本没有等待这个提示符就进入下一次循环,导致后续命令被错误地发送到未就绪的上下文,直接被设备输出覆盖或丢失。
  2. 无效命令行干扰:命令文件第一行的==是无效命令,执行后会产生错误输出,干扰脚本对正常提示符的匹配节奏。
  3. 空命令行问题:用split分割文件时,若文件存在换行空行,会生成空命令,发送空命令会导致设备重复输出提示符,打乱脚本的匹配逻辑。
  4. 缺少必要的等待同步:没有在发送确认指令后强制等待回到#提示符,导致脚本和设备的执行节奏不同步。
优化建议

1. 修复命令执行的同步逻辑

调整循环内的expect处理,确保每次发送命令(包括确认指令)后,必须等待回到#提示符再进行下一步:

foreach cmd $commands {
    # 跳过空行和无效的==行
    set trimmed_cmd [string trim $cmd]
    if {$trimmed_cmd eq "" || $trimmed_cmd eq "=="} {
        continue
    }
    # 等待提示符就绪再发命令
    expect "#"
    send -- "$trimmed_cmd\r"
    # 处理可能的确认提示
    expect {
        "No]:" {
            send -- "Y\r"
            expect "#" ;# 强制等待回到提示符
        }
        "#" {
            # 无需确认的命令直接进入下一次循环
        }
    }
}

2. 提前过滤无效命令行

读取命令文件时直接清理空行和无效行,避免无效命令干扰:

set f [ open "$namafile" ]
set commands [ split [read $f] "\n"]
close $f
# 清理命令列表
set clean_cmds [list]
foreach cmd $commands {
    set trimmed [string trim $cmd]
    if {$trimmed ne "" && $trimmed ne "=="} {
        lappend clean_cmds $trimmed
    }
}
set commands $clean_cmds

3. 启用超时与分页禁用

  • 添加超时配置防止脚本挂起:在脚本开头加入set timeout 10(单位:秒)
  • 取消注释terminal length 0相关代码,禁用设备分页输出,避免分页提示干扰匹配:
expect "#"
send "terminal length 0\r"
expect "#"

内容的提问来源于stack exchange,提问作者Wolverine adamantium

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 20:55:42