防止将 CTRL+C 发送到从 Bash 脚本调用的进程

Prevent CTRL+C being sent to process called from a Bash script

这是我正在处理的一些代码的简化版本:

#!/bin/bash

term() {
  echo ctrl c pressed!
  # perform cleanup - don't exit immediately
}
trap term SIGINT

sleep 100 &
wait $!

如您所见,我想捕获 CTRL+C / SIGINT 并使用自定义处理这些函数执行一些清理操作,而不是立即退出。

然而,在按下 CTRL+C 后,实际发生的事情似乎是,而我看到 ctrl c pressed! 是按预期回显,wait 命令也被终止,这是我不希望发生的(我的部分清理操作稍后会终止 sleep,但首先会做一些其他事情)。有什么办法可以防止这种情况,即停止将 CTRL+C 输入发送到 wait 命令?

您可以通过首先忽略 trap:

的信号来阻止从 Bash 脚本调用的进程接收信号
#!/bin/bash
# Cannot be interrupted
( trap '' INT; exec sleep 10; )

但是,只有父进程可以等待其子进程,因此 wait 是一个 shell 内置进程,而不是新进程。因此这不适用。

相反,只需在 wait 中断后重新启动它:

#!/bin/bash
n=0
term() {
  echo "ctrl c pressed!"
  n=$((n+1))
}
trap term INT


sleep 100 &

while
  wait "$!"
  [ "$?" -eq 130 ]   # Sigint results in exit code 128+2
do
  if [ "$n" -ge 3 ]
  then
    echo "Jeez, fine"
    exit 1
  fi
done

我最终使用了@thatotherguy 建议的修改版本:

#!/bin/bash

term() {
  echo ctrl c pressed!
  # perform cleanup - don't exit immediately
}
trap term SIGINT

sleep 100 &
pid=$!

while ps -p $pid > /dev/null; do
  wait $pid
done

这将检查进程是否仍然是 运行,如果是,则再次运行 wait