如何在 shell 腳本中判斷該腳本在掛起後是否繼續?

如何在 shell 腳本中判斷該腳本在掛起後是否繼續?

我有一個 shell 腳本,可以透過 cron/crontab 定期執行。我在那裡放了一個sleep命令幾分鐘:

sleep 5m # Waits 5 minutes.

我必須這樣做,因為隨後發生的操作取決於需要由其他(獨立)進程同步的檔案的一致狀態。

如果我的電腦從睡眠/掛起模式恢復,我不想繼續執行腳本(因為電腦可能會在 4 分 59 秒後喚醒,因此檔案尚未同步)。

如何在 shell 腳本中檢查從掛起喚醒的時間是否超過 5 分鐘?

(我的系統上的日期/var/log/pm-suspend.log似乎沒有更新)

答案1

首先,我們要注意的是,這sleep並沒有考慮暫停時間。

例如,如果您執行命令sleep 5m,然後掛起計算機,然後 4 分鐘後喚醒它,則該sleep命令將在啟動後 9 分鐘終止。它會休眠 5 分鐘(非暫停)。

考慮到這一點,我認為您根本不需要您正在尋找的那種技巧。你的問題暗示了相反的、不正確的假設,即一個sleep 5m命令可以在電腦暫停的 4 分 59 秒和 1 秒的喚醒時間中休眠。


話雖這麼說,讓我們看看一種可能的方法來判斷電腦是否在兩個時刻之間暫停。

如手冊中所述,有幾個系統時鐘clock_gettime(2)

一是CLOCK_MONOTONIC,這不計算停賽時間。它是一個以秒為單位的值,從某個任意的起點開始,表示電腦實際處於喚醒狀態的時間量。

還有另一種,CLOCK_REALTIME表示現實世界的時間。然而,如果調整時鐘,它很容易突然跳變,因此並不完全可靠。相反,讓我們使用CLOCK_BOOTTIME.這是一個以秒為單位的值,從某個任意起點(大概是系統的啟動時間)開始,包括電腦掛起的時間。

您可以使用以下命令列印這兩個值

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

(還有一種更簡單的語法來獲取單調時間,我特意選擇了適用於兩種時鐘的語法。)

在某個時刻,查詢這兩個值併計算它們的差異。在某個其他時間點再次執行此操作。

這兩個差異之間的差異給出了計算機在其間暫停的時間量。由於無法在完全相同的時刻查詢兩個值,因此存在一點測量誤差。

答案2

單程

上次恢復時間應該可以透過日誌系統取得systemd,如下所示:

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

因此,您可以將時間戳short-iso格式指派給變量,如下所示:

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

並添加五分鐘,同時將其轉換為 Unix 時間戳,如下所示:

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

並使用類似 (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

並使用類似於第一種方法的邏輯,根據您自己的自訂日誌檔案中的時間戳進行解析和評估。

注意:對於使用第二種方式執行需要/依賴網路連線的腳本,請先看:腳本的網路相關部分不會在 /lib/systemd/system-sleep 中執行

相關內容