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

在Expect的interact模式下恢复Ctrl-Z的常规作业控制功能

Expect脚本作业控制问题解决方案

问题概述

在Expect中使用interact命令时,终端会被设置为raw模式,破坏原生作业控制。手册建议拦截Ctrl-Z字符手动调用kill,但希望改为让终端自行发送SIGTSTP信号,通过预先设置的trap处理,同时保留interact传递用户输入给派生程序的功能。另外存在两个疑问:

  • 如何在interact代码块中执行stty isig?
  • -reset \032 {...}的实际作用,为何命名为"reset"却未执行终端重置操作?

关键知识点解析

1. -reset选项的真实作用

interact的-reset选项命名容易产生误导,它的实际功能是:当匹配到指定字符(此处为Ctrl-Z,即\032)时,先将终端模式重置为调用interact前的状态,再执行代码块内的自定义逻辑。这里的"reset"指恢复终端模式,而非重置整个终端环境,代码块中的kill操作是额外添加的业务逻辑。

2. 启用终端SIGTSTP信号的方法

要让终端自行发送SIGTSTP,需在interact期间保留终端的信号生成功能,即开启isig标志。只需在进入interact前执行stty isig配置终端,同时避免强制将终端设为raw模式即可。

修改后的脚本实现

以下是调整后的passwrap.exp,可让终端正常发送SIGTSTP,通过预先设置的trap处理子进程和Expect自身的暂停/恢复:

#!/usr/bin/expect -f

set timeout -1

if {$argc < 3} {
    send_user "Wrapper script for programs that prompt for a password and can't read it from a file/env var.\n"
    send_user "usage: $argv0 PASSWORD_FILE PASSWORD_PROMPT command args...\n"
    send_user "Ex: $argv0 ~/7zpass.txt \"Enter password:\" 7zz t encrypted.7z\n"
    exit 1
}

# First arg = password file
set password_file [lindex $argv 0]
set password_prompt [lindex $argv 1]

# Remaining args = command to execute
set cmd [lrange $argv 2 end]

# Read password
set fp [open $password_file r]
set password [read $fp]
if {[string index $password end] eq "\n"} {
        set password [string range $password 0 end-1]
}
close $fp

spawn {*}$cmd
set child_pid [exp_pid]

# 处理SIGTSTP:暂停子进程和Expect自身
trap {
    catch {exec kill -STOP $child_pid}
    exec kill -STOP [pid]
} SIGTSTP

# 处理SIGCONT:恢复子进程
trap {
    exec kill -CONT $child_pid
} SIGCONT

# 自动输入密码
expect {
        $password_prompt {
                stty -echo < $spawn_out(slave,name)
                send_user "\n"
                send -- "$password\r"
                stty echo < $spawn_out(slave,name)
        }
}

# 配置终端保留isig标志,让Ctrl-Z能触发SIGTSTP
stty isig
# 使用默认interact模式,不强制raw,保留作业控制
interact

catch wait result
exit [lindex $result 3]

核心调整说明

  • stty isig:在进入interact前执行,开启终端的信号生成功能,此时按下Ctrl-Z会自动触发SIGTSTP,交给预先设置的trap处理。
  • 移除原有的-reset \032拦截逻辑,因为终端现在会自行处理信号,无需手动捕获字符。
  • 未添加-raw选项的interact会使用默认模式,终端不会被强制设为raw,原生作业控制功能得以保留。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.02 02:33:12