2017-09-05 64 views
8

这是一个简单的程序,它注册两个trap处理程序,然后用trap -p显示它们。然后它做同样的事情,但在儿童后台进程。bash:为什么我不能在后台shell中为SIGINT设置陷阱?

为什么后台进程忽略SIGINT陷阱?

#!/bin/bash 

echo "Traps on startup:" 
trap -p 
echo "" 

trap 'echo "Received INT"' INT 
trap 'echo "Received TERM"' TERM 

echo "Traps set on parent:" 
trap -p 
echo "" 

(
    echo "Child traps on startup:" 
    trap -p 
    echo "" 

    trap 'echo "Child received INT"' INT 
    trap 'echo "Child received TERM"' TERM 

    echo "Traps set on child:" 
    trap -p 
    echo "" 
) & 

child_pid=$! 
wait $child_pid 

输出:

$ ./show-traps.sh 
Traps on startup: 

Traps set on parent: 
trap -- 'echo "Received INT"' SIGINT 
trap -- 'echo "Received TERM"' SIGTERM 

Child traps on startup: 

Traps set on child: 
trap -- 'echo "Child received TERM"' SIGTERM 

回答

6

SIGINTSIGQUIT在背景执行过程中被忽略(除非他们与set -m在背景执行)。这是一个(奇怪的)POSIX要求(有关更多详细信息,请参阅http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html或我的SO问题Why do shells ignore SIGINT and SIGQUIT in backgrounded processes?)。

此外,POSIX要求:

当进入子外壳,没有被被忽略陷阱应 设置为默认的动作,除了在只含有单一的命令 取代的情况下陷阱命令..

但是,即使你设置INT处理器在它被重置后再次子shell中,susbshel​​l不会,因为它忽略了能够接受它(你可以试试,或者你可以检查信号忽略掩码使用例如)。

+0

你可以扩展一下'set -m' - 它是什么以及它是如何完成的?我正在寻找一种解决方法,我可以将SIGINT发送到bg进程。谢谢。 – drevicko

+0

@revicko在联机帮助页中搜索“monitor”。监视模式('set -m')导致命令(管道)在不同的进程组中运行。你可能不想要那个。但是,如果你在后台进程中运行一个可执行文件,那么通过一个封装来启动它是很简单的,它将撤消SIGINT忽略(不做任何事情)。 (如果你不知道该怎么做,请提问,我会发布代码。) – PSkocik

+0

非常感谢!问题是[这里](https://stackoverflow.com/questions/49178556/how-do-i-launch-a-background-process-through-a-wrapper-thatll-undo-the-sigint-i)。 – drevicko

相关问题