【问题标题】:I have "trap 'echo ignore' USR1" in my called script, why does the calling script get killed?我的调用脚本中有“trap 'echo ignore' USR1”,为什么调用脚本会被杀死?
【发布时间】:2014-03-21 10:54:22
【问题描述】:

假设我有这两个 bash 脚本:

/tmp/trapper:

#!/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

为什么?

【问题讨论】:

    标签: bash process process-group


    【解决方案1】:

    试试这个改变

    /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

    【讨论】:

    • 是的,它不会发送到进程组。我最初的问题需要我终止进程组(在收到终止信号时终止我的整个管道,而不是离开杂散进程)——/tmp/trapper 中的陷阱只是为了避免 pgroup-signal 取消 /tmp/用它来捕猎。
    • (我在 bash 中错过的一件事是一种向所有“${PCHILDREN[@]}”发送信号的内置方式——我不知道是否可以捕获管道中的所有子节点,如 c1|c2|c3|c4。)
    • 检查ps -opid= --ppid=$$的输出 - 提示:当前进程的子进程(非递归...)
    【解决方案2】:

    似乎$() 确实使用单独的进程组/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
    

    请注意,“done”不会打印出来,不会捕获 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
    

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 2017-01-23
      • 1970-01-01
      • 2021-05-02
      • 1970-01-01
      • 1970-01-01
      • 2016-07-08
      • 2014-07-01
      • 1970-01-01
      相关资源
      最近更新 更多