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
相关产品推荐
相关产品推荐

