web-dev-qa-db-ja.com

SIGINTが子プロセスに到達しないようにする

サーバーを実行するためのbashスクリプトがあります。これは通常、ユーザーがCtrl-Cを使用して終了します。終了時に、クリーンアップ関数を実行します。これは、2番目の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

...

現時点では、scpが終了する前の2番目のCtrl-Cにより、スクリプトが無期限にハングします。これは、SIGINTがbashスクリプトとscpプロセスの両方に送信されることと関係があることを理解していますが、なぜこれが原因でスクリプトがハングするのかではなく、途方に暮れています。クリーンアップが失敗するだけです。

だから私の質問は:

  1. これによりスクリプトがハングするのはなぜですか?
  2. SIGINTがscpおよびssh子プロセスに到達しないようにするにはどうすればよいですか?
4
Phydeaux

trap '' INTは、シェルとそのすべての子のSIGINTを無視することを目的としています。

しかし、stracescp出力を見ると、scpが上記のSIG_IGNをキャンセルする独自のSIGINTハンドラーをインストールしているように見えます。

SIGINTを取得しないようにする唯一の方法は、次のような別のプロセスグループで実行することです。

Perl -MPOSIX -e 'setpgid 0,0; exec @ARGV' scp...

または

(set -m; scp ... & wait)

または、後で設定を復元したい場合でも、Ctrl-CでSIGINTの送信を停止するようにttyドライバーに指示します(stty -isig、またはstty intr ''のみの場合は^Cなど)。

saved=$(stty -g)
stty intr ''
scp ...
stty "$saved"
8