スクリプト内に5分の信号をトラップできますか?私はこのようなものを想像します、
function dosomething {
echo "It's been 5 minutes."
}
trap dosomething SIGNAL-EVERY-5-MINUTES
while true
do
sleep 10
done
この例には意味がないことに注意してください。 x回ごとに何かをトラップすることが可能かどうかを尋ねるだけです。
EDIT: @ vinc17の回答に基づいて、メインシェルからのsleep
コマンドがUSR1
信号によって中断されていないことに気づきました。それが、私がやりたいことです。 。
#!/bin/bash
time=10
(
set -e
while true
do
sleep 30
# Since this is run as a subshell (instead of an external command),
# the parent pid is $$, not $PPID.
kill -USR1 $$
done
) &
finish() {
kill $!
echo "Closing."
exit 0
}
changetime() {
echo "Signal USR1 received."
time=$(( $RANDOM % 8 + 1))
}
trap changetime USR1
trap finish SIGINT
while true
do
echo "before sleep"
sleep $time
echo "after sleep"
done
出力、
before sleep
Signal USR1 received.
after sleep
before sleep
Signal USR1 received.
after sleep
before sleep
Signal USR1 received.
Closing.
EDIT2:上記の例を編集した結果、同じ出力が得られましたが、もう1つ問題があります。スリープ時間はUSR1
トラップ関数によって変更されます。そのため、現在、30秒ごとに1から8までのランダムな時間が選択されています。したがって、シグナルが時間を変更したときに、メインスクリプトからsleep
を強制終了する必要があります。私はそれが意味をなさないと主張しますが、それが可能かどうかを知る必要があります。
はい。最も簡単な方法は、質問で最初に説明したとおりにそれを行うことです。それはその一部です何か 5分後にプロセスにシグナルを送信するために、別の子プロセスを生成する必要があります。 @ vinc17の本からページを取り、スパンも5秒に短縮します。
trap 'ME=$$
: $( (sleep 5
ps -p $ME >/dev/null 2>&1 && {
echo hey >/dev/tty
kill -USR1 $ME
})&)
' USR1; kill -USR1 $$
そうすれば、ゾンビになるように要求するだけの長期的なプロセスはありません。代わりに、間隔ごとに親のPIDへの新しい参照を取得する新しい単一目的のカウンターがあります。また、親が離れてから死亡した場合に、子供が1つの仕事をしようとしないことを確認するために、少しチェックを組み込みます。
それを実行すると、5秒ごとに次のようになります。
hey
hey
hey
hey
hey
hey
hey
hey
hey
hey
この例でも、その間にターミナルがハングする可能性があります。そうしないと、プロセス全体をバックグラウンドで実行しようとしても何も起こりません。これは、/dev/tty
が保持されているためです。バックグラウンドですべてを実行する場合は、代わりにファイルを選択します。それ以外の場合は、直接stty
呼び出しを実行し、必要に応じてttyを再実行します。