Bashスクリプトでクロック信号をキャプチャできますか?

Bashスクリプトでクロック信号をキャプチャできますか?

スクリプトから5分の信号をキャプチャできますか?このような想像をしてみてください。

function dosomething {
   echo "It's been 5 minutes."
}

trap dosomething SIGNAL-EVERY-5-MINUTES

while true
do
    sleep 10
done

この例は意味がありません。 x回ごとに何かをキャプチャすることが可能かどうか尋ねてください。


編集する:sleep@vinc17の答えに基づいて、メインシェルのコマンドがシグナルによって中断されないことがわかりました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.

編集2:同じ出力を得るために上記の例を編集しましたが、困難が追加されました。USR1トラップ機能が睡眠時間を変更します。 30秒ごとに1から8の間でランダムな時間を選択してください。したがって、sleepシグナルが時間を変更した場合は、基本スクリプトを終了する必要があります。私はこれが言葉にならないと主張しますが、これが可能かどうかを知る必要があります。

ベストアンサー1

SIGALRMたとえば、x回ごとにシェルスクリプトにシグナルを送信し、そのシグナルをトラップするプロセスを実行できます。このプロセスは、以下を実行するスクリプトです。

set -e
while true
do
  sleep 300
  kill -ALRM $PPID
done

デフォルトのシェルスクリプトによって起動された場合。

デフォルトのシェルスクリプトは、不要になったときにプロセスを終了し、/またはpidがもう存在しない場合(ただし競合状態があるとき)にプロセスを終了する必要があります。

(修正済み)注:デフォルトのシェルスクリプトはこのコマンドを使用し、それが組み込まれていると信号と誤って対話する可能性がsleepあります。ALRMsleepsleep(3)使用alarm(2)。これsleepシェルユーティリティのPOSIXの説明また、その理由について次のように述べました。SIGALRM 信号によって省電力モードが中断されると、終了状態は 0 になります。このユーティリティのほとんどの実装は、要求された完了時間に正常に到達したことを知らせるために、この信号の到着に依存するためです。したがって、これらの実装では、この場合と成功した完了のケースを区別することはできません。他の実装では、要求された時間が経過するまで信号をキャプチャし、スリープモードに戻るか、通常の信号終了手順を提供できます。「特定の実装で発生する可能性のある問題を回避するSIGUSR1には。SIGUSR2SIGALRM

以下は、サブシェルを使用する例です。動作を見やすくするために、5分期間(sleep 300)を5秒期間(sleep 5)に置き換えました。

#!/bin/sh

{
  set -e
  while true
  do
    sleep 5
    # Since this is run as a subshell (instead of an external command),
    # the parent pid is $$, not $PPID.
    kill -USR1 $$
  done
} &

trap 'echo "Signal USR1 received."' USR1

while true
do
  date
  sleep 1
done

Ctrl-Cを使用してスクリプトを中断できます。これが発生すると、サブシェルは終了しませんが、pidが再利用されないとコマンドがkill失敗したため(kill: No such process)一定時間(ここでは5秒)後にサブシェルが自動的に終了します。

おすすめ記事