Bash 脚本没有看到 SIGHUP?

Rog*_*mbe 14 bash signals

我有以下脚本:

#!/bin/bash
echo "We are $$"
trap "echo HUP" SIGHUP
cat    # wait indefinitely
Run Code Online (Sandbox Code Playgroud)

当我发送SIGHUP(使用kill -HUP pid)时,没有任何反应。

如果我稍微更改脚本:

#!/bin/bash
echo "We are $$"
trap "kill -- -$BASHPID" EXIT    # add this
trap "echo HUP" SIGHUP
cat    # wait indefinitely
Run Code Online (Sandbox Code Playgroud)

...然后脚本在echo HUP退出时做正确的事情(当我按 Ctrl+C 时):

roger@roger-pc:~ $ ./hupper.sh 
We are 6233
^CHUP
Run Code Online (Sandbox Code Playgroud)

这是怎么回事?我应该如何SIGHUP向此脚本发送信号(不一定必须是)?

xhi*_*nne 23

Bash 手册指出:

如果 bash 正在等待命令完成并接收到设置了陷阱的信号,则在命令完成之前不会执行陷阱。

这意味着尽管bash在您发送信号时收到了信号,但只有在以下情况下才会调用 SIGHUP 上的陷阱cat结束。

如果这种行为是不可取的,那么要么使用bash内置函数(例如,在循环中使用read+printf而不是cat),要么使用后台作业(请参阅Stéphane 的回答)。


Sté*_*las 9

@xhienne 已经解释了原因,但是如果您想让信号立即生效(而不是退出脚本),您可以将代码更改为:

#! /bin/bash -
interrupted=true
trap 'interrupted=true; echo HUP' HUP

{ cat <&3 3<&- & pid=$!; } 3<&0

while
  wait "$pid"
  ret=$?
  "$interrupted"
do
  interrupted=false
done
exit "$ret"
Run Code Online (Sandbox Code Playgroud)

文件描述符的小动作是解决bash将 stdin 重定向到/dev/null后台启动的命令这一事实。