陷阱无法在shell脚本中工作? [英] trap not working in shell script?
问题描述
我正在OS X上编写脚本,该脚本需要捕获SIGTERM,以便在退出之前杀死某些子进程.出于这个问题,我将其简化为以下最小示例,由于某些原因,该示例无法正常运行:
I'm in the process of writing a script on OS X that needs to trap SIGTERM in order to kill some child processes before exiting. For the sake of this question I've boiled it down to the following minimal example that, for some reason, isn't working as I'd expect it to:
#!/bin/sh
function shutdown()
{
touch foo.txt
exit 0
}
trap shutdown TERM
su -l myusername -c "sleep 9999"
我在一个终端窗口中运行此脚本,然后切换到另一个窗口,然后"ps -aef"显示以下内容:
I run this script in one terminal window, then switch to another and "ps -aef" yields this:
502 857 645 0 11:38PM ttys001 0:00.00 /bin/sh ./foo.sh
0 858 857 0 11:38PM ttys001 0:00.02 su -l myusername -c sleep 9999
502 859 858 0 11:38PM ttys001 0:00.00 sleep 9999
然后从第二个窗口中发出"kill -15 857",但永远不会触发陷阱.该脚本在"su"命令上仍然处于阻止状态.
From that second window I then issue "kill -15 857", but the trap is never triggered. The script remains blocked on the "su" command.
知道为什么吗?我觉得这很简单.
Any idea why? I get the feeling it's something simple.
推荐答案
如果bash正在等待命令完成并接收到信号对于已设置陷阱的陷阱,直到命令完成.
If bash is waiting for a command to complete and receives a signal
for which a trap has been set, the trap will not be executed until the
command completes. 正如 gniourf_gniourf 所说,这是相对于 As gniourf_gniourf says, this is a POSIX spec relative to signals in shells. 您可以通过捕获实例SIGUSR1而不是SIGTERM来进行检查;您会看到 You can check it by trapping for instance SIGUSR1 in place of SIGTERM; you'll see that 一种解决方案是在后台运行命令,然后 A solution is to run the command in background, then 您将遇到两个问题: You will get two problems: 这篇关于陷阱无法在shell脚本中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
kill -TERM
将再次杀死该进程.kill -TERM
will kill again the process. wait
终止命令.在这种情况下, trap
将起作用.试试这个:wait
for its termination. In this case the trap
will work. Try this:#! /bin/bash
shutdown()
{
touch foo.txt
exit 0
}
trap shutdown TERM
su -l myusername -c "sleep 9999" & # On Ubuntu: sudo su
wait
su
将无法在前台询问密码;您将必须手动杀死 su
.su
won't be able to ask password in foreground; you will have to manually kill su
.