防止 SIGINT 到达子进程

Phy*_*aux 4 bash process signals trap

我有一个用于运行服务器的 bash 脚本,该脚本通常由用户使用Ctrl-C. 在退出时,它运行一个清理函数,我不想被第二个中断Ctrl-C

#!/bin/bash

...

function cleanup {
    trap '' INT
    echo -n " Cleaning up..."
    scp $SRV:~/$DIR/server.log . && ssh -t $SRV "rm -rf ~/$DIR"
    echo " Finished."

    exit 0
}
trap cleanup EXIT

...
Run Code Online (Sandbox Code Playgroud)

目前,Ctrl-Cscp完成前一秒会导致脚本无限期挂起。我知道这与SIGINT发送到 bash 脚本和scp进程有关,但我不知道为什么这会导致脚本挂起,而不仅仅是导致清理失败。

所以我的问题是:

  1. 为什么这会导致脚本挂起?
  2. 如何防止到达的SIGINTscpssh子进程?

Sté*_*las 9

trap '' INT 旨在忽略 shell 及其所有子项的 SIGINT。

但是查看 上的strace输出scp,它看起来像是scp安装了自己的 SIGINT 处理程序,它取消了上面的 SIG_IGN。

阻止它获取 SIGINT 的唯一方法是在不同的进程组中运行它,例如:

perl -MPOSIX -e 'setpgid 0,0; exec @ARGV' scp...
Run Code Online (Sandbox Code Playgroud)

或者

(set -m; scp ... & wait)
Run Code Online (Sandbox Code Playgroud)

或者告诉TTY司机停车后按Ctrl-C发送SIGINT(像stty -isig,或stty intr ''^C单独的),但你会想事后恢复设置:

saved=$(stty -g)
stty intr ''
scp ...
stty "$saved"
Run Code Online (Sandbox Code Playgroud)