ファイルを繰り返すシェルスクリプトがあります。各ファイルの処理には数時間かかることがあります(CPU / GPU制限)。場合によっては、ファイルの処理が完了したら、ループの終わりで実行を一時停止し、後で再開できるようにしたい場合があります。 Ctrl-zを押してからを使用して一時停止するのと似ていますfg
が、以前は現在のループを完了したいと思います。実際に背景を一時停止/入力します。
デフォルトでは、スクリプトがctrl-z(または同様のもの)を受け取ったときに停止する前に特定の行に達するのを待ちたいと思います。これをどのように達成しますか?
答え1
私は次のようなものを使用します:
#!/bin/bash
function catch_sig ()
{
interrupted=1
trap catch_sig SIGUSR1
}
interrupted=0
trap catch_sig SIGUSR1
echo "kill -s SIGUSR1 $$ to pause"
while [[ there is more to do ]] ; do
long_running_task
if [[ 1 -eq "$interrupted" ]] ; then
interrupted=0
read -p "You rang? " junk
fi
done
次に、他の端末からkill -s SIGUSR1
通知されるPIDを実行します。
man stty
使用したい信号があるかどうかを読んでください。読むman signal kill pkill bash
。
答え2
解決策
デフォルトでは、スクリプトがctrl-z(または同様のもの)を受け取ったときに停止する前に特定の行に達するのを待ちたいと思います。
私があなたなら、特定のファイルが存在するかどうか特定の行をチェックします。ファイルが存在する場合、スクリプトはSIGSTOPを自分に送信する必要があります。
[ -e /path/to/file ] && kill -s STOP "$$"
私がシグナルの代わりにファイルを使用する理由は、シグナルを元に戻すことができないためです(または少なくとも簡単ではありません)。ファイルの場合、これは簡単です。気が変わったらファイルを削除するだけでスクリプトは自動的に停止しません。
スクリプト自体が停止した後にSIGCONTを送信すると、続行されます。実際には、ジョブ制御が有効な対話型シェルでスクリプトを実行する可能性が高くなります。この場合、シェルはスクリプトが停止するタイミングを検出し、ユーザーが望むようにスクリプトをfg
実行できます。bg
スクリプトが自動的にファイルを削除しようとするか、ファイルをそのままにして次の反復で SIGSTOP を発生させるかどうかはユーザー次第です。あなたファイルを削除します。
注は+kill -s STOP "$$"
と同じではありません。キーストロークにより、端末は(他に設定されていない限り)全フォアグラウンドプロセスグループにSIGTSTP(SIGSTOPの代わりに)を送信します。スクリプトを解釈するシェルがそのプロセスグループのリーダーであると確信している場合は、次のことができます。スクリプトがプロセスグループ内の非同期プロセスを開始してそれを停止したい場合は、次にシグナルを送信します。そのグループは効果を持つでしょう。プロセスは、SIGSTOP(キャッチ、ブロック、または無視できない)またはSIGTSTP(可能)を受信したときに異なる動作をする可能性があります。必要に応じてコマンドを調整します。Ctrlzkill -s TSTP -- "-$$"
kill …
概念の証拠
次のスクリプトは、存在するかどうかに応じてそれ自体で停止しますが、/tmp/blocker
ループ反復の途中ではなく終了時にのみ停止しますfor
。
#!/bin/sh -
for i in 1 2 3 4 5; do
echo "processing $i"
sleep 5
echo "still processing"
sleep 5
echo "and processing some more"
sleep 5
echo "done processing $i"
[ -e /tmp/blocker ] && kill -s STOP "$$"
done