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

提供: ArchWiki
ナビゲーションに移動 検索に移動
88行目: 88行目:
   
 
* タイマーとは別個にジョブを実行することが簡単にできます。これによってデバッグが楽になります。
 
* タイマーとは別個にジョブを実行することが簡単にできます。これによってデバッグが楽になります。
* 特定の環境で動作するようにジョブを設定することができます ({{ic|systemd.exec(5)}} [[man page|man ページ]]を参照)。
+
* 特定の環境で動作するようにジョブを設定することができます ({{ic|systemd.exec(5)}} [[man ページ]]を参照)。
* ジョブを [[cgroups|cgroups]] の支配下に置けます。
+
* ジョブを [[cgroups]] の支配下に置けます。
 
* 他の ''systemd'' ユニットに依存するようにジョブを設定できます。
 
* 他の ''systemd'' ユニットに依存するようにジョブを設定できます。
 
* ''systemd'' の journal でジョブが記録されるのでデバッグが簡単です。
 
* ''systemd'' の journal でジョブが記録されるのでデバッグが簡単です。

2015年8月9日 (日) 16:27時点における版

関連記事

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

タイマーユニット

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

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

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

サービスユニット

それぞれの .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 にある 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
ヒント: dailyweekly などの特殊なイベントの表現は特定の起動時間を示しているため、同じカレンダーイベントが設定されているタイマーがあった場合、同時に起動します。そのようなことが発生すると、タイマーのサービスがシステムリソースを取り合って、システムパフォーマンスが落ち込む可能性があります。OnCalendar=Wed, 23:15 のような特定のイベントで起動するタイマーを使うときはよく考えてからにしてください。#注意事項を参照。

cron を置き換える

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

メリット

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

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

注意事項

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

  • 冗長性: systemd を使って定期的なジョブを設定するには2つのファイルを作成して2回 systemctl コマンドを実行します。それに対して crontab には一行を追加するだけです。
  • メール: ジョブが失敗した時にメールを送信する cron の MAILTO と同等なものは存在しません。ただし各サービスに OnFailure= オプションを使うことで同じような機能を設定することはできます。
  • ランダム遅延: インターバルを指定してタイマーの実行をランダムに分散する cron の RANDOM_DELAY と同じ機能はありません (バグレポートテスト結果を参照)。同時に実行して欲しくないサービスには、手動でオーバーラップを少なくするようにタイマーを設定する必要があります。
ノート: タイマーを自動的にずらすには AccuracySec オプションが役に立つかもしれません。ただし"全てのローカルなタイマーユニット間で同期が行われる"ので注意してください (systemd.timer(5))。言い換えれば、AccuracySec は全てのタイマーの作動時間を同じ分だけずらします。例えば、AccuracySec=15m を使っている OnCalendar=daily のタイマーユニットは全て、00:00 から 00:15 の間の同一時刻に関連するサービスを起動します。

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 はユニットの名前をテンプレートに指定します。

ノート: SSMTP#セキュリティ にしたがって SSMTP を設定した場合、ユーザー nobody/etc/ssmtp/ssmtp.conf にアクセスすることができず、systemctl start status-email-user1@dbus.service コマンドは失敗します。status-email-user1@.service モジュールの User に root を使うことでこれを回避できます。

crontab を使用する

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

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

参照

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