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

Expect脚本远程执行后台脚本时退出致脚本中断的求助

解决Expect退出后远程脚本被中断的问题

我懂你的困扰——远程脚本要跑十几分钟,结果一退出Expect会话就被打断,加了&后台运行也没效果。这是因为哪怕后台运行,进程依然属于当前shell的会话组,当你执行exit时,shell会给会话组内的所有进程发送SIGHUP信号,默认情况下进程收到这个信号就会终止,而单纯的&并没有改变进程的会话归属。

既然你没有nohup工具,这里给你几个靠谱的替代方案:

1. 使用setsid(最推荐)

setsid是大部分类Unix系统自带的工具,它会为你的脚本创建一个全新的会话和进程组,让进程彻底脱离当前shell的控制。修改你的Expect脚本片段如下:

expect {
    -re ".*#.*" {
        send "setsid /usr/bin/bash myscript.sh > /dev/null 2>&1\n";
    }
}
expect {
    -re ".*#.*" {
        exp_send "exit\r";
    }
}

这样启动的脚本进程会成为新会话的领头进程,你退出原shell会话后,它不会收到SIGHUP信号,能正常跑完整个流程。

2. 使用disown

如果你的系统没有setsid,可以先把脚本后台运行,再用disown将它从shell的作业列表中移除,这样shell退出时就不会给它发信号:

expect {
    -re ".*#.*" {
        send "/usr/bin/bash myscript.sh > /dev/null 2>&1 &\n";
    }
}
expect -re ".*#.*" {
    send "disown %1\n";  # %1指刚启动的第一个后台作业
}
expect -re ".*#.*" {
    exp_send "exit\r";
}

注意%1是后台作业的编号,如果同时启动了多个作业,要对应调整编号。

3. 忽略SIGHUP信号

你也可以在启动脚本时,让它忽略SIGHUP信号,这样即使收到信号也不会终止:

expect {
    -re ".*#.*" {
        send "/usr/bin/bash -c 'trap \"\" HUP; myscript.sh' > /dev/null 2>&1 &\n";
    }
}
expect {
    -re ".*#.*" {
        exp_send "exit\r";
    }
}

这里用bash -c执行一段命令,先通过trap "" HUP设置忽略SIGHUP信号,再启动你的脚本。

额外提示

执行完启动脚本的命令后,一定要等shell返回提示符(也就是第二个expect -re ".*#.*")再发送exit,确保脚本已经完全启动并脱离控制,避免因为过早exit导致启动过程被打断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:35:49