# systemd/cron functionality (日本語)

関連記事

- systemd
- systemd/ユーザー
- systemd/サービス
- systemd FAQ
- cron

systemd には定時のイベントだけでなく (バージョン 197 から) カレンダーのイベントのサポートも組み込まれており、cron の主な機能を肩代わりすることができるようになっています。また、systemd バージョン 212 からタイマーに `Persistent` や `OnCalendar` オプションを使うことで anacron を代替する基礎も作られました。

## イントロダクション

Linux の中では何年にもわたって Cron が使われ続けていますが、今でもジョブの失敗を検知したり、ジョブの依存関係を制定したり、プロセスを cgroups に割り振る手段が提供されていません。こうした機能のどれかが必要な場合、systemd がジョブスケジューリングをセットアップする仕組みを提供しています。dcron や cronie などを使うのと比べると少しばかり扱いにくさがありますが、その恩恵は少なくありません:

- journalctl を使って最後の状態とログの出力を取得することができます。これにより正確なデバッグが可能です。
- Systemd にはジョブを適切に実行する環境を設定するのに役立つオプションが多数あります (例: IOSchedulingPriority, Nice, JobTimeoutSec)。
- 必要であればジョブを作成して他の systemd ユニットに依存させることができます。

## 毎時・毎日・毎週・毎月・毎年のイベント

機能を実装するためにターゲットから呼ばれるタイマーを使う方法があります。一時間ごとに実行する必要があるサービスは全てターゲットの依存として起動することができます。この方法は このブログ記事 で初めて記述されました。

Note: 少し異なる方法を使って同じことを実装する AUR パッケージ systemd-cron が存在します。このパッケージを使う場合は、以下のスクリプトを修正して適切な場所に移す必要があります。
Note: cron と anacron デーモンと完全な互換性がある AUR パッケージ systemd-crontab-generator もあります。(/etc/crontab や /var/spool/cron/ など) 既存のディレクトリに存在する crontab をパースして systemd のタイマーやサービスを生成します。まだ試験的な段階で python2 で作られており、完成しているとはまだ言えません。インストールする前にコメントを注意して読んで下さい。

まず最初に、ディレクトリを作成する必要があります:

    # mkdir /etc/systemd/system/timer-{hourly,daily,weekly,monthly,yearly}.target.wants

動作させるために以下のファイルを指定されたパスに作成してください。

### 毎時のイベント

    /etc/systemd/system/timer-hourly.timer

    [Unit]
    Description=Hourly Timer

    [Timer]
    OnBootSec=5min
    OnCalendar=hourly
    Unit=timer-hourly.target

    [Install]
    WantedBy=basic.target

    /etc/systemd/system/timer-hourly.target

    [Unit]
    Description=Hourly Timer Target
    StopWhenUnneeded=yes

### 毎日のイベント

    /etc/systemd/system/timer-daily.timer

    [Unit]
    Description=Daily Timer

    [Timer]
    OnBootSec=10min
    OnCalendar=daily
    Persistent=true
    Unit=timer-daily.target

    [Install]
    WantedBy=basic.target

    /etc/systemd/system/timer-daily.target

    [Unit]
    Description=Daily Timer Target
    StopWhenUnneeded=yes

systemd 212 から、anacron の機能がタイマーで実装されました。`Persistent` オプションと `OnCalendar` オプションを使用します。この機能について詳しく知りたい場合は、`systemd.timer(5)` の man ページを見て下さい。

### 毎週のイベント

    /etc/systemd/system/timer-weekly.timer

    [Unit]
    Description=Weekly Timer

    [Timer]
    OnBootSec=15min
    OnCalendar=weekly
    Persistent=true
    Unit=timer-weekly.target

    [Install]
    WantedBy=basic.target

    /etc/systemd/system/timer-weekly.target

    [Unit]
    Description=Weekly Timer Target
    StopWhenUnneeded=yes

### 毎月のイベント

    /etc/systemd/system/timer-monthly.timer

    [Unit]
    Description=Monthly Timer

    [Timer]
    OnBootSec=45min
    OnCalendar=monthly
    Persistent=true
    Unit=timer-monthly.target

    [Install]
    WantedBy=basic.target

    /etc/systemd/system/timer-monthly.target

    [Unit]
    Description=Monthly Timer Target
    StopWhenUnneeded=yes

### 毎年のイベント

    /etc/systemd/system/timer-yearly.timer

    [Unit]
    Description=Yearly Timer

    [Timer]
    OnBootSec=90min
    OnCalendar=yearly
    Persistent=true
    Unit=timer-yearly.target

    [Install]
    WantedBy=basic.target

    /etc/systemd/system/timer-yearly.target

    [Unit]
    Description=Yearly Timer Target
    StopWhenUnneeded=yes

### イベントを追加する

ターゲットにイベントを追加するには適切な wants フォルダにファイルを配置してください。特定のジョブを毎日実行したい場合、systemd サービスファイルを作成してください。

例えば、(プログラム bar を起動する) `foo.service` を毎日実行したいのならば、以下のファイルを作成します:

    /etc/systemd/system/foo.service

    [Unit]
    Description=Starts program bar
    Wants=timer-daily.timer

    [Service]
    User=                                          # Add a user if you wish the service to be executes as a particular user, else delete this line
    Type=                                          # Simple by default, change it if you know what you are doing, else delete this line
    Nice=19
    IOSchedulingClass=2
    IOSchedulingPriority=7
    ExecStart=/usr/bin/bar --option1 --option2     # More than one ExecStart can be used if required

    [Install]
    WantedBy=timer-daily.target

それからサービスを起動・有効化してください。

### タイマーを有効化・起動する

    # systemctl enable timer-{hourly,daily,weekly,monthly,yearly}.timer
    # systemctl start timer-{hourly,daily,weekly,monthly,yearly}.timer

## カレンダーのイベントを起動する

単調な間隔ではなく、カレンダーのイベントにあわせてサービスを実行したい場合 (crontab の機能を置き換えたい場合)、新しいタイマーを作成してサービスファイルをタイマーにリンクさせる必要があります。例:

    /etc/systemd/system/foo.timer

    [Unit]
    Description=foo timer

    [Timer]
    # To add a time of your choosing here, please refer to systemd.time manual page for the correct format
    OnCalendar=Mon-Thu *-9-28 *:30:00
    Persistent=true
    Unit=foo.service

    [Install]
    WantedBy=basic.target

このサービスファイルは定期的に実行するイベントと同じ方法で作成できます。ただし、`/etc/systemd/system/` フォルダに配置するので気を付けて下さい。

## サービスファイルのサンプル

Note: 以下のサンプルスクリプトは上述の、毎時・毎日・毎週のタイマーを作成していることを前提にしています。

### Reflector

reflector スクリプトを使って pacman のミラーリストを更新するのに使うサービスです。

    /etc/systemd/system/timer-daily.target.wants/reflector.service

    [Unit]
    Description=Update the mirrorlist

    [Service]
    Nice=19
    IOSchedulingClass=2
    IOSchedulingPriority=7
    Type=oneshot
    ExecStart=/usr/bin/reflector --protocol http --latest 30 --number 20 --sort rate --save /etc/pacman.d/mirrorlist

Note: Reflector のオプションはユーザーの使用にあわせて調整する必要があります。Moderator/TU の Xyne による使用例がフォーラムに投稿されています。

### modprobed_db サービス

このサービスはカーネルのコンパイル時間を大幅に短縮するので、カーネルをコンパイルするユーザーにとって大いに役立ちます。詳しくは Modprobed_db ページを参照してください。

    /etc/systemd/system/modprobed_db.service

    [Unit]
    Description=Run modprobed_db
    Wants=timer-daily.target

    [Service]
    Type=oneshot
    RemainAfterExit=yes
    User=enter user here
    Nice=19
    IOSchedulingClass=2
    IOSchedulingPriority=7
    ExecStart=/usr/bin/modprobed_db store

    [Install]
    WantedBy=timer-daily.target

それから、サービスを起動・有効化してください。

### Hosts-update サービス

hosts-update パッケージは mvps ブロックリストを使って `/etc/hosts` を更新します。

    /etc/systemd/system/timer-daily.target.wants/hosts-update.service

    [Unit]
    Description=Update hosts file
    After=network.target

    [Service]
    Nice=19
    IOSchedulingClass=2
    IOSchedulingPriority=7
    ExecStart=/usr/bin/hosts-update

    [Install]
    WantedBy=timer-daily.target

## 参照

- https://fedoraproject.org/wiki/Features/SystemdCalendarTimers - systemd calendar timers on the Fedora Project wiki

Categories:

- Daemons and system services (日本語)
- Boot process (日本語)