mcpField
S
systemd-services

systemd-services

github.com/bagelholeクラウド・DevOps1.2k515 回インストール23 週間前に更新
リポジトリ

systemd-services について

systemd-services は、Linux 管理者向けの systemd スキルです。サービスユニット、タイマー、ソケットアクティベーションの設定に加え、依存関係、リソース制限、ジャーナル分析を扱います。

主な機能

  1. 01サービスユニットの作成と管理
  2. 02systemd タイマーの設定
  3. 03ソケットアクティベーションの構成
  4. 04依存関係とリソース制限の管理
  5. 05journalctl によるログ分析

活用シーン

  1. 01アプリケーションをバックグラウンドサービスとして実行
  2. 02cron ジョブをタイマーに置き換え
  3. 03サービスの起動や実行時障害の診断

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/bagelhole/devops-security-agent-skills --skill systemd-services

インストール後、Claude Code で/systemd-servicesを入力して読み込まれたか確認します。

詳細

Systemd サービス

systemd サービスとタイマーの作成、管理、監視を行います。ユニットファイルの作成、依存関係の管理、ソケットアクティベーション、リソース制限、journalctl によるログ分析、本番環境向けの強化を扱います。

使用する場面

  • アプリケーションを管理対象のバックグラウンドサービスとしてデプロイする
  • ログ記録と依存関係の制御を改善するために、cron ジョブを systemd タイマーに置き換える
  • 必要に応じてサービスを起動できるよう、ソケットアクティベーションを設定する
  • サービスのリソース制限(CPU、メモリ、I/O)を設定する
  • サービスの起動失敗や実行時のクラッシュをデバッグする
  • サービスの依存関係と起動順序を管理する

前提条件

  • systemd を実行している Linux システム(大半の最新ディストリビューション)
  • システムレベルのユニットファイルを作成するための root または sudo アクセス
  • サービスとして実行するアプリケーションのバイナリまたはスクリプト
  • アプリケーションの起動/停止ライフサイクルに関する理解

サービスユニットファイル -- 完全な例

# /etc/systemd/system/myapp.service
[Unit]
Description=MyApp Production Server
Documentation=https://docs.example.com/myapp
After=network-online.target postgresql.service
Wants=network-online.target
Requires=postgresql.service

[Service]
Type=notify
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp

# Environment configuration
EnvironmentFile=/etc/myapp/env
Environment=NODE_ENV=production
Environment=PORT=8080

# Execution
ExecStartPre=/opt/myapp/bin/migrate --check
ExecStart=/opt/myapp/bin/server --config /etc/myapp/config.yaml
ExecStartPost=/opt/myapp/bin/healthcheck.sh
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/opt/myapp/bin/graceful-stop.sh

# Restart behavior
Restart=on-failure
RestartSec=5
StartLimitIntervalSec=300
StartLimitBurst=5

# Timeouts
TimeoutStartSec=30
TimeoutStopSec=30
WatchdogSec=60

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

# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp

[Install]
WantedBy=multi-user.target

サービス管理コマンド

# Reload systemd after creating or modifying unit files
systemctl daemon-reload

# Start, stop, restart a service
systemctl start myapp
systemctl stop myapp
systemctl restart myapp

# Reload service configuration without restart (if supported)
systemctl reload myapp

# Enable service to start on boot
systemctl enable myapp

# Enable and start in one command
systemctl enable --now myapp

# Disable and stop
systemctl disable --now myapp

# Check service status
systemctl status myapp

# Check if a service is active, enabled, or failed
systemctl is-active myapp
systemctl is-enabled myapp
systemctl is-failed myapp

# List all running services
systemctl list-units --type=service --state=running

# List all failed services
systemctl list-units --type=service --state=failed

# Show all properties of a service
systemctl show myapp

# Show specific property values
systemctl show myapp -p MainPID,MemoryCurrent,CPUUsageNSec

# Mask a service (prevent it from being started at all)
systemctl mask myapp

# Unmask
systemctl unmask myapp

# Reset a failed service state
systemctl reset-failed myapp

タイマーユニット(cron の置き換え)

タイマーファイル
# /etc/systemd/system/backup.timer
[Unit]
Description=Daily backup timer

[Timer]
# Run daily at 2:30 AM
OnCalendar=*-*-* 02:30:00
# If the system was off at the scheduled time, run when it boots
Persistent=true
# Add random delay up to 15 minutes to avoid thundering herd
RandomizedDelaySec=900
# Associate with a specific service (defaults to same name .service)
Unit=backup.service

[Install]
WantedBy=timers.target
対応するサービスファイル
# /etc/systemd/system/backup.service
[Unit]
Description=Daily backup job
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/run-backup.sh
StandardOutput=journal
StandardError=journal
タイマーの管理
# Common OnCalendar expressions:
# minutely, hourly, daily, weekly, monthly
# *-*-* 06:00:00       Daily at 6 AM
# Mon..Fri *-*-* 09:00 Weekdays at 9 AM
# *:0/15               Every 15 minutes

# Validate calendar expressions
systemd-analyze calendar "Mon..Fri *-*-* 09:00"

# List all active timers
systemctl list-timers --all

# Enable and start a timer
systemctl enable --now backup.timer

# Run the associated service immediately (for testing)
systemctl start backup.service

ソケットアクティベーション

# /etc/systemd/system/myapp.socket
[Unit]
Description=MyApp Socket

[Socket]
ListenStream=8080
Accept=no
# Optionally bind to a specific IP
# ListenStream=10.0.1.10:8080

[Install]
WantedBy=sockets.target
# /etc/systemd/system/myapp.service
[Unit]
Description=MyApp Server
Requires=myapp.socket

[Service]
Type=notify
User=myapp
ExecStart=/opt/myapp/bin/server
# Service receives the socket file descriptor from systemd

[Install]
WantedBy=multi-user.target
# Enable the socket (service starts on first connection)
systemctl enable --now myapp.socket

# Check socket status
systemctl status myapp.socket

# List all listening sockets
systemctl list-sockets

依存関係の管理

# Key [Unit] directives for ordering and dependencies:
# After=            Start after these units (ordering only)
# Requires=         Hard dependency -- fail if this unit cannot start
# Wants=            Soft dependency -- try to start, don't fail if unavailable
# PartOf=           Stop this unit when the parent stops
# Conflicts=        Cannot run alongside this unit

# Visualize the dependency tree for a service
systemctl list-dependencies myapp

# Show reverse dependencies (who depends on this unit)
systemctl list-dependencies myapp --reverse

# Analyze boot order for a service
systemd-analyze critical-chain myapp.service

リソース制限(cgroups v2)

# /etc/systemd/system/myapp.service.d/limits.conf
# (drop-in override file)
[Service]
# Memory limits
MemoryMax=1G
MemoryHigh=768M

# CPU limits
CPUQuota=200%          # Up to 2 full CPU cores
CPUWeight=100          # Relative weight (default=100)

# I/O limits
IOWeight=50
IOReadBandwidthMax=/dev/sda 100M
IOWriteBandwidthMax=/dev/sda 50M

# Process limits
LimitNOFILE=65535
LimitNPROC=4096
TasksMax=512

# Disable OOM killer (let the app handle it)
OOMPolicy=continue
# Apply drop-in overrides without editing the main unit file
mkdir -p /etc/systemd/system/myapp.service.d/

cat <<'EOF' > /etc/systemd/system/myapp.service.d/limits.conf
[Service]
MemoryMax=1G
CPUQuota=200%
EOF

systemctl daemon-reload
systemctl restart myapp

# View current resource usage for a service
systemctl status myapp                  # Shows Memory and CPU
systemd-cgtop                          # Real-time cgroup resource usage

# Edit a service's overrides interactively
systemctl edit myapp
# This creates a drop-in file automatically

Journalctl によるログ分析

# Follow logs for a service in real time
journalctl -u myapp -f

# Show logs since last boot
journalctl -u myapp -b

# Show logs for a specific time range
journalctl -u myapp --since "2025-01-15 08:00" --until "2025-01-15 12:00"

# Show only error and above
journalctl -u myapp -p err

# Show the last 100 lines with full messages (no truncation)
journalctl -u myapp -n 100 --no-pager -l

# Show logs in JSON format (for parsing)
journalctl -u myapp -o json-pretty --no-pager | head -50

# Check journal disk usage and vacuum old entries
journalctl --disk-usage
journalctl --rotate
journalctl --vacuum-time=7d
journalctl --vacuum-size=500M

トラブルシューティング

症状診断コマンドよくある解決方法
サービスの起動に失敗するsystemctl status myapp、journalctl -u myapp -n 50ExecStart のパス、権限、設定の構文を確認します
サービスが再起動を繰り返すjournalctl -u myapp --since "5 min ago"StartLimitBurst を確認し、ログでクラッシュの有無を調べます
"Main process exited, code=exited, status=217"journalctl -u myappユニットファイルで指定されたユーザーまたはグループが存在しません
"Failed to set up mount namespacing"ProtectSystem/PrivateTmp を確認しますカーネルが古いか、SELinux によってブロックされています。ディレクティブを緩和します
タイマーが作動しないsystemctl list-timers、systemctl status backup.timerタイマーが有効になっていることを確認し、OnCalendar の式を検証します
依存先より先にサービスが起動するAfter= と Requires= を確認します起動順序を指定するために After=dependency.service を追加します
OOM によって強制終了されるjournalctl -k | grep oom、dmesgMemoryMax を増やすか、アプリケーションのメモリ使用量を最適化します
ポート 80 にバインドできないAmbientCapabilities を確認しますCAP_NET_BIND_SERVICE を追加するか、より大きいポート番号を使用します

関連スキル

  • linux-administration -- システム管理全般のコンテキスト
  • performance-tuning -- カーネルのチューニングとリソースの最適化
  • user-management -- サービスアカウントと権限
  • backup-recovery -- systemd タイマーを使ったバックアップのスケジュール設定

コメント