systemd で crontab を置き換えるための最低限の設定の書き方を紹介したいと思います。 今回はまず crontab での @reboot
(起動時に1回だけ実行される) 相当の処理をできるようにしたいと思います。
確認環境
- Ubuntu 18.04 LTS
最小限の unit ファイル例
sudoedit /etc/systemd/system/hello.service
などで作成します。
ini ファイル形式で、 最低限の設定は [Service]
セクションに書きます。
[Service]
Type=oneshot
ExecStart=/bin/echo hello
Type
のデフォルトは simple
でデーモンを想定しているので、 すぐに終了するコマンドの場合は Type=oneshot
にしておきます。
ExecStart
が実際に実行するコマンドです。 コマンドはフルパスで書く必要があります。
出力は systemd journal に送られるので、 crontab と違って リダイレクトなどは気にしなくても大丈夫です。
確認
systemctl cat hello
や systemctl status hello
で確認します。 service unit の場合は拡張子の .service
は省略できます。
$ systemctl cat hello
# /etc/systemd/system/hello.service
[Service]
Type=oneshot
ExecStart=/bin/echo hello
$ systemctl status hello
● hello.service
Loaded: loaded (/etc/systemd/system/hello.service; static; vendor preset: enabled)
Active: inactive (dead)
実行
sudo systemctl start hello
で実行できます。
$ sudo systemctl start hello
$ systemctl status hello
● hello.service
Loaded: loaded (/etc/systemd/system/hello.service; static; vendor preset: enabled)
Active: inactive (dead)
Sep 12 HH:MM:SS vagrant systemd[1]: Starting hello.service...
Sep 12 HH:MM:SS vagrant echo[1864]: hello
Sep 12 HH:MM:SS vagrant systemd[1]: Started hello.service.
ログ確認
systemctl status
でも一部出ていますが、 journalctl -u hello
でログが確認できます。
oneshot なので、 Starting から Started までの間が実際の処理 (ExecStart) になっています。
デーモンに書き換え
crontab の @reboot
で何かを起動しておくのを 置き換えるのを想定して、 デーモンの例も書いておきます。
まず hello.service
を以下の内容に書き換えます。
[Service]
ExecStart=/bin/sleep inf
書き換えた後は sudo systemctl daemon-reload
で再読み込みが必要です。 再読み込みしていないと警告が出るので、忘れていても気付きやすいと思います。
$ sudoedit /etc/systemd/system/hello.service
$ systemctl cat hello
# Warning: hello.service changed on disk, the version systemd has loaded is outdated.
# This output shows the current version of the unit's original fragment and drop-in files.
# If fragments or drop-ins were added or removed, they are not properly reflected in this output.
# Run 'systemctl daemon-reload' to reload units.
# /etc/systemd/system/hello.service
[Service]
ExecStart=/bin/sleep inf
$ sudo systemctl daemon-reload
$ systemctl cat hello
# /etc/systemd/system/hello.service
[Service]
ExecStart=/bin/sleep inf
起動
sudo systemctl start hello
で起動して、 sudo systemctl stop hello
で停止できます。
$ sudo systemctl start hello
$ systemctl status hello
● hello.service
Loaded: loaded (/etc/systemd/system/hello.service; static; vendor preset: enabled)
Active: active (running) since Wed 2018-09-12 HH:MM:SS UTC; 6s ago
Main PID: 2026 (sleep)
Tasks: 1 (limit: 1135)
CGroup: /system.slice/hello.service
└─2026 /bin/sleep inf
Sep 12 HH:MM:SS vagrant systemd[1]: Started hello.service.
$ sudo systemctl stop hello
$ systemctl status hello
● hello.service
Loaded: loaded (/etc/systemd/system/hello.service; static; vendor preset: enabled)
Active: inactive (dead)
(ログ略)
自動起動
@reboot
を置き換えるためには、 OS 起動時にデーモンも自動起動する必要があるので、 [Install]
セクションを追加します。
[Install]
WantedBy=multi-user.target
[Install]
セクションを追加して systemctl enable
すると symlink が作成されて、 OS 起動時に自動起動するようになります。
systemctl enable --now hello
のように --now
オプションをつけると enable
と start
を同時にできます。
$ sudoedit /etc/systemd/system/hello.service
sudoedit: /etc/systemd/system/hello.service unchanged
$ sudo systemctl daemon-reload
$ systemctl cat hello
# /etc/systemd/system/hello.service
[Service]
ExecStart=/bin/sleep inf
[Install]
WantedBy=multi-user.target
$ sudo systemctl status hello
● hello.service
Loaded: loaded (/etc/systemd/system/hello.service; disabled; vendor preset: enabled)
Active: inactive (dead)
(ログ略)
$ sudo systemctl enable hello
Created symlink /etc/systemd/system/multi-user.target.wants/hello.service → /etc/systemd/system/hello.service.
$ sudo systemctl status hello
● hello.service
Loaded: loaded (/etc/systemd/system/hello.service; enabled; vendor preset: enabled)
Active: inactive (dead)
(ログ略)
削除
systemctl disable
して service ファイルも削除すれば元に戻ります。
systemctl disable --now hello
のように --now
オプションをつけると disable
と stop
を同時にできます。
$ sudo systemctl disable hello
Removed /etc/systemd/system/multi-user.target.wants/hello.service.
$ sudo systemctl status hello
● hello.service
Loaded: loaded (/etc/systemd/system/hello.service; disabled; vendor preset: enabled)
Active: inactive (dead)
(ログ略)
$ sudo rm /etc/systemd/system/hello.service
$ sudo systemctl daemon-reload
$ sudo systemctl status hello
Unit hello.service could not be found.
まとめ
crontab で @reboot some-command args
で常駐させているデーモンを置き換えるには、 以下のような unit ファイルを作って systemctl enable --now
すれば良いということを紹介しました。
[Service]
ExecStart=/path/to/some-command args
[Install]
WantedBy=multi-user.target