「Systemd/タイマー」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(校正(でき・出来))
 
(6人の利用者による、間の19版が非表示)
1行目: 1行目:
 
{{Lowercase title}}
 
{{Lowercase title}}
[[Category:デーモンとシステムサービス]]
+
[[Category:システム管理]]
  +
[[de:Systemd/Timers]]
[[Category:ブートプロセス]]
 
 
[[en:Systemd/Timers]]
 
[[en:Systemd/Timers]]
  +
[[es:Systemd/Timers]]
 
[[fr:Systemd/cron]]
 
[[fr:Systemd/cron]]
[[zh-CN:Systemd/Timers]]
+
[[pt:Systemd/Timers]]
  +
[[ru:Systemd (Русский)/Timers]]
  +
[[zh-hans:Systemd/Timers]]
 
{{Related articles start}}
 
{{Related articles start}}
 
{{Related|systemd}}
 
{{Related|systemd}}
 
{{Related|systemd/ユーザー}}
 
{{Related|systemd/ユーザー}}
{{Related3|systemd/Services|systemd/サービス}}
 
 
{{Related|systemd FAQ}}
 
{{Related|systemd FAQ}}
 
{{Related|cron}}
 
{{Related|cron}}
16行目: 18行目:
 
== タイマーユニット ==
 
== タイマーユニット ==
   
タイマーは拡張子が {{ic|.timer}} の ''systemd'' のユニットファイルです。他の[[systemd#カスタム .service ファイルを書く|ユニット設定ファイル]]と似ていますが特別に {{ic|[Timer]}} セクションが存在します。{{ic|[Timer]}} セクションにはタイマーが作動する時間と処理を定義します。タイマーには2つのタイプがあり、どちらか一つを使って定義されます:
+
タイマーは拡張子が {{ic|.timer}} の ''systemd'' のユニットファイルです。他の [[systemd#ユニットファイル|ユニット設定ファイル]] と似ていますが特別に {{ic|[Timer]}} セクションが存在します。{{ic|[Timer]}} セクションにはタイマーが作動する時間と処理を定義します。タイマーには2つのタイプがあり、どちらか一つを使って定義されます:
   
* '''モノトニックタイマー'''は刻々と変わる開始点と相応したタイムスパンの後に作動します。様々なモノトニックタイマーが存在しますがどれも次のような形式です: {{ic|1=On''Type''Sec=}}{{ic|OnBootSec}} と {{ic|OnActiveSec}} は全てのモノトニックタイマーで共通です。
+
* '''モノトニックタイマー''' は刻々と変わる開始点と相応したタイムスパンの後に作動します。様々なモノトニックタイマーが存在しますがどれも次のような形式です: {{ic|1=On''Type''Sec=}} {{ic|OnBootSec}} と {{ic|OnActiveSec}} は全てのモノトニックタイマーで共通です。
 
* '''リアルタイムタイマー''' (別名ウォールクロックタイマー) は (cron のジョブと同じように) カレンダーイベントにあわせて作動します。{{ic|1=OnCalendar=}} オプションを使って定義を行います。
 
* '''リアルタイムタイマー''' (別名ウォールクロックタイマー) は (cron のジョブと同じように) カレンダーイベントにあわせて作動します。{{ic|1=OnCalendar=}} オプションを使って定義を行います。
   
タイマーのオプションについては {{ic|systemd.timer(5)}} の [[man ページ]]で説明されています。カレンダーイベントやタイムスパンの引数構文については {{ic|systemd.time(7)}} の [[man ページ]]で説明されています。
+
タイマーのオプションについては {{man|5|systemd.timer}} の [[man ページ]] で説明されています。カレンダーイベントやタイムスパンの引数構文については {{man|7|systemd.time}} の [[man ページ]] で説明されています。
  +
  +
{{Note|''systemd'' は、ブート後にアクティブにする必要があるすべてのタイマーを設定するターゲット {{ic|timers.target}} を提供します (詳細については、{{man|7|systemd.special}} を参照してください) これを使用するには、タイマーの {{ic|[Install]}} セクションに {{ic|1=WantedBy=timers.target}} を追加し、タイマーユニットを [[有効化]] します。}}
   
 
== サービスユニット ==
 
== サービスユニット ==
38行目: 42行目:
   
 
{{Note|
 
{{Note|
  +
* (有効でないタイマーも含めて) 全てのタイマーを確認したい場合、{{ic|systemctl list-timers --all}} を使って下さい。
 
* タイマーによって実行するサービスの状態は、今現在作動しているのでない限り、inactive になります。
 
* タイマーによって実行するサービスの状態は、今現在作動しているのでない限り、inactive になります。
* タイマーがズレる場合は、{{ic|/var/lib/systemd/timers}} にある {{ic|stamp-*}} ファイルを削除してみてください。stamp ファイルはタイマーが実行された最後の時刻を記録しており、ファイルを削除することでタイマーの次の作動時に systemd が再構成を行います。
+
* タイマーがズレる場合は、{{ic|/var/lib/systemd/timers}} もしくは {{ic|~/.local/share/systemd/}} にある {{ic|stamp-*}} ファイルを削除してみてください。stamp ファイルはタイマーが実行された最後の時刻を記録しており、ファイルを削除することでタイマーの次の作動時に systemd が再構成を行います。
 
}}
 
}}
   
64行目: 69行目:
 
=== リアルタイムタイマー ===
 
=== リアルタイムタイマー ===
   
一週間ごとに起動するタイマー (月曜日の午前12:00に実行)。システムの電源が切られていたなどの理由で、最後の起動時間を過ぎていた場合、すぐに実行されます ({{ic||1=Persistent=true}} オプション):
+
一週間ごとに起動するタイマー (月曜日の午前12:00に実行)。システムの電源が切られていたなどの理由で、最後の起動時間を過ぎていた場合、すぐに実行されます ({{ic|1=Persistent=true}} オプション):
   
 
{{hc|/etc/systemd/system/foo.timer|<nowiki>
 
{{hc|/etc/systemd/system/foo.timer|<nowiki>
77行目: 82行目:
 
WantedBy=timers.target</nowiki>}}
 
WantedBy=timers.target</nowiki>}}
   
  +
もっと細かく日時を指定する必要がある場合、次の形式で {{ic|OnCalendar}} イベントを制御できます: {{ic|DayOfWeek Year-Month-Day Hour:Minute:Second}}。アスタリスクをワイルドカードとして使うことができ、カンマで複数の日時を指定することができます。値を {{ic|..}} で区切ることで連続的に日程を指定することも可能です。
{{Tip|{{ic|daily}} や {{ic|weekly}} などの特殊なイベントの表現は''特定の起動時間''を示しているため、同じカレンダーイベントが設定されているタイマーがあった場合、同時に起動します。そのようなことが発生すると、タイマーのサービスがシステムリソースを取り合って、システムパフォーマンスが落ち込む可能性があります。{{ic|1=OnCalendar=Wed, 23:15}} のような特定のイベントで起動するタイマーを使うときはよく考えてからにしてください。[[#注意事項]]を参照。}}
 
  +
  +
例えば、以下の場合、毎月の1日から4日まで、月曜日か火曜日の場合にのみ、午後0時にサービスを実行します:
  +
  +
OnCalendar=Mon,Tue *-*-01..04 12:00:00
  +
  +
毎月第1土曜日にサービスを実行したい場合は以下のようになります:
  +
  +
OnCalendar=Sat *-*-1..7 18:00:00
  +
  +
毎朝4時に実行したい場合は以下のようになります:
  +
  +
OnCalendar=*-*-* 4:00:00
  +
  +
{{ic|OnCalendar}} は複数指定でき、複数の異なるタイミングでサービスを実行できます。次の例では、平日の22:30および土日の20:00に実行されます:
  +
  +
OnCalendar=Mon..Fri 22:30
  +
OnCalendar=Sat,Sun 20:00
  +
  +
ディレクティブの最後にタイムゾーンを指定することもできます (受け入れられる値をリストするには、{{ic|timedatectl list-timezones}} を使用します。)
  +
  +
OnCalendar=*-*-* 02:00:00 Europe/Paris
  +
  +
詳しくは {{man|7|systemd.time}} を見てください。
  +
  +
{{Tip|
  +
* {{ic|OnCalendar}} の日時の指定方法は ''systemd-analyze'' ユーティリティの {{ic|calendar}} オプションを使用することでテストすることができます。タイマーユニットで使用したときに次に実行される日時も確認できます。例えば、{{ic|systemd-analyze calendar weekly}} や {{ic|systemd-analyze calendar "Mon,Tue *-*-01..04 12:00:00"}} のようにコマンドを実行することでテストできます。
  +
* {{Pkg|libfaketime}} でインストールできる {{ic|faketime}} コマンドを使うと、これらのコマンドを使ったいろいろなシナリオをテストするのに便利です。
  +
* {{ic|daily}} や {{ic|weekly}} などの特殊なイベントの表現は''特定の起動時間''を示しているため、同じカレンダーイベントが設定されているタイマーがあった場合、同時に起動します。そのようなことが発生すると、タイマーのサービスがシステムリソースを取り合って、システムパフォーマンスが落ち込む可能性があります。このような問題は {{ic|RandomizedDelaySec}} オプションを使用してタイマーの起動時間を散らすことで解決できます。{{man|5|systemd.timer}} を参照してください。
  +
* {{ic|AccuracySec}} のデフォルト値 ''1m'' の不正確さを避けるために、オプション {{ic|1=AccuracySec=1us}} を [Timer] セクションに追加します。{{man|5|systemd.timer}} も参照してください。
  +
* 一部のオプション ({{ic|WakeSystem}}) は、特定のシステム機能を必要とし、タイマーの開始を妨げる場合があり、その結果、次のエラーメッセージが表示されます: "Failed to enter waiting state: Operation not supported" そして "Failed with result 'resources'."
  +
}}
  +
  +
== 一時的な .timer ユニット ==
  +
  +
{{ic|systemd-run}} を使うことで一時的な {{ic|.timer}} ユニットを作ることができます。サービスファイルを作成しなくても、特定時刻にコマンドが実行されるように設定することが可能です。例えば、以下のコマンドは30秒後にファイルを作成します:
  +
  +
# systemd-run --on-active=30 /bin/touch /tmp/foo
  +
  +
タイマーファイルが存在しない既存のサービスファイルを指定することもできます。例えば、以下のコマンドは12.5時間後に {{ic|''someunit''.service}} という名前の systemd ユニットを起動します:
  +
  +
# systemd-run --on-active="12h 30m" --unit ''someunit''.service
  +
  +
詳しくは {{man|1|systemd-run}} を見てください。
   
 
== cron を置き換える ==
 
== cron を置き換える ==
88行目: 136行目:
   
 
* タイマーとは別個にジョブを実行することが簡単にできます。これによってデバッグが楽になります。
 
* タイマーとは別個にジョブを実行することが簡単にできます。これによってデバッグが楽になります。
* 特定の環境で動作するようにジョブを設定することができます ({{ic|systemd.exec(5)}} [[man page|man ページ]]を参照)。
+
* 特定の環境で動作するようにジョブを設定することができます ({{man|5|systemd.exec}} [[man ページ]]を参照)。
* ジョブを [[cgroups|cgroups]] の支配下に置けます。
+
* ジョブを [[cgroups]] の支配下に置けます。
 
* 他の ''systemd'' ユニットに依存するようにジョブを設定できます。
 
* 他の ''systemd'' ユニットに依存するようにジョブを設定できます。
 
* ''systemd'' の journal でジョブが記録されるのでデバッグが簡単です。
 
* ''systemd'' の journal でジョブが記録されるのでデバッグが簡単です。
99行目: 147行目:
 
* 冗長性: ''systemd'' を使って定期的なジョブを設定するには2つのファイルを作成して2回 {{ic|systemctl}} コマンドを実行します。それに対して crontab には一行を追加するだけです。
 
* 冗長性: ''systemd'' を使って定期的なジョブを設定するには2つのファイルを作成して2回 {{ic|systemctl}} コマンドを実行します。それに対して crontab には一行を追加するだけです。
 
* メール: ジョブが失敗した時にメールを送信する cron の {{ic|MAILTO}} と同等なものは存在しません。ただし各サービスに {{ic|1=OnFailure=}} オプションを使うことで同じような機能を設定することはできます。
 
* メール: ジョブが失敗した時にメールを送信する cron の {{ic|MAILTO}} と同等なものは存在しません。ただし各サービスに {{ic|1=OnFailure=}} オプションを使うことで同じような機能を設定することはできます。
* ランダム遅延: インターバルを指定してタイマーの実行をランダムに分散する cron の {{ic|RANDOM_DELAY}} と同じ機能はありません ([https://bugs.freedesktop.org/show_bug.cgi?id=82084 バグレポート]や[https://wiki.archlinux.org/index.php?title=Talk:Systemd/Timers&oldid=356408#Parallelization_section_is_confusing テスト結果]を参照)。同時に実行して欲しくないサービスには、手動でオーバーラップを少なくするようにタイマーを設定する必要があります。
 
 
:{{note|タイマーを自動的にずらすには {{ic|AccuracySec}} オプションが役に立つかもしれません。ただし"全てのローカルなタイマーユニット間で同期が行われる"ので注意してください ({{ic|systemd.timer(5)}})。言い換えれば、{{ic|AccuracySec}} は全てのタイマーの作動時間を同じ分だけずらします。例えば、{{ic|1=AccuracySec=15m}} を使っている {{ic|1=OnCalendar=daily}} のタイマーユニットは全て、00:00 から 00:15 の間の同一時刻に関連するサービスを起動します。
 
   
 
=== MAILTO ===
 
=== MAILTO ===
   
Cron の {{ic|MAILTO}} のように、systemd で、ユニットが失敗したときにメールを送信するように設定できます。それにはまず2つのファイルが必要です: メールを送信するための実行可能ファイルと、実行可能ファイルを起動するための ''.service''。以下の例では、{{ic|sendmail}} を使用するシェルスクリプトが実行可能ファイルになっています:
+
Cron の {{ic|MAILTO}} のように、systemd で、ユニットが失敗したときにメールを送信するように設定できます。それにはまず2つのファイルが必要です: メールを送信するための実行可能ファイルと、実行可能ファイルを起動するための ''.service''。以下の例では、{{ic|sendmail}} ({{ic|smtp-forwarder}} を含むパッケージにはすべて含まれています) を使用するシェルスクリプトが実行可能ファイルになっています:
   
 
{{hc|/usr/local/bin/systemd-email|<nowiki>#!/bin/bash
 
{{hc|/usr/local/bin/systemd-email|<nowiki>#!/bin/bash
121行目: 166行目:
 
どんな実行可能ファイルを使うのであれ、上記のシェルスクリプトのように、最低でも2つの引数が必要になります: 送信先のアドレスと状態を取得するユニットファイルです。以下の ''.service'' はそれらの引数を渡します:
 
どんな実行可能ファイルを使うのであれ、上記のシェルスクリプトのように、最低でも2つの引数が必要になります: 送信先のアドレスと状態を取得するユニットファイルです。以下の ''.service'' はそれらの引数を渡します:
   
{{hc|/etc/systemd/system/status-email-user1@.service|<nowiki>[Unit]
+
{{hc|/etc/systemd/system/status-email-''user''@.service|2=[Unit]
Description=status email for %I to user1
+
Description=status email for %i to ''user''
   
 
[Service]
 
[Service]
 
Type=oneshot
 
Type=oneshot
ExecStart=/usr/local/bin/systemd-email user1@mailhost %i
+
ExecStart=/usr/local/bin/systemd-email ''address'' %i
 
User=nobody
 
User=nobody
Group=systemd-journal
+
Group=systemd-journal}}
</nowiki>}}
 
   
メールを送信するユニットがインスタンスパラメなっていることに気づいて下さい。これによってユニットでメールを送信するのも使るようになっていますただしメールの取人はハードコードされています (ユニットテプレートが使用できるパラメータは一つだけのため)。メールを様々なころに送りたい場合は複数のサービスを作成す必要あります。サービス作成たら、メールがちゃんと受け取れるかどうかテストてみてください:
+
{{ic|''user''}} はメールを送信するユーザーに、{{ic|''address''}} はユーザーのメールアドレス置き換えてください。受信者はハードコードされますが、イスタンスパラメータとしてユニットファイルを渡すこで、上記のサービスだけで他のユニットのメールも送ことできます。{{ic|status-email-''user''@dbus.service}} [[systemd#ユニットを使う|起動]]、メールが受け取れることを確認してください
   
  +
問題ないようでしたら、メールを送って欲しいユニットの {{ic|[Unit]}} セクションに {{ic|1=OnFailure=status-email-''user''@%n.service}} を追加してください。{{ic|%n}} はユニットの名前をテンプレートに指定します。
{{bc|# systemctl start status-email-user1@dbus.service}}
 
   
  +
{{note|
問題ないようでしたら、メールを送って欲しいユニットの {{ic|[Unit]}} セクションに {{ic|1=OnFailure=status-email-user1@%n.service}} を追加してください。{{ic|%n}} はユニットの名前をテンプレートに指定します。
 
  +
*[[SSMTP#セキュリティ]] にしたがって SSMTP を設定した場合、ユーザー {{ic|nobody}} は {{ic|/etc/ssmtp/ssmtp.conf}} にアクセスすることができず、{{ic|systemctl start status-email-''user''@dbus.service}} コマンドは失敗します。{{ic|status-email-''user''@.service}} モジュールの User に {{ic|root}} を使うことでこれを回避できます。
  +
* メールスクリプトで {{ic|mail -s somelogs ''address''}} を使用すると、{{ic|mail}} はフォークして、systemd はスクリプトの終了を確認したときに mail プロセスを終了します。{{ic|mail -Ssendwait -s somelogs ''address''}} として mail がフォークしないようにしてください。}}
   
 
=== crontab を使用する ===
 
=== crontab を使用する ===
   
crontab を使って定期的なサービスを管理するツールとして {{aur|systemd-crontab-generator}} と {{aur|systemd-cron}} があります。どちらも [[AUR]] からインストールすることができます。これらのツールには systemd に存在しない {{ic|MAILTO}} と {{ic|RANDOM_DELAY}} 機能が実装されています。
+
crontab を使って定期的なサービスを管理するツールとして {{aur|systemd-cron-next}} と {{aur|systemd-cron}} があります。どちらも [[AUR]] からインストールすることができます。これらのツールには systemd に存在しない {{ic|MAILTO}} 機能が実装されています。
   
 
もし、スケジュールされたジョブをまとめて見れるから crontab が好きだという場合は、{{ic|systemctl}} でそれと同じことが可能です。[[#管理]] を見て下さい。
 
もし、スケジュールされたジョブをまとめて見れるから crontab が好きだという場合は、{{ic|systemctl}} でそれと同じことが可能です。[[#管理]] を見て下さい。
  +
  +
=== 手動で行う ===
  +
  +
既存の crontab から移行する以外に、cron と同じ周期を使用することが望ましい場合があります。定期的に開始する各サービスのタイマーを作成するという面倒な作業を回避するには、[[systemd#ユニットを使う|テンプレートユニット]] を使用します。例:
  +
  +
{{hc|/etc/systemd/system/monthly@.timer|2=
  +
[Unit]
  +
Description=Monthly Timer for %i service
  +
  +
[Timer]
  +
OnCalendar=*-*-1 02:00:00
  +
AccuracySec=6h
  +
RandomizedDelaySec=1h
  +
Persistent=true
  +
Unit=%i.service
  +
  +
[Install]
  +
WantedBy=default.target
  +
}}
  +
  +
{{Note|タイマーの起動によってすべてのユニットが同時に開始されるのを避けるために、{{ic|AccuracySec}} だけでなく {{ic|RandomizedDelaySec}} を使用する重要性については、{{man|5|systemd.timer|OPTIONS}} を参照してください。}}
  +
  +
その後、{{ic|monthly@''unit_name''.timer}} を [[起動/有効化]] 行うだけで済みます。
  +
  +
{{Tip|テンプレートユニットはネストできます。たとえば、{{ic|monthly@btrfs-scrub@mnt-$(systemd-escape bbb76c63-e4ac-4e39-8897-a120c5d30686).timer}} を [[起動/有効化]] することができます。}}
  +
  +
== "有効期間" の処理 ==
  +
  +
一部のソフトウェアは、最後に実行されてからの経過時間を追跡します。たとえば、最後のダウンロードが 24 時間以内に終了した場合はデータベースの更新をブロックします。
  +
  +
デフォルトでは、タイマーは起動したタスクがいつ終了したかを追跡しません。これを回避するには、{{ic|OnUnitInactiveSeconds}} を使用できます:
  +
  +
{{hc|/etc/systemd/system/daily-inactive@.timer|2=
  +
[Unit]
  +
Description=Launch %i service 24hours after it deactivated
  +
  +
[Timer]
  +
'''OnUnitInactiveSec=1day1sec'''
  +
Unit=%i.service
  +
Persistent=true
  +
  +
[Install]
  +
WantedBy=default.target
  +
}}
  +
  +
{{Tip|{{ic|1=Restart=on-failure}} と {{ic|RestartSec}} を併用すると、失敗と成功の後に異なるスケジュールに従ってユニットを再実行することができます。{{man|5|systemd.service|OPTIONS}} を参照して下さい。}}
   
 
== 参照 ==
 
== 参照 ==
   
  +
* {{man|5|systemd.timer}}
* [http://www.freedesktop.org/software/systemd/man/systemd.timer.html systemd.timer man page] on freedesktop.org
 
 
* [https://fedoraproject.org/wiki/Features/SystemdCalendarTimers Fedora Project wiki] の ''systemd'' カレンダータイマーのページ
 
* [https://fedoraproject.org/wiki/Features/SystemdCalendarTimers Fedora Project wiki] の ''systemd'' カレンダータイマーのページ
 
* [https://wiki.gentoo.org/wiki/Systemd#Timer_services Gentoo wiki] の ''systemd'' タイマーサービスのセクション
 
* [https://wiki.gentoo.org/wiki/Systemd#Timer_services Gentoo wiki] の ''systemd'' タイマーサービスのセクション
* {{App|systemd-crontab-generator|crontab と anacrontab ファイルからタイマーとサービスを生成するツール|https://github.com/kstep/systemd-crontab-generator|{{Aur|systemd-crontab-generator}}}}
+
* {{App|systemd-cron-next|crontab と anacrontab ファイルからタイマーとサービスを生成するツール|https://github.com/systemd-cron/systemd-cron-next|{{Aur|systemd-cron-next}}}}
 
* {{App|systemd-cron|cron スクリプトを実行する systemd ユニットが入っています。''systemd-crontab-generator'' を使って crontab を変換。|https://github.com/systemd-cron/systemd-cron|{{Aur|systemd-cron}}}}
 
* {{App|systemd-cron|cron スクリプトを実行する systemd ユニットが入っています。''systemd-crontab-generator'' を使って crontab を変換。|https://github.com/systemd-cron/systemd-cron|{{Aur|systemd-cron}}}}

2024年7月10日 (水) 20:53時点における最新版

関連記事

タイマーは名前が .timer で終わる systemd のユニットファイルであり、.service ファイルやイベントを制御します。cron の代わりとしてタイマーを使うことができます (#cron を置き換える を読んで下さい)。タイマーにはカレンダー時刻のイベントとモノトニック時刻のイベントのサポートが入っており、さらに非同期に実行することも可能です。

タイマーユニット

タイマーは拡張子が .timersystemd のユニットファイルです。他の ユニット設定ファイル と似ていますが特別に [Timer] セクションが存在します。[Timer] セクションにはタイマーが作動する時間と処理を定義します。タイマーには2つのタイプがあり、どちらか一つを使って定義されます:

  • モノトニックタイマー は刻々と変わる開始点と相応したタイムスパンの後に作動します。様々なモノトニックタイマーが存在しますがどれも次のような形式です: OnTypeSec= OnBootSecOnActiveSec は全てのモノトニックタイマーで共通です。
  • リアルタイムタイマー (別名ウォールクロックタイマー) は (cron のジョブと同じように) カレンダーイベントにあわせて作動します。OnCalendar= オプションを使って定義を行います。

タイマーのオプションについては systemd.timer(5)man ページ で説明されています。カレンダーイベントやタイムスパンの引数構文については systemd.time(7)man ページ で説明されています。

ノート: systemd は、ブート後にアクティブにする必要があるすべてのタイマーを設定するターゲット timers.target を提供します (詳細については、systemd.special(7) を参照してください) これを使用するには、タイマーの [Install] セクションに WantedBy=timers.target を追加し、タイマーユニットを 有効化 します。

サービスユニット

それぞれの .timer ファイルには、対応する .service ファイルが存在します (例: foo.timerfoo.service)。.timer ファイルは .service ファイルを作動・制御します。.service[Install] セクションは必要ありません。有効にするのは timer ユニットだからです。必要ならば、タイマーの [Timer] セクションで Unit= オプションを使うことで別の名前のユニットを制御することもできます。

管理

timer ユニットを使用するには、他のユニットと同じように有効化・起動します。起動しているタイマーを全て表示するには、次を実行:

$ systemctl list-timers
NEXT                          LEFT        LAST                          PASSED     UNIT                         ACTIVATES
Thu 2014-07-10 19:37:03 CEST  11h left    Wed 2014-07-09 19:37:03 CEST  12h ago    systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
Fri 2014-07-11 00:00:00 CEST  15h left    Thu 2014-07-10 00:00:13 CEST  8h ago     logrotate.timer              logrotate.service
ノート:
  • (有効でないタイマーも含めて) 全てのタイマーを確認したい場合、systemctl list-timers --all を使って下さい。
  • タイマーによって実行するサービスの状態は、今現在作動しているのでない限り、inactive になります。
  • タイマーがズレる場合は、/var/lib/systemd/timers もしくは ~/.local/share/systemd/ にある stamp-* ファイルを削除してみてください。stamp ファイルはタイマーが実行された最後の時刻を記録しており、ファイルを削除することでタイマーの次の作動時に systemd が再構成を行います。

サンプル

タイマーを使用してサービスを実行するのにあたって、service ユニットファイルに変更を加える必要はありません。以下の例では foo.timer という名前のタイマーを使って foo.service を定期的に実行します。

モノトニックタイマー

起動15分後に実行され、システムが起動している間、一週間ごとに再度実行されるタイマー:

/etc/systemd/system/foo.timer
[Unit]
Description=Run foo weekly and on boot

[Timer]
OnBootSec=15min
OnUnitActiveSec=1w 

[Install]
WantedBy=timers.target

リアルタイムタイマー

一週間ごとに起動するタイマー (月曜日の午前12:00に実行)。システムの電源が切られていたなどの理由で、最後の起動時間を過ぎていた場合、すぐに実行されます (Persistent=true オプション):

/etc/systemd/system/foo.timer
[Unit]
Description=Run foo weekly

[Timer]
OnCalendar=weekly
Persistent=true     
 
[Install]
WantedBy=timers.target

もっと細かく日時を指定する必要がある場合、次の形式で OnCalendar イベントを制御できます: DayOfWeek Year-Month-Day Hour:Minute:Second。アスタリスクをワイルドカードとして使うことができ、カンマで複数の日時を指定することができます。値を .. で区切ることで連続的に日程を指定することも可能です。

例えば、以下の場合、毎月の1日から4日まで、月曜日か火曜日の場合にのみ、午後0時にサービスを実行します:

OnCalendar=Mon,Tue *-*-01..04 12:00:00

毎月第1土曜日にサービスを実行したい場合は以下のようになります:

OnCalendar=Sat *-*-1..7 18:00:00

毎朝4時に実行したい場合は以下のようになります:

OnCalendar=*-*-* 4:00:00

OnCalendar は複数指定でき、複数の異なるタイミングでサービスを実行できます。次の例では、平日の22:30および土日の20:00に実行されます:

OnCalendar=Mon..Fri 22:30
OnCalendar=Sat,Sun 20:00

ディレクティブの最後にタイムゾーンを指定することもできます (受け入れられる値をリストするには、timedatectl list-timezones を使用します。)

OnCalendar=*-*-* 02:00:00 Europe/Paris

詳しくは systemd.time(7) を見てください。

ヒント:
  • OnCalendar の日時の指定方法は systemd-analyze ユーティリティの calendar オプションを使用することでテストすることができます。タイマーユニットで使用したときに次に実行される日時も確認できます。例えば、systemd-analyze calendar weeklysystemd-analyze calendar "Mon,Tue *-*-01..04 12:00:00" のようにコマンドを実行することでテストできます。
  • libfaketime でインストールできる faketime コマンドを使うと、これらのコマンドを使ったいろいろなシナリオをテストするのに便利です。
  • dailyweekly などの特殊なイベントの表現は特定の起動時間を示しているため、同じカレンダーイベントが設定されているタイマーがあった場合、同時に起動します。そのようなことが発生すると、タイマーのサービスがシステムリソースを取り合って、システムパフォーマンスが落ち込む可能性があります。このような問題は RandomizedDelaySec オプションを使用してタイマーの起動時間を散らすことで解決できます。systemd.timer(5) を参照してください。
  • AccuracySec のデフォルト値 1m の不正確さを避けるために、オプション AccuracySec=1us を [Timer] セクションに追加します。systemd.timer(5) も参照してください。
  • 一部のオプション (WakeSystem) は、特定のシステム機能を必要とし、タイマーの開始を妨げる場合があり、その結果、次のエラーメッセージが表示されます: "Failed to enter waiting state: Operation not supported" そして "Failed with result 'resources'."

一時的な .timer ユニット

systemd-run を使うことで一時的な .timer ユニットを作ることができます。サービスファイルを作成しなくても、特定時刻にコマンドが実行されるように設定することが可能です。例えば、以下のコマンドは30秒後にファイルを作成します:

# systemd-run --on-active=30 /bin/touch /tmp/foo

タイマーファイルが存在しない既存のサービスファイルを指定することもできます。例えば、以下のコマンドは12.5時間後に someunit.service という名前の systemd ユニットを起動します:

# systemd-run --on-active="12h 30m" --unit someunit.service

詳しくは systemd-run(1) を見てください。

cron を置き換える

おそらく一番有名なジョブスケジューラは cron ですが、systemd のタイマーはその代替手段になりえます。

メリット

タイマーを使う主要なメリットは、それぞれのジョブが固有の systemd サービスを使うというところに根ざします。そのメリットには以下のようなものがあります:

  • タイマーとは別個にジョブを実行することが簡単にできます。これによってデバッグが楽になります。
  • 特定の環境で動作するようにジョブを設定することができます (systemd.exec(5) man ページを参照)。
  • ジョブを cgroups の支配下に置けます。
  • 他の systemd ユニットに依存するようにジョブを設定できます。
  • systemd の journal でジョブが記録されるのでデバッグが簡単です。

注意事項

cron では簡単にできることが、タイマーユニットを使用する場合、難しかったり不可能であったりすることがいくつか存在します。

  • 冗長性: systemd を使って定期的なジョブを設定するには2つのファイルを作成して2回 systemctl コマンドを実行します。それに対して crontab には一行を追加するだけです。
  • メール: ジョブが失敗した時にメールを送信する cron の MAILTO と同等なものは存在しません。ただし各サービスに OnFailure= オプションを使うことで同じような機能を設定することはできます。

MAILTO

Cron の MAILTO のように、systemd で、ユニットが失敗したときにメールを送信するように設定できます。それにはまず2つのファイルが必要です: メールを送信するための実行可能ファイルと、実行可能ファイルを起動するための .service。以下の例では、sendmail (smtp-forwarder を含むパッケージにはすべて含まれています) を使用するシェルスクリプトが実行可能ファイルになっています:

/usr/local/bin/systemd-email
#!/bin/bash

/usr/bin/sendmail -t <<ERRMAIL
To: $1
From: systemd <root@$HOSTNAME>
Subject: $2
Content-Transfer-Encoding: 8bit
Content-Type: text/plain; charset=UTF-8

$(systemctl status --full "$2")
ERRMAIL

どんな実行可能ファイルを使うのであれ、上記のシェルスクリプトのように、最低でも2つの引数が必要になります: 送信先のアドレスと状態を取得するユニットファイルです。以下の .service はそれらの引数を渡します:

/etc/systemd/system/status-email-user@.service
[Unit]
Description=status email for %i to user

[Service]
Type=oneshot
ExecStart=/usr/local/bin/systemd-email address %i
User=nobody
Group=systemd-journal

user はメールを送信するユーザーに、address はユーザーのメールアドレスに置き換えてください。受信者はハードコードされますが、インスタンスパラメータとしてユニットファイルを渡すことで、上記のサービスだけで他のユニットのメールも送ることができます。status-email-user@dbus.service起動して、メールが受け取れることを確認してください。

問題ないようでしたら、メールを送って欲しいユニットの [Unit] セクションに OnFailure=status-email-user@%n.service を追加してください。%n はユニットの名前をテンプレートに指定します。

ノート:
  • SSMTP#セキュリティ にしたがって SSMTP を設定した場合、ユーザー nobody/etc/ssmtp/ssmtp.conf にアクセスすることができず、systemctl start status-email-user@dbus.service コマンドは失敗します。status-email-user@.service モジュールの User に root を使うことでこれを回避できます。
  • メールスクリプトで mail -s somelogs address を使用すると、mail はフォークして、systemd はスクリプトの終了を確認したときに mail プロセスを終了します。mail -Ssendwait -s somelogs address として mail がフォークしないようにしてください。

crontab を使用する

crontab を使って定期的なサービスを管理するツールとして systemd-cron-nextAURsystemd-cronAUR があります。どちらも AUR からインストールすることができます。これらのツールには systemd に存在しない MAILTO 機能が実装されています。

もし、スケジュールされたジョブをまとめて見れるから crontab が好きだという場合は、systemctl でそれと同じことが可能です。#管理 を見て下さい。

手動で行う

既存の crontab から移行する以外に、cron と同じ周期を使用することが望ましい場合があります。定期的に開始する各サービスのタイマーを作成するという面倒な作業を回避するには、テンプレートユニット を使用します。例:

/etc/systemd/system/monthly@.timer
[Unit]
Description=Monthly Timer for %i service

[Timer]
OnCalendar=*-*-1 02:00:00
AccuracySec=6h
RandomizedDelaySec=1h
Persistent=true
Unit=%i.service

[Install]
WantedBy=default.target
ノート: タイマーの起動によってすべてのユニットが同時に開始されるのを避けるために、AccuracySec だけでなく RandomizedDelaySec を使用する重要性については、systemd.timer(5) § OPTIONS を参照してください。

その後、monthly@unit_name.timer起動/有効化 行うだけで済みます。

ヒント: テンプレートユニットはネストできます。たとえば、monthly@btrfs-scrub@mnt-$(systemd-escape bbb76c63-e4ac-4e39-8897-a120c5d30686).timer起動/有効化 することができます。

"有効期間" の処理

一部のソフトウェアは、最後に実行されてからの経過時間を追跡します。たとえば、最後のダウンロードが 24 時間以内に終了した場合はデータベースの更新をブロックします。

デフォルトでは、タイマーは起動したタスクがいつ終了したかを追跡しません。これを回避するには、OnUnitInactiveSeconds を使用できます:

/etc/systemd/system/daily-inactive@.timer
[Unit]
Description=Launch %i service 24hours after it deactivated

[Timer]
OnUnitInactiveSec=1day1sec
Unit=%i.service
Persistent=true

[Install]
WantedBy=default.target
ヒント: Restart=on-failureRestartSec を併用すると、失敗と成功の後に異なるスケジュールに従ってユニットを再実行することができます。systemd.service(5) § OPTIONS を参照して下さい。

参照

  • systemd.timer(5)
  • Fedora Project wikisystemd カレンダータイマーのページ
  • Gentoo wikisystemd タイマーサービスのセクション
  • systemd-cron-next — crontab と anacrontab ファイルからタイマーとサービスを生成するツール
https://github.com/systemd-cron/systemd-cron-next || systemd-cron-nextAUR
  • systemd-cron — cron スクリプトを実行する systemd ユニットが入っています。systemd-crontab-generator を使って crontab を変換。
https://github.com/systemd-cron/systemd-cron || systemd-cronAUR