
我想安排一個命令在特定時間運行,由 Unix 時間戳記標識。看起來這可以透過 systemd 來實現systemd-run
,但是它是如何運作的呢?如果在調度命令時機器斷電或暫停,那麼調度的命令會發生什麼情況?
at
相關問題:使用from做同樣的事情atd
(需要將時間戳解析回日期):是否可以使用 at 指令安排作業在給定時間戳運行?
答案1
systemd-run
可以安排命令在特定時間運行,只要:
- 系統在此之前不會斷電,因為它會將瞬態計時器和服務檔案寫入 /run,該檔案在重新啟動時會被清除,並且
- 系統在該特定時間內不會暫停,除非您使用「WakeSystem」選項(請參閱下文)。
有關重新啟動持久選項,請參閱下文。
一個簡單的例子systemd-run
:
# generate an arbitrary timestamp, in seconds-since-the-epoch
timestamp=$(date -d 'now + 42 seconds' +%s)
systemd-run --on-calendar "$(date -d @"$timestamp" +'%F %T')" \
--timer-property=AccuracySec=1us \
touch /tmp/done
systemd-run
使用自紀元以來的秒數時間戳記的重要部分是:
- 使用
--on-calendar
和 - 在這裡,使用 GNU date 將紀元時間戳以來的秒數轉換為
systemd-run
可以理解的格式。您可以自行輸入或轉換時間戳,只要結果在OnCalendar 可以理解的格式。
OnCalendar 的目前文件表明它直接支援自紀元時間戳以來的秒數輸入。添加了“@秒”支持系統版本 234(在該頁面中搜尋該文件src/basic/calendarspec.c
)提交 d80e5b7。您的 systemd 版本可能早於此變更;舉些例子:
- RHEL 7從systemd 208開始,後來升級到版本219; RHEL 8 使用版本 239 (參考)。
- Debian 8 使用版本 215,Debian 9 使用版本 232,Debian 10 使用版本 241(參考)。
- Ubuntu 16.04 LTS 的版本為 229,Ubuntu 17.10 的版本為 234,Ubuntu 18.04 LTS 的版本為 237(參考)。
使用足夠新的 systemd 版本,您可以使用以下呼叫:
timestamp=$(date -d 'now + 42 seconds' +%s)
systemd-run --on-calendar "@${timestamp}" \
--timer-property=AccuracySec=1us \
touch /tmp/done
我還展示了一個AccuracySec 的計時器屬性,預設為 1 分鐘,您應該根據文件調整其值:
為了優化功耗,請確保將該值設定得盡可能高並根據需要設定得盡可能低。
我還沒有測試過它,但還有一個名為的計時器選項WakeSystem
:
使系統從掛起狀態恢復(如果系統處於掛起狀態且系統支援此操作)。請注意,此選項僅確保系統在適當的時間恢復,而不會在任何要完成的工作完成後再次暫停系統。
您可以將其整合到上面,如下所示:
timestamp=$(date -d 'now + 42 seconds' +%s)
systemd-run --on-calendar "$(date -d @"$timestamp" +'%F %T')" \
--timer-property=AccuracySec=1us \
--timer-property=WakeSystem=true \
touch /tmp/done
要求 systemd 在某個時間點運行命令,其方式重啟後仍然存在,並且獨立於任何特定的登入會話,您需要將計時器和服務單元文件放在/etc/systemd/system/
./etc/systemd/system 是儲存本地配置的位置對於系統。
範例計時器檔案如下:
[Timer]
AccuracySec=1us
[Unit]
Description=2020-01-22 09:50:00 timer
[Timer]
OnCalendar=2020-01-22 09:50:00
範例服務文件是:
[Unit]
Description=my 2020-01-22 09:50:00 service
[Service]
ExecStart=
ExecStart=@/usr/bin/bash "/usr/bin/bash" "-c" "echo 2020-01-22 09:50:00 timer and service ran > /tmp/done"
然後,您可以透過重新載入檔案來通知 systemd 有關這些檔案的資訊:
systemctl daemon-reload
...然後啟用計時器:
systemctl enable foo.timer
....然後啟動計時器:
systemctl start foo.timer
一旦過期的計時器和服務單元的時間過去,您可能需要定期從 /etc/systemd/system 中刪除它們。