1

假设我有这两个 bash 脚本:

/tmp/陷阱:

#!/bin/bash
trap 'echo trapper: ignoring USR1' USR1
"$(dirname $0)"/usr1er & p=$!
sleep 1
echo trapper: now killing usr1er
kill $p
echo trapper: sleeping
sleep 1
echo trapper: reached end of trapper

/tmp/usr1er:

#!/bin/bash
trap 'echo "usr1er: EXIT received, sending USR1"; kill -USR1 0' EXIT
while sleep 1;do echo usr1er: sleeping;done

Trapper 应该捕获 USR1 并简单地忽略它。它启动 usr1er,它使用 USR1 信号终止其进程组。现在,如果我从交互式 shell 中将 trapper 作为脚本单独启动,它会杀死 usr1er 并正常退出:

$ /tmp/trapper; echo done
trapper: now killing usr1er
trapper: sleeping
usr1er: EXIT received, sending USR1
/tmp/trapper: line 9: 16596 Terminated              "$(dirname $0)"/usr1er
trapper: ignoring USR1
trapper: reached end of trapper
done

如果我尝试$(/tmp/trapper),它会退出整个外壳。同样,如果我制作一个单独的脚本来调用/tmp/trapper,例如/tmp/outer

#!/bin/bash
"$(dirname $0)"/trapper
echo outer: reached end of outer

它被杀死而不打印“到达外部的末端”:

$ /tmp/outer
trapper: now killing usr1er
trapper: sleeping
usr1er: EXIT received, sending USR1
User defined signal 1
/tmp/trapper: line 9: 23544 Terminated              "$(dirname $0)"/usr1er
User defined signal 1
trapper: ignoring USR1
trapper: reached end of trapper

为什么?

4

2 回答 2

0

似乎$()没有使用单独的进程组/PGID(显然是为了C-c工作)来启动进程。

此外,任何非交互式 shell 也不会为其子级启动单独的 PGID(除非您使用 set -m 打开作业控制):

$ bash -c '/tmp/trapper;echo done'
trapper: now killing usr1er
trapper: sleeping
usr1er: EXIT received, sending USR1
User defined signal 1
$ /tmp/trapper: line 9: 17522 Terminated              "$(dirname $0)"/usr1er
trapper: ignoring USR1
trapper: reached end of trapper

请注意,不会打印“完成”,不会捕获 USR1 的外部 bash 脚本会被杀死,而 trapper 会一直存活到最后。

ps -o %p%r%c -p$$您可以通过输入脚本来检查每个进程的 PGID :

$ /tmp/outer
  PID  PGID COMMAND
27630 27630 outer
  PID  PGID COMMAND
27633 27630 trapper
  PID  PGID COMMAND
27635 27630 usr1er
trapper: now killing usr1er
trapper: sleeping
usr1er: EXIT received, sending USR1
User defined signal 1
$ /tmp/trapper: line 9: 27635 Terminated              "$(dirname $0)"/usr1er
trapper: ignoring USR1
trapper: reached end of trapper
于 2014-02-20T13:09:08.933 回答
0

试试这个改变

/tmp/usr1er:

#!/bin/bash
trap 'echo "usr1er: EXIT received, sending USR1"; kill -USR1 $PPID' TERM
while sleep 1;do echo usr1er: sleeping;done

处理 TERM 信号而不是 EXIT 并将 USR1 发送到$PPID而不是0

于 2014-02-20T14:38:54.120 回答