systemd で特定のタイムスタンプでコマンドを実行するようにスケジュールする

systemd で特定のタイムスタンプでコマンドを実行するようにスケジュールする

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の現在のドキュメントでは、エポックからの秒数タイムスタンプの入力を直接サポートしていると示されています。この「@seconds」サポートは、systemd バージョン 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はローカル設定が保存される場所ですsystemd 用。

サンプルのタイマー ファイルは次のようになります。

[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 から定期的に削除することをお勧めします。

関連情報