簡単なスクリプトがあります。
f=1 # initial value
loop(){
...
if [[ $f -eq 1 ]]
then
echo $msg1
f=2
(sleep $interval; loop) &
exit 1
elif [[ $f -eq 2 ]]
then
echo $msg2
f=1
(sleep $interval; loop) &
exit 2
fi
...
}
その目的は、これら2つのメッセージの間を順番に繰り返すことです。私はスクリプトがバックグラウンドにありたいので、通常のwhileループの代わりにこれをやっています。したがって、私の端末で起こると予想されるタスクは次のとおりです。
gt@gt:~./timer.sh
<msg1>
gt@gt:~<me running some other commands>
<some output>
gt@gt:~<as soon as $interval time gets over>
<msg2>
gt@gt:~<fresh prompt>
ご覧のとおり、通常のエコー出力が表示される場所にmsg2が表示されたら、その直後に新しいコマンド入力プロンプトを残す必要があります。しかし、実際に起こっていることは次のとおりです。
gt@gt:~./timer.sh
<msg1>
gt@gt:~<me running some other commands>
<some output>
gt@gt:~<msg2>
<same prompt is still waiting for input here>
この問題をどのように解決しますか?
#!/bin/bash
秒を実行して設定することで、sleep=3
この問題をローカルで確認できます。
ベストアンサー1
タイマースクリプトがSIGINT
親プロセス($PPID
)にシグナルを送信するようにします。
はい
#!/bin/bash
echo "Going to interrupt $PPID in 5 seconds"
sleep 5
echo "More output"
kill -SIGINT $PPID
sleep 5
このスクリプトが./script &
バックグラウンド()で実行されたら、出力を送信してスリープモードに切り替え、追加の出力を送信してプロンプトを強制的に再描画する必要があります。
スクリプトは再びスリープ状態になった後に終了します。
OPスクリプトの更新
f=1 # initial value
loop(){
...
if [[ $f -eq 1 ]]
then
echo $msg1
kill -SIGINT $PPID
f=2
(sleep $interval; loop) &
exit 1
elif [[ $f -eq 2 ]]
then
echo $msg2
kill -SIGINT $PPID
f=1
(sleep $interval; loop) &
exit 2
fi
...
}
シェルプロセスがシグナルによって中断されると、保留中の入力行は失われますが、コマンドプロンプトはタイマースクリプトの出力後に再描画されます。
編集する
サブスクリプトでこの動作を再現するには、呼び出し側スクリプトの親PID環境変数をサブスクリプトに渡します。
main.sh
...
./timer.sh $PPID
...
#exits
timer.sh
...
# Save the parent pid argument
gp=$1
...
# Replace instances of $PPID with $gp in timer.sh
...
kill -SIGINT $gp