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

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 -Uvh --oldpackage --replacepkgs mysoftware.rpm > rpm_exec.log 2>&1
    
    查看日志确认rpm执行过程中是否有未预期的交互请求或错误信息。
  • 验证rpm的终端依赖:rpm可能在某些场景下尝试访问终端设备(如签名验证提示),而Expect的终端环境与直接执行的终端有差异。可以尝试用script命令模拟完整终端环境执行rpm:
    script -q -c "rpm -Uvh --oldpackage --replacepkgs mysoftware.rpm" /dev/null
    
    或添加rpm的非交互式参数(如--nosignature,若涉及签名验证)。
  • 检查文件描述符:卡住时用lsof -p <rpm进程的PID>查看rpm打开的文件描述符,确认是否有未关闭的管道、终端设备或异常文件。
  • 调整Expect的EOF处理:尝试将expect eof替换为wait,或添加超时机制:
    expect -timeout 60 eof
    
    观察是否能强制退出,同时查看是否有错误输出。
  • 清理子进程:在installSoftware.sh的echo语句前添加wait命令,等待所有后台子进程退出;或谨慎使用pkill -P $$杀掉当前脚本的所有子进程(注意:可能误杀其他关联进程,需测试)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 17:55:20