シェル スクリプトで、このスクリプトが中断後に続行されるかどうかを確認する方法を教えてください。

シェル スクリプトで、このスクリプトが中断後に続行されるかどうかを確認する方法を教えてください。

cron/crontab 経由で定期的に実行されるシェル スクリプトがあります。そこにsleep数分間コマンドを配置します。

sleep 5m # Waits 5 minutes.

その後のアクションは、他の(独立した)プロセスによって同期される必要があるファイルの一貫した状態に依存するため、そうする必要があります。

コンピュータがスリープ/サスペンド モードから復帰する場合、スクリプトの実行を続行したくありません (コンピュータは 4 分 59 秒後に起動する可能性があり、ファイルはまだ同期されていないため)。

シェル スクリプトで、サスペンドからの復帰が 5 分以上前であることを確認するにはどうすればよいでしょうか?

(私のシステムでは日付が/var/log/pm-suspend.log更新されていないようです)

答え1

まず第一に、sleep中断時間は考慮されないことに注意してください。

たとえば、コマンド を実行しsleep 5m、コンピューターをサスペンドし、4 分後に起動すると、コマンドはsleep起動してから 9 分後に終了します。サスペンドされていない 5 分間はスリープ状態になります。

これを念頭に置くと、あなたが探しているハックはまったく必要ないと思います。あなたの質問は、反対の誤った仮定、つまり、コマンドは、sleep 5mコンピューターがサスペンド状態にある 4 分 59 秒と起動状態の 1 秒の間スリープ状態を維持できるという仮定を暗示しています。


そうは言っても、2 つの瞬間の間にコンピューターがサスペンドされていたかどうかを確認する 1 つの方法を見てみましょう。

マニュアルに記載されているように、システム クロックはいくつかありますclock_gettime(2)

1 つはCLOCK_MONOTONIC、サスペンド時間はカウントされないことです。これは、任意の開始点からの秒単位の値で、コンピューターが実際に起動していた時間を表します。

現実世界の時間を表す別の方法もありますCLOCK_REALTIME。ただし、時計が調整されると突然ジャンプする傾向があるため、完全に信頼できるわけではありません。代わりに を使用しましょうCLOCK_BOOTTIME。これは、コンピューターがサスペンドされていた時間を含む、任意の開始点 (おそらくシステムの起動時間) からの秒単位の値です。

これらの2つの値は次のようなコマンドで出力できます。

python3 -c 'import time; print(time.clock_gettime(time.CLOCK_MONOTONIC))'
python3 -c 'import time; print(time.clock_gettime(time.CLOCK_BOOTTIME))'

(単調な時間を取得するためのより単純な構文もありますが、私は意図的に両方の種類のクロックで機能する構文を選択しました。)

ある時点で、これら 2 つの値を照会し、その差を計算します。別の特定の時点で、これを再度実行します。

これら 2 つの差から、その間にコンピューターが一時停止していた時間の長さがわかります。2 つの値を正確に同時に照会することはできないため、多少の測定誤差が生じる可能性があります。

答え2

一方通行

systemd最終履歴書の時間は、次のようなジャーナル システムで確認できます。

journalctl -r | awk '/resume/ {print $0; exit}'

したがって、次のような形式でタイムスタンプをshort-iso変数に割り当てることができます。

lr="$(journalctl -r -o short-iso | awk '/resume/ {printf "%s", $1; exit}')"

次のようにして、これを Unix タイムスタンプに変換しながら 5 分を追加します。

lr5="$(date -d "$lr + 5 minutes" +'%s')"

そして、後のUnixタイムスタンプを現在のUnixタイムスタンプと比較/評価します(bash特定の構文):

if [[ "$(date +'%s')" -ge "$lr5" ]]
  then
    echo "Five minutes have passed since last resume."
    # Your command/s here
    fi

別の方法

次のテンプレートを使用してディレクトリの下にスクリプト ファイルを配置することで、独自のタイムスタンプを作成できます/lib/systemd/system-sleep/

#!/bin/sh

case "${1}" in
  pre)
    # Command(s)/script(s) to execute before system goes to sleep/hibernate
    # nothing
      ;;
  post)
    # Command(s)/script(s) to execute after system wakes up from sleep/hibernate
    # Save your timestamp e.g.:
    # /bin/date +'%s' > /home/user/timestamp.log
      ;;
esac

そして、最初の方法と同様のロジックを使用して、独自のカスタム ログ ファイルのタイムスタンプに基づいて解析および評価します。

知らせ: ネットワーク接続を必要とする/ネットワーク接続に依存するスクリプトを実行する 2 番目の方法を使用する場合は、まず以下を参照してください。スクリプトのネットワーク関連部分は /lib/systemd/system-sleep では実行されません

関連情報