0Pricing
Linux Command Line & Bash Scripting Mastery · レッスン

systemdサービスの制御とユニットファイルの作成

systemctlでサービスを操作し、スクリプトで動かすデーモン用のカスタムユニットファイルやタイマーファイルを作成します。

「systemdサービスの制御とユニットファイルの作成」はCoddyKit上の無料Linux Command Line & Bash Scripting Masteryレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLinux Command Line & Bash Scripting Mastery学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Linux Command Line & Bash Scripting Masteryコースには全4レッスンが含まれています。

systemdとsystemctlの概要

systemdは、最新のLinuxディストリビューションの多くで使われているinitシステムおよびサービスマネージャーです。システムサービスの起動、停止、管理に加えて、ブートシーケンスとシステム状態の管理も担います。

systemdを操作するための主要なツールがsystemctlです。これを使うと、次の操作ができます。

  • サービスを起動および停止する
  • ブート時のサービスを有効化または無効化する
  • サービスの状態とログを確認する
  • 再起動せずに設定を再読み込みする

systemdが管理するすべてのサービスはユニットファイルで定義されています。ユニットファイルは宣言型の設定ファイルで、/etc/systemd/system/(システム全体)または~/.config/systemd/user/(ユーザー単位)に保存されます。

基本的なsystemctlコマンド

日常的なサービス管理で最もよく使うsystemctlコマンドを紹介します。各コマンドは、nginx.serviceや単にnginxのようなユニット名に対して操作を行います。

  • systemctl start <unit> — サービスを直ちに起動します
  • systemctl stop <unit> — 実行中のサービスを停止します
  • systemctl restart <unit> — 停止してから起動します(完全な再起動)
  • systemctl reload <unit> — サービスを停止せずに設定を再読み込みするため、SIGHUPを送信します
  • systemctl enable <unit> — 起動時にユニットが開始されるよう、シンボリックリンクを作成します
  • systemctl disable <unit> — それらのシンボリックリンクを削除します
  • systemctl status <unit> — 状態、PID、最近のログ行を表示します
#!/usr/bin/env bash
# Quick reference: inspect and control an nginx service
# (Requires nginx to be installed; run as root or with sudo)

systemctl status nginx
systemctl start nginx
systemctl enable nginx
systemctl reload nginx
systemctl restart nginx
systemctl stop nginx
systemctl disable nginx

サービスの状態を詳しく確認する

systemctl statusは、ユニットの詳細なスナップショットを表示します。問題をすばやく診断するには、出力内容を理解することが不可欠です。

  • Loaded: ユニットファイルのパスと、起動時に有効になっているかどうか
  • Active: 現在の状態 — active (running)、inactive (dead)、failed
  • Main PID: サービスのメインプロセスのプロセスID
  • CGroup: サービスに属するすべての子プロセス
  • Log lines: このユニットに関する最新のジャーナルエントリ

systemctl is-activeを使えばアクティブ状態だけを、systemctl is-enabledを使えば有効状態だけを問い合わせることもできます。これらはスクリプトでの利用に適しています。

#!/usr/bin/env bash
# Script-friendly service health check
SERVICE="sshd"

if systemctl is-active --quiet "$SERVICE"; then
    echo "$SERVICE is running."
else
    echo "$SERVICE is NOT running. Attempting restart..."
    systemctl restart "$SERVICE"
fi

if systemctl is-enabled --quiet "$SERVICE"; then
    echo "$SERVICE is enabled at boot."
else
    echo "WARNING: $SERVICE is not enabled at boot."
fi

ユニットの一覧表示とフィルタリング

多数のサービスを管理する場合は、ユニットを効率的に一覧表示し、フィルタリングする方法が必要です。systemctl list-unitsは現在ロードされているすべてのユニットを表示し、list-unit-filesはインストールされているすべてのユニットファイルと、その有効状態を表示します。

便利なフィルタリングオプション:

  • --type=service — サービスユニットだけを表示します
  • --state=failed — 失敗したユニットだけを表示します
  • --state=active — アクティブなユニットだけを表示します
  • --all — 一覧に非アクティブなユニットも含めます

これらのフィルターをgrepと組み合わせると、メンテナンススクリプトで強力な検査パイプラインを構築できます。

#!/usr/bin/env bash
# List all failed services and report them
echo "=== Failed Services ==="
systemctl list-units --type=service --state=failed --no-legend

echo ""
echo "=== Services Enabled at Boot ==="
systemctl list-unit-files --type=service --state=enabled --no-legend | awk '{print $1}'

systemdサービスユニットファイルの構成

サービスユニットファイルは、セクションで構成されたプレーンテキストのINI形式ファイルです。各セクションは、ユニットのライフサイクルにおける異なる側面を制御します。

  • [Unit] — メタデータ:説明、順序関係の依存関係(After=、Requires=、Wants=)
  • [Service] — プロセスの起動・停止方法:ExecStart、ExecStop、Restart、User、WorkingDirectory
  • [Install] — このユニットを有効にするタイミング:WantedBy=multi-user.targetは、通常のマルチユーザー起動時にアクティブ化することを意味します

/etc/systemd/system/にユニットファイルを配置または編集した後は、systemdが変更を取り込めるようにsystemctl daemon-reloadを実行する必要があります。

初めてのサービスユニットファイルを書く

カスタムPython HTTPサーバースクリプト用の、シンプルなサービスユニットファイルを作成します。このユニットファイルにより、systemdは他のシステムサービスと同じように、このプロセスを正確に管理できます。

ここで使用する主な[Service]ディレクティブ:

  • Type=simple — systemdはExecStartのプロセスをメインプロセスとして扱います
  • User=www-data — セキュリティのため、root以外のアカウントで実行します
  • WorkingDirectory — プロセスの作業ディレクトリを設定します
  • Restart=on-failure — プロセスが0以外のコードで終了した場合に自動的に再起動します
  • RestartSec=5 — 再起動を試みる間隔として5秒待機します
#!/usr/bin/env bash
# Create a custom service unit file for a simple HTTP server
# Run as root

cat > /etc/systemd/system/mywebserver.service << 'EOF'
[Unit]
Description=My Custom Python Web Server
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/mysite
ExecStart=/usr/bin/python3 -m http.server 8080
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now mywebserver.service
systemctl status mywebserver.service

サービスの種類とプロセスのライフサイクル

[Service]内のType=ディレクティブは、サービスの起動が完了したタイミングをsystemdがどのように追跡するかを指定します。誤った種類を選ぶと、順序制御のバグが発生することがあります。

  • Type=simple — デフォルトです。ExecStartが起動すると、systemdはサービスが開始されたとみなします。準備完了シグナルは必要ありません。
  • Type=forking — ExecStartのプロセスがフォークして終了し、実際のデーモンは子プロセスとして実行されます。systemdが追跡できるようにPIDFile=を使用します。
  • Type=notify — プロセスが実際に準備完了した時点でsd_notify(READY=1)を送信します。複雑なデーモンに最も信頼性の高い方式です。
  • Type=oneshot — 一度だけ実行して終了します。後続のユニットは完了するまで待機します。セットアップスクリプトに適しています。
  • Type=idle — simpleと同様ですが、アクティブなすべてのジョブが完了するまで実行を遅延させます。
#!/usr/bin/env bash
# Example: oneshot service for a database migration script
# /etc/systemd/system/db-migrate.service

cat > /etc/systemd/system/db-migrate.service << 'EOF'
[Unit]
Description=Run Database Migrations
After=postgresql.service
Requires=postgresql.service

[Service]
Type=oneshot
User=appuser
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/scripts/migrate.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl start db-migrate.service

環境変数とセキュリティ強化

サービスユニットファイルには、環境変数を渡したり、セキュリティ制限を適用したりするための複数のディレクティブがあります。どちらも本番システムでは重要です。

環境変数関連のディレクティブ:

  • Environment="KEY=value" — 1つの変数をインラインで設定します
  • EnvironmentFile=/etc/myapp/env — ファイルから変数を読み込みます(1行につき1つのKEY=value)

一般的なセキュリティ強化ディレクティブ:

  • NoNewPrivileges=true — setuidによってプロセスが追加の権限を取得するのを防ぎます
  • ProtectSystem=strict — /usr、/boot、/etcを読み取り専用でマウントします
  • PrivateTmp=true — サービス専用の隔離された/tmpを提供します
  • CapabilityBoundingSet= — Linuxのケーパビリティをすべて削除します
#!/usr/bin/env bash
# Hardened service unit with environment file

cat > /etc/systemd/system/secureapp.service << 'EOF'
[Unit]
Description=Secure Application Daemon
After=network.target

[Service]
Type=simple
User=secureapp
Group=secureapp
WorkingDirectory=/opt/secureapp
EnvironmentFile=/etc/secureapp/env
ExecStart=/opt/secureapp/bin/server
Restart=on-failure
RestartSec=10

# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
CapabilityBoundingSet=
ReadWritePaths=/var/lib/secureapp /var/log/secureapp

[Install]
WantedBy=multi-user.target
EOF

# Create the environment file separately so secrets stay out of the unit file
install -m 600 -o secureapp /dev/null /etc/secureapp/env
echo 'APP_PORT=9000' >> /etc/secureapp/env
echo 'DB_URL=postgresql://localhost/mydb' >> /etc/secureapp/env

systemctl daemon-reload

systemdタイマーユニット入門

systemdタイマーは、スケジュールに従って別のユニット(通常は.service)をアクティブ化するユニットです。従来のcronジョブを、より統合され、ログを記録でき、制御しやすい仕組みに置き換えます。

すべてのタイマーユニット(foo.timer)には、同じベース名を持ち、実際の処理を行うサービスユニット(foo.service)が対応します。有効化して起動するのはタイマーであり、サービスを直接有効化・起動するのではありません。

タイマーの種類:

  • Realtime(カレンダー)タイマー — OnCalendar=の式を使い、daily、weekly、Mon *-*-* 02:00:00のような実時間で発火します
  • モノトニックタイマー — OnBootSec=、OnActiveSec=、OnUnitActiveSec=を使い、システムイベントからの経過時間を基準に発火します

タイマーユニットファイルを書く

毎日02:00にバックアップスクリプトを実行する、タイマーとサービスの完全な組み合わせを作成します。[Timer]セクションは独立した.timerファイルに置き、実際の処理は対応する.serviceファイルに記述する点に注目してください。

主な[Timer]ディレクティブ:

  • OnCalendar= — スケジュールを表すカレンダー式
  • Persistent=true — タイマーが発火する予定の時刻にシステムが停止していた場合、次回起動時に直ちに実行します
  • RandomizedDelaySec= — 多数のホストが同じスケジュールを共有している場合の一斉実行を防ぐため、最大N秒のランダムな遅延を追加します
  • Unit= — 対象ユニットを明示的に指定します(名前が一致する場合は省略可能です)
#!/usr/bin/env bash
# Create a daily backup timer pair
# Run as root

# 1. The service that does the work
cat > /etc/systemd/system/daily-backup.service << 'EOF'
[Unit]
Description=Daily Database Backup
After=network.target postgresql.service

[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/backup-db.sh
StandardOutput=journal
StandardError=journal
EOF

# 2. The timer that schedules it
cat > /etc/systemd/system/daily-backup.timer << 'EOF'
[Unit]
Description=Run Daily Database Backup at 02:00

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
RandomizedDelaySec=300

[Install]
WantedBy=timers.target
EOF

systemctl daemon-reload
systemctl enable --now daily-backup.timer

# Verify
systemctl list-timers daily-backup.timer

ユニットのログ確認とトラブルシューティング

systemdはすべてのサービス出力をジャーナルに送り、journalctlで検索します。これにより、すべてのユニットのログを1つの検索可能なストアに集約できます。

サービスのトラブルシューティングに必要なjournalctlの主なフラグ:

  • -u <unit> — ユニット名で絞り込みます
  • -f — ログをリアルタイムで追跡します(tail -fと同様です)
  • -n 50 — 最後の50行だけを表示します
  • --since "1 hour ago" — 時間で範囲を限定します
  • -p err — エラーレベル以上だけを表示します
  • -b — 現在の起動時のログだけを表示します

ユニットの起動に失敗した場合は、まずjournalctl -u <unit> -n 30 --no-pagerを実行し、続けてsystemctl status <unit>を実行して直近のエラー状況を確認します。

#!/usr/bin/env bash
# Troubleshooting helper: dump unit status and recent logs
# Usage: ./service-debug.sh <unit-name>

UNIT="${1:-nginx.service}"

echo "=============================="
echo "STATUS: $UNIT"
echo "=============================="
systemctl status "$UNIT" --no-pager -l

echo ""
echo "=============================="
echo "RECENT LOGS (last 50 lines): $UNIT"
echo "=============================="
journalctl -u "$UNIT" -n 50 --no-pager

echo ""
echo "=============================="
echo "ERRORS ONLY (current boot)"
echo "=============================="
journalctl -u "$UNIT" -b -p err --no-pager

理解度チェック:systemdユニットファイル

systemdのサービスおよびタイマーユニットの設定について、理解度を確認しましょう。

レッスンのまとめ:systemdサービスの制御とユニットファイルの作成

このレッスンでは、systemdによるサービス管理と、ユニットファイルをプロフェッショナルなレベルで作成するための基本概念を学びました。ここまでの内容をまとめます。

  • systemctlの基本 — start、stop、restart、reload、enable、disable、status、is-active、is-enabledを使った、スクリプトで確認しやすい操作
  • 一覧表示とフィルタリング — list-unitsおよびlist-unit-filesと、--type・--stateフラグを使って、失敗または有効なサービスを絞り込みます
  • ユニットファイルの構成 — 3つのセクション[Unit]、[Service]、[Install]と、それぞれの主要なディレクティブ
  • サービスの種類 — simple、forking、notify、oneshotと、それぞれを使う場面
  • 環境とセキュリティ — 強化されたデーモンに使用するEnvironmentFile、NoNewPrivileges、ProtectSystem、PrivateTmp
  • タイマーユニット — .timerファイルと.serviceファイルの組み合わせ、OnCalendar式、Persistentによる実行漏れのキャッチアップ動作
  • Journalctl — ユニット、時間、起動、優先度によるフィルタリングで、障害を効率的に診断します

これらのスキルがあれば、あらゆるシステムサービスを管理し、定期タスクを確実にスケジュールし、自分のデーモン用に本番環境向けのユニットファイルを作成できます。

よくある質問

「systemdサービスの制御とユニットファイルの作成」レッスンは無料ですか?

はい。「systemdサービスの制御とユニットファイルの作成」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Linux Command Line & Bash Scripting Masteryコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Linux Command Line & Bash Scripting Masteryコースには全4レッスンが含まれています。

「systemdサービスの制御とユニットファイルの作成」で何を学びますか?

systemctlでサービスを操作し、スクリプトで動かすデーモン用のカスタムユニットファイルやタイマーファイルを作成します。 ブラウザで直接実行するハンズオンコードでLinux Command Line & Bash Scripting Masteryを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Linux Command Line & Bash Scripting Masteryを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのLinux Command Line & Bash Scripting Masteryは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「systemdサービスの制御とユニットファイルの作成」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このLinux Command Line & Bash Scripting Masteryレッスンでコードを書いて実行できますか?

はい。すべてのLinux Command Line & Bash Scripting Masteryレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. ユーザーとグループのプロビジョニング自動化
  2. systemdサービスの制御とユニットファイルの作成
  3. ディスク、ファイルシステム、マウントの自動化
  4. システムヘルスチェックとアラートスクリプトの構築
← Linux Command Line & Bash Scripting Masteryに戻る