能否让expect修改子进程tty状态匹配interact模式而不使用interact?
问题描述
现有一段用于自动化无源码程序X审批流程的Expect脚本:
eval spawn $argv set timeout -1 expect -ex {Approve Request} sleep 1 send "y\r" interact
该脚本可正常执行并退出;但将最后一行的interact替换为expect eof后,程序X会挂起。通过expect -d日志发现:使用interact时,程序X接收y后会继续输出并发送EOF;替换为expect eof后,程序X接收y后停止输出,需手动用Control-C终止。推测程序X的行为与tty状态相关,尝试过设置stty_init及spawn -nottycopy:
set stty_init "raw -echo" eval spawn -nottycopy $argv
但无预期效果,现需实现:不使用interact,让Expect将子进程的tty状态修改为interact模式下的状态。
解决方案
1. 先获取interact模式下的tty属性
运行原脚本(带interact),在程序进入interact阶段后,按Ctrl+Z挂起Expect进程,找到程序X的PID,执行以下命令查看其tty属性:
stty -a -F /proc/<程序X的PID>/fd/0
记录输出中的所有属性(比如icanon echo intr ^c等)。
2. 在脚本中手动设置tty属性
将步骤1中记录的属性通过Expect的stty命令设置给子进程,替换expect eof的脚本示例:
eval spawn $argv # 设置为interact模式下的tty属性,替换为你实际获取到的内容 stty icanon echo intr ^c quit ^\\ erase ^? kill ^U eof ^D start ^Q stop ^S susp ^Z rprnt ^R flush ^O werase ^W lnext ^V -ixon -ixoff set timeout -1 expect -ex {Approve Request} sleep 1 send "y\r" expect eof
也可以将属性写入stty_init变量,在spawn时生效:
# 替换为你实际获取到的interact模式tty属性 set stty_init "icanon echo intr ^c quit ^\\ erase ^? kill ^U eof ^D start ^Q stop ^S susp ^Z rprnt ^R flush ^O werase ^W lnext ^V -ixon -ixoff" eval spawn $argv set timeout -1 expect -ex {Approve Request} sleep 1 send "y\r" expect eof
3. 补充说明
interact模式下,Expect会将子进程的pty与当前终端关联,并维持tty的交互模式属性(如规范模式、回显开启等);而expect eof模式下,子进程的pty默认处于非交互状态,程序X可能因检测不到终端交互信号而卡住。手动设置匹配interact的tty属性,即可让程序X在expect eof模式下正常执行并退出。
内容的提问来源于stack exchange,提问作者merlin2011
相关产品推荐
相关产品推荐

