Linux管理・運用の基本
システム管理者のための実践ガイド
システム管理者のための実践ガイド
この記事では、Linuxのサービス管理において中心的な役割を果たすsystemdのユニットファイルについて、その詳細な構造と編集方法を解説します。独自のサービスを作成したり、既存のサービスの挙動をカスタマイズしたりする際に、ユニットファイルの中身を理解することは不可欠です。
[Service]
セクションの主要オプション[Unit]
セクションのオプションsystemdは、システム上の様々なリソース(サービス、デバイス、マウントポイントなど)をユニットとして管理します。その定義ファイルがユニットファイルです。サービスを定義する.service
ファイルが最も一般的ですが、他にもマウントポイントを定義する.mount
やソケットを定義する.socket
などがあります。
ユニットファイルは、Windowsの.ini
ファイルに似たシンプルなテキスト形式です。セクションヘッダー([Unit]
など)と、そのセクション内のキーと値のペア(Description=
, ExecStart=
など)で構成されています。
ユニットファイルは、主に以下のディレクトリに配置されます。
ディレクトリ | 説明 |
---|---|
/lib/systemd/system/ ( /usr/lib/systemd/system/ ) |
ディストリビューションが提供するユニットファイル。基本的に直接編集はしません。最近のディストリビューションでは /usr/lib/systemd/system/ が標準です。 |
/etc/systemd/system/ |
管理者が手動で作成・編集する場所。/lib/ 内のファイルをオーバーライドする目的でも使用します。 |
/etc/systemd/system/<サービス名>.d/ |
systemctl edit コマンドで作成される設定ファイル群。 |
systemctl edit
コマンドを使った安全な編集
既存のユニットファイルの設定を部分的に変更したい場合は、systemctl edit <サービス名>
コマンドを使うのが最も安全です。このコマンドを実行すると、元のファイルを直接編集するのではなく、/etc/systemd/system/<サービス名>.d/
ディレクトリ内に新しい設定ファイルが作成されます。これにより、ディストリビューションのアップデートで元のファイルが変更されても、カスタマイズした設定が上書きされることがありません。
元の設定を完全に上書きしたい場合
元の設定をすべて破棄して、ゼロから新しい設定を書きたい場合は、systemctl edit --full <サービス名>
を使います。このコマンドは、元のファイルを/etc/systemd/system/
にコピーし、編集を開始します。この場合、アップデートで元のファイルが変更されても、ユーザーが編集したファイルが優先されます。
現在のユニットファイルの内容を確認する
サービス設定を変更する前に、systemctl cat <サービス名>
コマンドで、現在有効になっているユニットファイルの内容をすべて確認できます。オーバーライドファイルもすべてまとめて表示されるため、最終的な設定内容を把握するのに役立ちます。
[Unit]
セクション:依存関係とメタデータ[Unit]
セクションは、すべてのユニットタイプに共通するメタデータや、他のユニットとの依存関係を定義します。
オプション | 説明 | 例 |
---|---|---|
Description |
ユニットの説明。systemctl status などで表示されます。 |
Description=My Custom Web Server |
Documentation |
関連ドキュメントのURL。 | Documentation=https://example.com/docs |
After , Before |
起動の順序を制御します。After=network.target とすると、network.target の後にこのサービスが起動します。Before はその逆です。 |
After=network-online.target |
Wants , Requires |
依存関係を定義します。Wants= は推奨的な依存関係で、依存先が起動に失敗しても自身の起動は試行されます。Requires= はより厳格で、依存先が起動に失敗すると自身の起動も失敗します。 |
Wants=mysql.service |
Conflicts |
競合するユニットを定義します。このユニットが起動すると、指定したユニットは停止されます。 | Conflicts=apache2.service |
Wants
とRequires
、After
とBefore
の関係
Wants
やRequires
は、論理的な依存関係を定義します。これは「Aが起動するにはBが必要」という関係です。一方、After
やBefore
は、起動の物理的な順序を定義します。「AはBの後に起動する」という関係です。
Webアプリケーションなど、ネットワーク接続が完了してから起動したいサービスには、After=network-online.target
と Wants=network-online.target
を組み合わせるのが一般的なベストプラクティスです。これにより、ネットワークが利用可能になってからサービスが起動するようになります。
起動順序のボトルネックを調べる
systemd-analyze blame
コマンドは、システムの起動時にどのサービスがどれくらいの時間を消費しているかを表示します。また、systemd-analyze critical-chain <サービス名>
を使うと、指定したサービスが起動するまでの依存関係チェーンを可視化できます。これらのコマンドは、起動順序の問題を特定するのに非常に役立ちます。
[Service]
セクション:サービスの核となる定義とセキュリティ[Service]
セクションは、サービスユニットに特有の設定を定義します。このセクションが、サービスの起動、停止、再起動方法を決定します。
オプション | 説明 | 例 |
---|---|---|
Type |
サービスの種類。simple 、forking 、oneshot など。詳細は後述。 |
Type=simple |
ExecStart |
サービスを起動するためのコマンド。フルパスで記述します。 | ExecStart=/usr/bin/python3 /opt/my-app/app.py |
ExecStartPre |
ExecStart の実行前に実行するコマンド。 |
ExecStartPre=/bin/mkdir -p /var/log/my-app |
ExecStartPost |
ExecStart の実行後に実行するコマンド。 |
ExecStartPost=/bin/touch /var/log/my-app/started |
ExecStop |
サービスを停止するためのコマンド。 | ExecStop=/bin/kill -TERM $MAINPID |
ExecReload |
サービスをリロードするためのコマンド。このオプションがない場合、systemctl reload はExecStop とExecStart を実行してサービスを再起動します。 |
ExecReload=/bin/kill -HUP $MAINPID |
Restart |
サービスが終了したときの再起動ポリシー。always 、on-failure など。 |
Restart=on-failure |
RestartSec |
再起動までの待機時間(秒)。 | RestartSec=5s |
SuccessExitStatus |
成功と見なされる終了コード。デフォルトは0 。 |
SuccessExitStatus=0 1 2 |
WorkingDirectory |
サービスプロセスの作業ディレクトリ。 | WorkingDirectory=/opt/my-app |
User , Group |
サービスを実行するユーザー・グループ。 | User=www-data |
Environment |
サービスプロセスに追加する環境変数。 | Environment="PORT=8080" |
EnvironmentFile |
環境変数を外部ファイルから読み込みます。 | EnvironmentFile=/etc/default/my-app |
StandardOutput , StandardError |
標準出力と標準エラーの出力先。デフォルトはjournal 。 |
StandardOutput=journal StandardError=inherit |
OOMScoreAdjust |
OOM killerのスコアを調整。 | OOMScoreAdjust=-500 |
サンドボックス(セキュリティ強化)機能
systemdは、サービスを隔離してセキュリティを強化する機能も提供しています。
ProtectSystem=full
: /usr/
や/boot/
など、システムディレクトリへの書き込みアクセスを禁止します。ProtectHome=true
: /home/
や/root/
など、ユーザーのホームディレクトリへのアクセスを禁止します。PrivateTmp=true
: サービス専用の一時ディレクトリ(/tmp/
と/var/tmp/
)を作成し、他のサービスやシステムから隔離します。【補足】より詳細なオプションを知るには
[Service]
セクションに関するすべてのオプションについては、man systemd.service
を参照してください。また、Exec*
系のコマンドに関するより詳細な挙動は、man systemd.exec
で確認できます。
[Install]
セクション:サービス有効化(enable
)の設定[Install]
セクションは、systemctl enable
コマンドが実行されたときに、サービスがどのターゲットと結びつくかを定義します。
オプション | 説明 | 例 |
---|---|---|
WantedBy |
指定したターゲットが起動するときに、このサービスも起動するようにします。Wants の関係が作られます。 |
WantedBy=multi-user.target |
RequiredBy |
WantedBy の厳格版。Requires の関係が作られます。 |
RequiredBy=some-critical.target |
systemctl enable
の仕組み
systemctl enable
コマンドは、[Install]
セクションに定義されたWantedBy
やRequiredBy
をもとに、/etc/systemd/system/
配下にある対応するターゲットのディレクトリに、ユニットファイルへのシンボリックリンクを作成します。これにより、システムの起動時にそのターゲットが呼び出されると、リンク先のサービスも自動的に起動するようになります。
ユーザー単位の自動起動
システム全体ではなく、特定のユーザーがログインしたときにサービスを起動したい場合は、WantedBy=default.target
を指定し、systemctl --user
コマンドでサービスを有効化します。
以下の例は、Pythonで書かれたシンプルなウェブサーバーをsystemdサービスとして起動するユニットファイルです。
my-webserver.service
[Unit]
Description=My Simple Python Web Server
Documentation=https://example.com/docs
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=my-user
Group=my-user
WorkingDirectory=/home/my-user/web-app
ExecStart=/usr/bin/python3 /home/my-user/web-app/app.py
Restart=on-failure
RestartSec=10s
StandardOutput=journal
StandardError=inherit
Environment="PORT=8080"
ProtectHome=true
ProtectSystem=full
PrivateTmp=true
[Install]
WantedBy=multi-user.target
サービスの有効化と起動
このファイルを/etc/systemd/system/my-webserver.service
として保存し、以下のコマンドでサービスを有効化、起動します。
sudo systemctl daemon-reload
sudo systemctl enable my-webserver.service
sudo systemctl start my-webserver.service
sudo systemctl status my-webserver.service
サービスが起動しない、エラーの原因が知りたい
systemctl status <サービス名>
コマンドで、現在のステータスと直近のエラーログを確認します。より詳細なログは journalctl -u <サービス名> -e
で見ることができます。
サービスが繰り返し再起動してしまう
RestartSec
を調整して再起動までの待機時間を長くするか、StartLimitInterval
(古いバージョンではStartLimitIntervalSec
)と
StartLimitBurst
を使って、指定した時間内に再起動を試みる回数を制限します。
ユーザーサービスがログアウト後に停止してしまう
ユーザーサービスは通常、ユーザーがログアウトすると停止します。セッション終了後もサービスを動かし続けたい場合は、loginctl enable-linger <ユーザー名>
コマンドを実行します。
設定を変更したのに反映されない
ユニットファイルを編集した後は、必ず sudo systemctl daemon-reload
を実行して、systemdに新しい設定を読み込ませる必要があります。
現在の有効な設定値を確認したい
systemctl show <サービス名>
コマンドを使用すると、ユニットファイルに設定されているすべてのオプションと、その有効な値が一覧で表示されます。特定のオプションのみを確認したい場合は、grep
と組み合わせると便利です。
systemctl show my-webserver.service | grep Restart
ログファイルが肥大化して困る
journald
のログは/etc/systemd/journald.conf
で容量を制限できます(例:SystemMaxUse=50M
)。また、journalctl
には、時間でログを絞り込む便利なオプションがあります。
journalctl --since "1 hour ago" -u <サービス名>
この記事では、systemdのユニットファイルについて、その構成要素である[Unit]
、[Service]
、[Install]
の各セクションを詳細に解説しました。これらの設定を適切に組み合わせることで、システムの起動・停止・再起動を自在に制御し、独自のサービスを安全かつ確実に運用できるようになります。
この記事が、systemdのユニットファイルについて理解を深める一助となれば幸いです。ご覧いただきありがとうございました。次回は、より高度な機能であるタイマーユニットとソケットユニットについて解説します。