Linux & IT ノート

systemd の基本:サービスを自分で作る

管理人 約5分で読めます

Linux を日常的に使っていると、何かしらのデーモンを自分で管理したくなる場面が出てきます。 たとえば、自作のバックアップスクリプトを定期的に走らせたい、あるいは開発用の小さなサーバーをシステム起動時に自動で立ち上げたい ―― そういったときに頼りになるのが systemd の Unit ファイルです。

本記事では Unit ファイルの最小構成から始めて、enablestart・ログ確認まで一通りの流れを紹介します。 慣れてしまえば数分で書けるようになるので、ぜひ一度手を動かしてみましょう。

Unit ファイルの構成

Unit ファイルは /etc/systemd/system/ に置くテキストファイルです。 [Unit][Service][Install] の3セクションで構成されており、最小限の記述でサービスとして登録できます。

# /etc/systemd/system/myapp.service
[Unit]
Description=My Custom Application
After=network.target

[Service]
Type=simple
User=myuser
ExecStart=/usr/local/bin/myapp
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

[Unit] セクション

Description にはサービスの説明を書きます。After=network.target を指定すると、ネットワークが使用可能になってからサービスを起動するよう依存関係を設定できます。

[Service] セクション

実際に実行するコマンドを ExecStart に指定します。User でサービスを実行するユーザーを限定することで、余計な権限を与えずに済みます。

[Install] セクション

WantedBy=multi-user.target が最も一般的な設定です。これにより systemctl enable したときに、通常のマルチユーザーモードで自動起動するようリンクが張られます。

基本コマンドの流れ

Unit ファイルを作成または編集したあとは、daemon-reload で systemd に変更を読み込ませる必要があります。

# Unit ファイルを systemd に再読み込みさせる
sudo systemctl daemon-reload

# サービスをすぐに起動し、かつ自動起動も有効にする
sudo systemctl enable --now myapp

# サービスの状態を確認する
sudo systemctl status myapp

# ログをリアルタイムで追いかける
sudo journalctl -u myapp -f

enable --nowenablestart を一度に行う便利なオプションです。Unit ファイルを書いたら、まずこれを叩くのが習慣になると良いでしょう。

自動再起動の設定

Restart=on-failure[Service] セクションに追加しておくと、プロセスが予期せず終了したときに自動で再起動してくれます。本番環境での運用を想定するなら、この設定は最初から入れておくことをおすすめします。

また RestartSec=5 で再起動までの待機時間を秒単位で設定できます。連続クラッシュを防ぐため、短くしすぎず適切な間隔を設定しましょう。

[Service]
ExecStart=/usr/local/bin/myapp
Restart=on-failure
RestartSec=5
# 最大リスタート試行回数を制限したい場合
StartLimitIntervalSec=60
StartLimitBurst=3

よく使うデバッグコマンド

# 直近のログを20行表示する
sudo journalctl -u myapp -n 20

# エラーのみ表示する
sudo journalctl -u myapp -p err

# 今回の起動以降のログだけを見る
sudo journalctl -u myapp -b

# サービス一覧と状態を確認する
systemctl list-units --type=service --state=running

まとめ

systemd の Unit ファイルは一見とっつきにくいですが、基本構成を把握してしまえばあとは応用するだけです。 自作スクリプトをデーモン化したいときや、開発用サーバーをシステム起動時に自動で上げたいときなど、活躍の場は意外と多くあります。まずは小さなスクリプトをサービス化するところから試してみてください。