sh -cで実行されたスクリプトはシグナルを受信しません。

sh -cで実行されたスクリプトはシグナルを受信しません。

時間がかかるコマンドを実行する前に3分間待機するスクリプトがあります。SIGINT長期実行コマンドを実行するのではなくスリープ状態でのみ受信した場合は、スクリプトを終了したいと思います。これは、時間のかかるコマンドのインスタンスが与えられた瞬間に1つだけ実行されるようにするためです。

これはmyscript.sh

#!/bin/bash

trap 'exit' INT
sleep 180 &
wait
trap '' INT

# Long running command
/etc/init.d/myd sync 

実行方法は次のとおりです。

kill -INT `pgrep myscript.sh` 2>/dev/null; ! pgrep -x "myscript.sh" > /dev/null && /opt/my/scripts/myscript.sh &

今後の実行でも期待どおりに動作します。つまり

  1. 実行していない場合はスクリプトを実行します。

  2. SIGINTスクリプトが実行されているがまだ長期実行コマンドを実行していない場合は、スクリプトを停止(send)してから再起動してください。

  3. スクリプトが実行中で長期実行コマンドを実行している場合は、何もしません。

しかし、以下を使用して同じライナーを実行する場合sh -c

sh -c 'kill -INT `pgrep myscript.sh` 2>/dev/null; ! pgrep -x "myscript.sh" > /dev/null && /opt/my/scripts/myscript.sh &'

以前に実行されたことがないと、スクリプトは起動しますが停止できないようです。

なぜこれがうまくいかないのか分かりません。

答え1

したがって、コマンドパスを少し変更する必要がありましたが、これがあなたの要件を満たしていると思います。ただし、まずスクリプトを変更する必要があります。

#!/bin/bash
# Make sure we know when the trap fires. 
trap 'printf "quiting with return code %d\n" "$?"; exit' INT
sleep 180 &
wait
trap '' INT

# Long running command
/usr/bin/sleep 86400

その後、2番目のコマンドを次のように変更して目的の結果を得ることができます。

sh -c 'set -x; (exec kill --verbose -INT $(pgrep myscript.sh) 2>/dev/null); ! pgrep -x "myscript.sh" > /dev/null && /tmp/myscript.sh &'

このように実行すると、期待どおりに動作することを確認した後、スクリプトの最初のトラップからprintfステートメントを削除し、次のコマンドを実行できます。

 sh -c '(exec kill -INT $(pgrep myscript.sh) 2>/dev/null); ! pgrep -x "myscript.sh" > /dev/null && /tmp/myscript.sh &'

上記のコマンドの最初のステートメントに括弧がなく、サブシェルで実行される場合、そのプロセスは置き換えられ、2番目のステートメントshkill実行されません。

関連情報