1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

systemdサービスの基本を理解する:サービスファイル・systemctl・journalctl入門

1
Posted at

はじめに

自宅サーバーやクラウド上のLinux環境でアプリを動かしていると、こんな悩みに出会うことがあります。

  • ターミナルを閉じたらアプリが止まってしまう
  • サーバーを再起動したら、また手動でアプリを起動し直さないといけない
  • アプリが落ちていたとき、原因を調べるログがどこにあるかわからない

これらをまとめて解決してくれるのが systemd という仕組みです。本記事では、systemdを構成する要素のうち特に登場頻度の高い「サービスファイル」「systemctl」「journalctl」の3つをまとめて解説します。

systemdとは

まず前提となるsystemdについて簡単に触れておきます。

  • Linuxのinitシステム。OS起動時に最初に起動するプロセス(PID 1)で、以後起動する全プロセスの管理元になる
  • 従来の/etc/init.d配下のシェルスクリプトで起動処理を書く方式(SysVinit)に代わり、Debian/Ubuntu/RHEL系/Fedoraなど現在の主要ディストリビューションで標準採用されている
  • サービスの起動・停止・依存関係の解決・並列起動・ログの一元管理などをまとめて担う

systemdが管理する対象は「ユニット(Unit)」と呼ばれ、常駐プログラムを扱うものが本記事のテーマであるサービスユニットです。

サービスファイル(Unitファイル)とは

サービスユニットの実体は、.serviceという拡張子を持つ設定用のテキストファイルです。「サービスファイル」「unitファイル」などと呼ばれます。

主な設置場所

パス 用途
/usr/lib/systemd/system/ パッケージ管理(apt/dnf等)でインストールされたサービスの標準定義
/etc/systemd/system/ 管理者が独自に追加・上書きするサービス定義。標準定義より優先される

自作のアプリをサービス化する場合は、基本的に/etc/systemd/system/配下に作成します。

基本構造

サービスファイルは[Unit] [Service] [Install]という3つのセクションで構成されるのが基本形です。FastAPIアプリを例にすると、以下のようなイメージになります。

/etc/systemd/system/sample-app.service
[Unit]
Description=Sample FastAPI Application
After=network.target

[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/sample-app
ExecStart=/opt/sample-app/venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8000
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

主なディレクティブは次の通りです。

セクション ディレクティブ 内容
[Unit] Description サービスの説明文
[Unit] After 起動順序の制御(このユニットの後に起動、が指定した対象より後になる)
[Unit] Requires / Wants 依存するユニットの指定(Requiresは必須依存、Wantsは緩い依存)
[Service] Type プロセスの起動形態(後述)
[Service] ExecStart サービス起動時に実行するコマンド
[Service] ExecStop サービス停止時に実行するコマンド(省略可)
[Service] Restart 異常終了時などの再起動ポリシー(no/on-failure/always等)
[Service] User / Group 実行ユーザー・グループの指定
[Service] WorkingDirectory 作業ディレクトリ
[Service] Environment / EnvironmentFile 環境変数の指定
[Install] WantedBy enable実行時にどのターゲット(起動段階)に紐づけるか

Typeには主に以下の種類があります。

Type 内容
simple ExecStartで起動したプロセスがそのままメインプロセスになる(デフォルト)
forking 起動時に一度フォークして親プロセスが終了する、従来型デーモン向け
oneshot 一度実行して終了する処理向け(常駐しない)
notify プロセス自身がsystemdに起動完了を通知する方式

サービスファイルを新規作成・変更した後は、systemctl daemon-reloadを実行しないと変更内容がsystemdに反映されません。編集後にstartrestartをしても反映されない場合、まずこのコマンドを忘れていないか確認するのがセオリーです。

systemctlとは

systemctlは、systemdが管理するユニットを操作するためのコマンドです。サービスの起動・停止から自動起動設定、状態確認まで、日常の運用操作はほぼこのコマンド一つでまかなえます。

主なサブコマンド

コマンド 内容
systemctl start <unit> 今すぐ起動する
systemctl stop <unit> 今すぐ停止する
systemctl restart <unit> 再起動する
systemctl reload <unit> プロセスを再起動せずに設定だけ再読み込みする(対応サービスのみ)
systemctl status <unit> 状態・直近ログを確認する
systemctl enable <unit> OS起動時に自動起動するよう設定する
systemctl disable <unit> 自動起動設定を解除する
systemctl enable --now <unit> 自動起動の有効化と今すぐの起動を同時に行う
systemctl is-enabled <unit> 自動起動設定になっているか確認する
systemctl is-active <unit> 現在稼働中かどうか確認する
systemctl list-units --type=service 実行中のサービス一覧を表示する
systemctl daemon-reload サービスファイルの変更をsystemdに反映する

「起動する」と「自動起動を設定する」は別物

見落としやすいポイントですが、startenableは役割が異なります。

  • start今この瞬間サービスを起動する。次回OS再起動時には引き継がれない
  • enable:OS起動時に自動的に起動されるよう登録する。ただし今すぐは起動しない

そのため、常駐させたいアプリではsystemctl enable --now sample-app.serviceのように両方をまとめて実行するのが定石です。

statusで見る主な状態

systemctl status <unit>を実行すると、Active:欄に稼働状態が表示されます。

表示 意味
active (running) プロセスが常駐して稼働中
active (exited) 正常に実行され、すでにプロセス自体は終了している状態(Type=oneshotなどで見られる)
inactive (dead) 停止している
failed 異常終了した
activating 起動処理中

active (exited)は一見「動いていない」ように見えますが、異常ではありません。ディストリビューションによっては、実体となる個別サービス(例:バージョン番号付きの子サービス)を起動するためだけの「ラッパー用ユニット」が用意されており、役目を終えると正常にexitする設計になっていることがあります。「exited=異常」と早合点せず、実際に目的のプロセスが起動しているかはpsコマンドや該当の個別サービスの状態で確認するのが確実です。

journalctlとは

journalctlは、systemdのログ収集の仕組みであるjournaldが集めたログを閲覧するためのコマンドです。

従来のLinuxでは、/var/log/syslog/var/log/auth.logのようにログの種類ごとにテキストファイルが分散していました。journald環境下では、各サービスの標準出力・標準エラー出力を含め、ログがバイナリ形式で一元的に記録されます(/var/log/journal/配下)。バイナリのため直接catでは読めず、journalctl経由で検索・整形して閲覧します。

主なオプション

オプション 内容
journalctl -u <unit> 特定のサービスのログのみ表示する
journalctl -f tail -fのようにリアルタイムで追尾表示する
journalctl -b 直近の起動以降のログのみ表示する
journalctl --since "10 min ago" 相対/絶対時刻を指定して絞り込む
journalctl -p err 優先度(緊急度)で絞り込む(指定レベル以上)
journalctl -r 新しい順(降順)に表示する
journalctl -n 50 末尾50行のみ表示する
journalctl --disk-usage ジャーナルが使用しているディスク容量を確認する
journalctl --vacuum-time=7d 7日より古いログを削除して容量を整理する

-pで指定できる優先度は、syslogの重大度レベルに準拠しています。

レベル 名称 内容
0 emerg システム利用不能
1 alert 直ちに対応が必要
2 crit 重大な状態
3 err エラー
4 warning 警告
5 notice 正常だが注意すべき事象
6 info 情報
7 debug デバッグ情報

自作サービスのログをリアルタイムで追いたいときは、次のように組み合わせるのが定番です。

journalctl -u sample-app.service -f

3つの関係性

ここまでの内容を一連の流れとして整理すると、次のようになります。

  1. サービスファイル/etc/systemd/system/に作成し、起動コマンドや再起動ポリシーを定義する
  2. systemctl daemon-reloadで変更をsystemdに反映する
  3. systemctl enable --now <unit>で自動起動を設定しつつ起動する
  4. 動作がおかしいときはsystemctl status <unit>で状態を確認し、詳細な原因はjournalctl -u <unit>でログを追う

この4ステップを押さえておけば、自作アプリを「落ちても自動的に立ち上がり直す常駐サービス」として運用するための基本は一通りカバーできます。

まとめ

要素 役割
サービスファイル サービスの起動方法・再起動ポリシーなどを定義する設定ファイル
systemctl サービスの起動・停止・自動起動設定・状態確認を行う操作コマンド
journalctl systemdが一元管理するログを検索・閲覧するコマンド

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?