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

提供: ArchWiki
ナビゲーションに移動 検索に移動
imported>Jokeryu
(add zh-cn link)
 
(校正(でき・出来))
 
(6人の利用者による、間の24版が非表示)
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}}
{{Related2|systemd|systemd}}
+
{{Related|systemd}}
{{Related2|systemd/User|systemd/ユーザー}}
+
{{Related|systemd/ユーザー}}
{{Related2|systemd/Services|systemd/サービス}}
+
{{Related|systemd FAQ}}
  +
{{Related|cron}}
{{Related2|systemd FAQ|systemd FAQ}}
 
{{Related2|cron|cron}}
 
 
{{Related articles end}}
 
{{Related articles end}}
タイマーは名前が {{ic|.timer}} で終わる [[systemd|systemd]] のユニットファイルで、{{ic|.service}} ファイルやイベントを制御します。[[cron|cron]] の代わりとしてタイマーを使うことができます ([[#cron を置き換える]] を読んで下さい)。タイマーにはカレンダー時刻のイベントとモノトニック時刻のイベントのサポートが入っており、さらに非同期に実行することも可能です。
+
タイマーは名前が {{ic|.timer}} で終わる [[systemd]] のユニットファイルであり、{{ic|.service}} ファイルやイベントを制御します。[[cron]] の代わりとしてタイマーを使うことができます ([[#cron を置き換える]] を読んで下さい)。タイマーにはカレンダー時刻のイベントとモノトニック時刻のイベントのサポートが入っており、さらに非同期に実行することも可能です。
   
 
== タイマーユニット ==
 
== タイマーユニット ==
   
タイマーは拡張子が {{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|systemd.timer(5)}} の [[man page|man ページ]]で説明されています。
+
* '''モノトニックタイマー''' は刻々と変わる開始点と相応したタイムスパンの後に作動します。様々なモノトニックタイマーが存在しますがどれも次のような形式です: {{ic|1=On''Type''Sec=}} {{ic|OnBootSec}} と {{ic|OnActiveSec}} は全てのモノトニックタイマーで共通です。
* '''リアルタイムタイマー''' (別名ウォールクロックタイマー) は (cron のジョブと同じように) カレンダーイベントにあわせて作動します。{{ic|1=OnCalender=}} オプションを使って定義を行います。カレンダーイベントやタイムスパンの引数構文については {{ic|systemd.time(7)}} の [[man page|man ページ]]で説明されています。
+
* '''リアルタイムタイマー''' (別名ウォールクロックタイマー) は (cron のジョブと同じように) カレンダーイベントにあわせて作動します。{{ic|1=OnCalendar=}} オプションを使って定義を行います。
  +
  +
タイマーのオプションについては {{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}} を追加し、タイマーユニットを [[有効化]] します。}}
   
 
== サービスユニット ==
 
== サービスユニット ==
35行目: 41行目:
 
}}
 
}}
   
  +
{{Note|
{{Note|タイマーによって実行するサービスの状態は、今現在作動しているのでない限り、inactive になります。そして {{ic|/var/lib/systemd/timers}} ディレクトリの {{ic|stamp-*}} ファイルを使って ''systemd'' は {{ic|LAST}} フィールドの情報を管理します。長さゼロのファイルで時刻フィールドを使用します。タイマーがズレる場合は、この stamp ファイルを削除することでタイマーの次の作動時に systemd が再構成を行います。}}
 
  +
* (有効でないタイマーも含めて) 全てのタイマーを確認したい場合、{{ic|systemctl list-timers --all}} を使って下さい。
  +
* タイマーによって実行するサービスの状態は、今現在作動しているのでない限り、inactive になります。
  +
* タイマーがズレる場合は、{{ic|/var/lib/systemd/timers}} もしくは {{ic|~/.local/share/systemd/}} にある {{ic|stamp-*}} ファイルを削除してみてください。stamp ファイルはタイマーが実行された最後の時刻を記録しており、ファイルを削除することでタイマーの次の作動時に systemd が再構成を行います。
  +
}}
   
 
== サンプル ==
 
== サンプル ==
   
  +
タイマーを使用してサービスを実行するのにあたって、service ユニットファイルに変更を加える必要はありません。以下の例では {{ic|foo.timer}} という名前のタイマーを使って {{ic|foo.service}} を定期的に実行します。
以下はサンプルのタイマー、''service'' ユニットです。バックアップスクリプトのサービスです:
 
   
  +
=== モノトニックタイマー ===
{{hc|/etc/systemd/system/mybackup.service|<nowiki>
 
  +
  +
起動15分後に実行され、システムが起動している間、一週間ごとに再度実行されるタイマー:
  +
  +
{{hc|/etc/systemd/system/foo.timer|<nowiki>
 
[Unit]
 
[Unit]
Description=Full system backup
+
Description=Run foo weekly and on boot
   
[Service]
+
[Timer]
  +
OnBootSec=15min
Nice=19
 
  +
OnUnitActiveSec=1w
IOSchedulingClass=2
 
  +
IOSchedulingPriority=7
 
  +
[Install]
ExecStart=/path/to/mybackup/script
 
  +
WantedBy=timers.target
 
</nowiki>}}
 
</nowiki>}}
   
 
=== リアルタイムタイマー ===
 
=== リアルタイムタイマー ===
   
  +
一週間ごとに起動するタイマー (月曜日の午前12:00に実行)。システムの電源が切られていたなどの理由で、最後の起動時間を過ぎていた場合、すぐに実行されます ({{ic|1=Persistent=true}} オプション):
カレンダーイベントにあわせてバックアップを実行したい場合は、{{ic|OnCalendar}} オプションを使います:
 
   
{{hc|/etc/systemd/system/mybackup.timer|<nowiki>
+
{{hc|/etc/systemd/system/foo.timer|<nowiki>
 
[Unit]
 
[Unit]
Description=weekly full backup
+
Description=Run foo weekly
   
 
[Timer]
 
[Timer]
 
OnCalendar=weekly
 
OnCalendar=weekly
Persistent=true
+
Persistent=true
  +
 
 
[Install]
 
[Install]
WantedBy=timers.target
+
WantedBy=timers.target</nowiki>}}
</nowiki>}}
 
   
  +
もっと細かく日時を指定する必要がある場合、次の形式で {{ic|OnCalendar}} イベントを制御できます: {{ic|DayOfWeek Year-Month-Day Hour:Minute:Second}}。アスタリスクをワイルドカードとして使うことができ、カンマで複数の日時を指定することができます。値を {{ic|..}} で区切ることで連続的に日程を指定することも可能です。
{{Tip|Shortcuts like {{ic|daily}} and {{ic|weekly}} refer to ''specific start times'' and thus any timers sharing such calendar events will start simultaneously. This can cause poor performance if the timers' services compete for system resources. Consider using more specific calendar events, which can be manually staggered (e.g. {{ic|OnCalendar&#61;Wed, 23:15}}).}}
 
   
  +
例えば、以下の場合、毎月の1日から4日まで、月曜日か火曜日の場合にのみ、午後0時にサービスを実行します:
=== モノトニックタイマー ===
 
   
  +
OnCalendar=Mon,Tue *-*-01..04 12:00:00
また、システムが起動する時に、一週間ごとに再起動でバックアップを実行したい場合、{{ic|OnBootSec}} を {{ic|OnUnitActiveSec}} と組み合わせます:
 
   
  +
毎月第1土曜日にサービスを実行したい場合は以下のようになります:
{{hc|/etc/systemd/system/mybackup.timer|<nowiki>
 
[Unit]
 
Description=Weekly and post-boot backup
 
   
  +
OnCalendar=Sat *-*-1..7 18:00:00
[Timer]
 
OnBootSec=15min
 
OnUnitActiveSec=1w
 
   
  +
毎朝4時に実行したい場合は以下のようになります:
[Install]
 
  +
WantedBy=timers.target
 
  +
OnCalendar=*-*-* 4:00:00
</nowiki>}}
 
  +
  +
{{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}} を見てください。
{{Tip|リソースを消費するサービスでは、起動してすぐにタイマーを設定しないでください。ログインや X セッションに遅延が発生する可能性があります。}}
 
   
 
== cron を置き換える ==
 
== cron を置き換える ==
   
おそらく [[cron|cron]] が一番有名なジョブスケジューラですが、''systemd'' のタイマーはその代替手段になりえます。
+
おそらく一番有名なジョブスケジューラは [[cron]] ですが、''systemd'' のタイマーはその代替手段になりえます。
   
 
=== メリット ===
 
=== メリット ===
97行目: 136行目:
   
 
* タイマーとは別個にジョブを実行することが簡単にできます。これによってデバッグが楽になります。
 
* タイマーとは別個にジョブを実行することが簡単にできます。これによってデバッグが楽になります。
* 特定の環境で動作するようにジョブを設定することができます ({{ic|systemd.exec(5)}} [[man page|man ページ]]を参照)。
+
* 特定の環境で動作するようにジョブを設定することができます ({{man|5|systemd.exec}} [[man ページ]]を参照)。
* ジョブを [[cgroups|cgroups]] の支配下に置けます。
+
* ジョブを [[cgroups]] の支配下に置けます。
 
* 他の ''systemd'' ユニットに依存するようにジョブを設定できます。
 
* 他の ''systemd'' ユニットに依存するようにジョブを設定できます。
 
* ''systemd'' の journal でジョブが記録されるのでデバッグが簡単です。
 
* ''systemd'' の journal でジョブが記録されるのでデバッグが簡単です。
104行目: 143行目:
 
=== 注意事項 ===
 
=== 注意事項 ===
   
  +
cron では簡単にできることが、タイマーユニットを使用する場合、難しかったり不可能であったりすることがいくつか存在します。
* 冗長性: ''systemd'' を使って定期的なジョブを設定するには2つのファイルを作成して2回 {{ic|systemctl}} コマンドを実行します。それに対して crontab には一行を追加するだけです。crontab を使って定期的なサービスを管理するツールとして {{aur|systemd-crontab-generator}} と {{aur|systemd-cron}} があります。もし、スケジュールされたジョブをまとめて見れるから crontab が好きだという場合は、{{ic|systemctl}} でそれと同じことが可能です。[[#管理]] を見て下さい。
 
  +
* メール: ジョブが失敗した時にメールを送信する cron の {{ic|MAILTO}} と同等なものは存在しません。各サービスに {{ic|1=OnFailure=}} オプションを使うことで同じような機能を設定することはできます。
 
  +
* 冗長性: ''systemd'' を使って定期的なジョブを設定するには2つのファイルを作成して2回 {{ic|systemctl}} コマンドを実行します。それに対して crontab には一行を追加するだけです。
* ランダム遅延: インターバルを指定してタイマーの実行をランダムに分散する cron の {{ic|RANDOM_DELAY}} と同じ機能はありません ([https://bugs.freedesktop.org/show_bug.cgi?id=82084 バグレポート]を参照)。同時に実行して欲しくないサービスには、手動でオーバーラップを少なくするようにタイマーを設定する必要があります。
 
  +
* メール: ジョブが失敗した時にメールを送信する cron の {{ic|MAILTO}} と同等なものは存在しません。ただし各サービスに {{ic|1=OnFailure=}} オプションを使うことで同じような機能を設定することはできます。
  +
  +
=== MAILTO ===
  +
  +
Cron の {{ic|MAILTO}} のように、systemd で、ユニットが失敗したときにメールを送信するように設定できます。それにはまず2つのファイルが必要です: メールを送信するための実行可能ファイルと、実行可能ファイルを起動するための ''.service''。以下の例では、{{ic|sendmail}} ({{ic|smtp-forwarder}} を含むパッケージにはすべて含まれています) を使用するシェルスクリプトが実行可能ファイルになっています:
  +
  +
{{hc|/usr/local/bin/systemd-email|<nowiki>#!/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</nowiki>}}
  +
  +
どんな実行可能ファイルを使うのであれ、上記のシェルスクリプトのように、最低でも2つの引数が必要になります: 送信先のアドレスと状態を取得するユニットファイルです。以下の ''.service'' はそれらの引数を渡します:
  +
  +
{{hc|/etc/systemd/system/status-email-''user''@.service|2=[Unit]
  +
Description=status email for %i to ''user''
  +
  +
[Service]
  +
Type=oneshot
  +
ExecStart=/usr/local/bin/systemd-email ''address'' %i
  +
User=nobody
  +
Group=systemd-journal}}
  +
  +
{{ic|''user''}} はメールを送信するユーザーに、{{ic|''address''}} はユーザーのメールアドレスに置き換えてください。受信者はハードコードされますが、インスタンスパラメータとしてユニットファイルを渡すことで、上記のサービスだけで他のユニットのメールも送ることができます。{{ic|status-email-''user''@dbus.service}} を[[systemd#ユニットを使う|起動]]して、メールが受け取れることを確認してください。
  +
  +
問題ないようでしたら、メールを送って欲しいユニットの {{ic|[Unit]}} セクションに {{ic|1=OnFailure=status-email-''user''@%n.service}} を追加してください。{{ic|%n}} はユニットの名前をテンプレートに指定します。
  +
  +
{{note|
  +
*[[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 を使って定期的なサービスを管理するツールとして {{aur|systemd-cron-next}} と {{aur|systemd-cron}} があります。どちらも [[AUR]] からインストールすることができます。これらのツールには systemd に存在しない {{ic|MAILTO}} 機能が実装されています。
  +
  +
もし、スケジュールされたジョブをまとめて見れるから 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}} を参照して下さい。}}
タイマーを自動的にずらすには {{ic|AccuracySec}} オプションが役に立つかもしれません。ただし"全てのローカルなタイマーユニット間で同期が行われる"ので注意してください ({{ic|systemd.timer(5)}})。言い換えれば、{{ic|AccuracySec}} は全てのタイマーの作動時間を同じ分だけずらします。例えば、{{ic|1=AccuracySec=15m}} を使っている {{ic|1=OnCalendar=daily}} のタイマーユニットは全て、00:00 から 00:15 の間の同一時刻に関連するサービスを起動します。
 
   
 
== 参照 ==
 
== 参照 ==
   
  +
* {{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