Expect调用installSoftware.sh脚本后进程无法退出问题求助
问题:Expect调用安装脚本执行rpm后卡住无法退出
我用Expect实现软件安装自动化,简化后的Expect代码如下(直接在控制台执行会出现相同问题):
expect <<-EOS #!/usr/bin/expect -f set timeout -1 #run the command spawn ./installSoftware.sh expect "*?Question 1*" { send "N\r" } expect -ex {Question 2 (default is [RANDOM STRING]):} { send "\r" } puts "-------------- DONE 1 ---------------" expect eof puts "-------------- DONE 2 ---------------" EOS
installSoftware.sh是负责软件包安装的大型脚本,最后一行代码为:
echo "----------- Done-----------"
直接执行installSoftware.sh一切正常,但通过上述Expect脚本调用时,脚本执行完最后一行echo输出后会卡住,HTOP显示进程仍在运行无法正常退出。目前发现移除脚本中的rpm -Uvh --oldpackage --replacepkgs mysoftware.rpm语句后,进程即可正常退出。
请问该如何调试此问题?此问题属于installSoftware.sh脚本本身的问题还是Expect相关问题?
解决方案与调试方法
问题归属判断
大概率是rpm命令导致的子进程残留/未完全退出问题,而非Expect本身的问题。直接执行脚本正常,仅在Expect接管终端且保留rpm语句时卡住,说明rpm在Expect模拟的终端环境下存在未处理的文件描述符、后台子进程,或是rpm对终端环境的特殊依赖未被满足。
调试步骤
- 跟踪进程树:卡住时执行
pstree -p <installSoftware.sh的PID>,查看进程树结构,确认是rpm进程本身卡住,还是它启动的子进程未退出。 - 重定向rpm输出:修改
installSoftware.sh中的rpm命令,将标准输出和错误重定向到日志文件:
查看日志确认rpm执行过程中是否有未预期的交互请求或错误信息。rpm -Uvh --oldpackage --replacepkgs mysoftware.rpm > rpm_exec.log 2>&1 - 验证rpm的终端依赖:rpm可能在某些场景下尝试访问终端设备(如签名验证提示),而Expect的终端环境与直接执行的终端有差异。可以尝试用
script命令模拟完整终端环境执行rpm:
或添加script -q -c "rpm -Uvh --oldpackage --replacepkgs mysoftware.rpm" /dev/nullrpm的非交互式参数(如--nosignature,若涉及签名验证)。 - 检查文件描述符:卡住时用
lsof -p <rpm进程的PID>查看rpm打开的文件描述符,确认是否有未关闭的管道、终端设备或异常文件。 - 调整Expect的EOF处理:尝试将
expect eof替换为wait,或添加超时机制:
观察是否能强制退出,同时查看是否有错误输出。expect -timeout 60 eof - 清理子进程:在
installSoftware.sh的echo语句前添加wait命令,等待所有后台子进程退出;或谨慎使用pkill -P $$杀掉当前脚本的所有子进程(注意:可能误杀其他关联进程,需测试)。
内容的提问来源于stack exchange,提问作者DangerSchwob
相关产品推荐
相关产品推荐

