「Systemd/タイマー」の版間の差分
Kusanaginoturugi (トーク | 投稿記録) 細 (→サンプル) |
Kusanaginoturugi (トーク | 投稿記録) 細 (→サービス) |
||
88行目: | 88行目: | ||
[Service] |
[Service] |
||
Type=oneshot |
Type=oneshot |
||
− | ExecStart=/home/ |
+ | ExecStart=/home/<user>/scripts/foo.sh |
</nowiki>}} |
</nowiki>}} |
||
2015年12月23日 (水) 23:04時点における版
タイマーは名前が .timer
で終わる systemd のユニットファイルであり、.service
ファイルやイベントを制御します。cron の代わりとしてタイマーを使うことができます (#cron を置き換える を読んで下さい)。タイマーにはカレンダー時刻のイベントとモノトニック時刻のイベントのサポートが入っており、さらに非同期に実行することも可能です。
目次
タイマーユニット
タイマーは拡張子が .timer
の systemd のユニットファイルです。他のユニット設定ファイルと似ていますが特別に [Timer]
セクションが存在します。[Timer]
セクションにはタイマーが作動する時間と処理を定義します。タイマーには2つのタイプがあり、どちらか一つを使って定義されます:
- モノトニックタイマーは刻々と変わる開始点と相応したタイムスパンの後に作動します。様々なモノトニックタイマーが存在しますがどれも次のような形式です:
OnTypeSec=
。OnBootSec
とOnActiveSec
は全てのモノトニックタイマーで共通です。 - リアルタイムタイマー (別名ウォールクロックタイマー) は (cron のジョブと同じように) カレンダーイベントにあわせて作動します。
OnCalendar=
オプションを使って定義を行います。
タイマーのオプションについては systemd.timer(5)
の man ページで説明されています。カレンダーイベントやタイムスパンの引数構文については systemd.time(7)
の man ページで説明されています。
サービスユニット
それぞれの .timer
ファイルには、対応する .service
ファイルが存在します (例: foo.timer
と foo.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
サンプル
タイマーを使用してサービスを実行するのにあたって、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
サービス
/etc/systemd/system/foo.service
[Unit] Description=daily foo RefuseManualStart=no RefuseManualStop=yes [Service] Type=oneshot ExecStart=/home/<user>/scripts/foo.sh
cron を置き換える
おそらく一番有名なジョブスケジューラは cron ですが、systemd のタイマーはその代替手段になりえます。
メリット
タイマーを使う主要なメリットは、それぞれのジョブが固有の systemd サービスを使うというところに根ざします。そのメリットには以下のようなものがあります:
- タイマーとは別個にジョブを実行することが簡単にできます。これによってデバッグが楽になります。
- 特定の環境で動作するようにジョブを設定することができます (
systemd.exec(5)
man ページを参照)。 - ジョブを cgroups の支配下に置けます。
- 他の systemd ユニットに依存するようにジョブを設定できます。
- systemd の journal でジョブが記録されるのでデバッグが簡単です。
注意事項
cron では簡単にできることが、タイマーユニットを使用する場合、難しかったり不可能であったりすることがいくつか存在します。
- 冗長性: systemd を使って定期的なジョブを設定するには2つのファイルを作成して2回
systemctl
コマンドを実行します。それに対して crontab には一行を追加するだけです。 - メール: ジョブが失敗した時にメールを送信する cron の
MAILTO
と同等なものは存在しません。ただし各サービスにOnFailure=
オプションを使うことで同じような機能を設定することはできます。 - ランダム遅延: インターバルを指定してタイマーの実行をランダムに分散する cron の
RANDOM_DELAY
と同じ機能はありません (バグレポートやテスト結果を参照)。同時に実行して欲しくないサービスには、手動でオーバーラップを少なくするようにタイマーを設定する必要があります。
MAILTO
Cron の MAILTO
のように、systemd で、ユニットが失敗したときにメールを送信するように設定できます。それにはまず2つのファイルが必要です: メールを送信するための実行可能ファイルと、実行可能ファイルを起動するための .service。以下の例では、sendmail
を使用するシェルスクリプトが実行可能ファイルになっています:
/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-user1@.service
[Unit] Description=status email for %I to user1 [Service] Type=oneshot ExecStart=/usr/local/bin/systemd-email user1@mailhost %i User=nobody Group=systemd-journal
メールを送信するユニットがインスタンスパラメータになっていることに気づいて下さい。これによって、他のユニットでメールを送信するのにも使えるようになっています。ただしメールの受取人はハードコードされています (ユニットテンプレートが使用できるパラメータは一つだけのため)。メールを様々なところに送りたい場合は複数のサービスを作成する必要があります。サービスを作成したら、メールがちゃんと受け取れるかどうかテストしてみてください:
# systemctl start status-email-user1@dbus.service
問題ないようでしたら、メールを送って欲しいユニットの [Unit]
セクションに OnFailure=status-email-user1@%n.service
を追加してください。%n
はユニットの名前をテンプレートに指定します。
crontab を使用する
crontab を使って定期的なサービスを管理するツールとして systemd-crontab-generatorAUR と systemd-cronAUR があります。どちらも AUR からインストールすることができます。これらのツールには systemd に存在しない MAILTO
と RANDOM_DELAY
機能が実装されています。
もし、スケジュールされたジョブをまとめて見れるから crontab が好きだという場合は、systemctl
でそれと同じことが可能です。#管理 を見て下さい。
参照
- systemd.timer man page on freedesktop.org
- Fedora Project wiki の systemd カレンダータイマーのページ
- Gentoo wiki の systemd タイマーサービスのセクション
- systemd-crontab-generator — crontab と anacrontab ファイルからタイマーとサービスを生成するツール
- systemd-cron — cron スクリプトを実行する systemd ユニットが入っています。systemd-crontab-generator を使って crontab を変換。