将 SIGINT 从键盘发送到 bash 中的管道命令



如果在 bash 中我在命令行上运行a | b | c | d然后按 ^C,哪个进程得到信号?

简而言之,他们都这样做。

设置管道时,shell 会创建一个进程组^C 被内核的行规则解释为用户中断当前在前台运行的进程组的请求。向进程组发送信号(如 SIGINT)会自动将信号传递到组中的所有进程。

我更喜欢实验:

#!/bin/bash
# FILE /tmp/bla.sh
# trap ctrl-c and call ctrl_c()
trap ctrl_c INT
MY_ID=$1 # Identifier for messages
function ctrl_c() {
    echo >&2 "GOODBYE $MY_ID"
    exit
}
# This will continue until interrupted, e.g. if the input/output get closed
cat
# If we somehow got to the end
echo >&2 "grace $MY_ID"

链接它们,运行和破坏它们

nitz@mars:~$ /tmp/bla.sh 1 | /tmp/bla.sh 2
^CGOODBYE 2
GOODBYE 1
0

如您所见,两次执行都得到了中断信号,这意味着它们都被杀死了。此外,他们输出他们被杀的顺序是随机的,例如:

nitz@mars:~$ /tmp/bla.sh 1 | /tmp/bla.sh 2 | /tmp/bla.sh 3 | /tmp/bla.sh 4
^CGOODBYE 2
GOODBYE 4
GOODBYE 1
GOODBYE 3

基于@Nitz的优秀(我也喜欢实验)答案,如果您不希望所有进程都获得信号,您可以使用 bash 进程替换(感谢这个答案)。

以下示例显示1进程确实会获取信号,但23进程不会。

$ /tmp/bla.sh 1 > >(/tmp/bla.sh 2 | /tmp/bla.sh 3)
^CGOODBYE 1
grace 2
grace 3

您也可以重定向 stderr,它仍然有效。

我的用例是尝试过滤作为 docker 容器入口点的命令的输出,但我不想弄乱主进程的信号处理。

编辑:某些命令组合似乎存在一些缓冲问题,但我不明白为什么。因此,这可能不适合您的用例。

# no buffering issues here
(echo 1; sleep 1; echo 2; sleep 2; echo 3) > >(cat)
(echo 1; sleep 1; echo 2; sleep 2; echo 3) > >(cat | cat | cat)
(echo 1; sleep 1; echo 2; sleep 2; echo 3) > >(cat | grep -v blah)
# no output until original command finishes for this *shrugs*
(echo 1; sleep 1; echo 2; sleep 2; echo 3) > >(grep -v blah | cat)

相关内容

  • 没有找到相关文章

最新更新