何が起きているか
systemctl start myapp.service を実行したところ、systemdが以下のエラーを返しました:
Job for myapp.service failed because the control process exited with error code.
See "systemctl status myapp.service" and "journalctl -xe" for details.
このメッセージ自体はほぼ無意味です — 「プロセスが0以外の終了コードで終了した」という汎用的なラッパーに過ぎません。本当の原因はもう一段深いところにあります。以下でその取り出し方を説明します。
ステップ1:実際のエラーを取得する
2つのコマンドを両方実行してください:
systemctl status myapp.service
journalctl -u myapp.service -n 50 --no-pager
1つ目は短いログの末尾と終了コードを表示します。2つ目は直近50行のログをターミナルに直接出力します。障害が直前に発生した場合は、journalctl -xe も有効で、タイムスタンプ周辺のカーネルレベルのコンテキストも追加されます。
FAILED、error、またはプロセスの生出力が含まれる行を探してください — そこに本当のメッセージがあります。
ステップ2:根本原因を特定する
ほとんどのケースは6つの原因のいずれかに該当します。この順序で確認してください:
バイナリパスが間違っているか実行ファイルが存在しない
ExecStart= が存在しないパスを指しているか、ファイルに実行権限がありません。
# ユニットファイルを確認する
systemctl cat myapp.service
# バイナリが存在するか確認する
which myapp
ls -la /usr/local/bin/myapp
ユニットファイルのパスを修正するか、不足しているバイナリをインストールしてください。
権限が拒否されている
サービスが(User= を使用して)非rootユーザーとして実行される場合、そのユーザーにはバイナリ、設定ファイル、作業ディレクトリへの読み取り/実行権限が必要です。いずれか一つが欠けると即座にクラッシュします。
# サービスが実行されるユーザーを確認する
grep -E 'User=|Group=|WorkingDirectory=' /etc/systemd/system/myapp.service
# 手動でアクセスをテストする
sudo -u serviceuser /usr/local/bin/myapp --config /etc/myapp/config.yaml
所有権または権限を調整します:
chown serviceuser:serviceuser /etc/myapp/config.yaml
chmod 750 /var/lib/myapp
ポートがすでに使用中
使用中のポートへのバインドは起動時に即座に失敗します。よくある原因:同じアプリの別インスタンス、または以前のクラッシュによる残留プロセスです。
ss -tlnp | grep :8080
# または
lsof -i :8080
競合しているプロセスを終了させるか、アプリの設定でポートを変更してください。
環境変数が不足しているか設定が不正
EnvironmentFile= に依存するアプリは、そのファイルが存在しないか無効な値を含む場合に即座に終了します。
# EnvironmentFileが存在するか確認する
grep EnvironmentFile /etc/systemd/system/myapp.service
ls -la /etc/myapp/.env
envファイルを作成または修正し、サービスユーザーとして手動実行したときにバイナリが実際に起動するか確認します:
sudo -u serviceuser bash -c 'source /etc/myapp/.env && /usr/local/bin/myapp'
ユーザーまたはグループが存在しない
ユニットファイルの User= または Group= で指定されたユーザー/グループがシステムに存在しない場合、systemdはサービスの起動を拒否します。クリーンインストール後によく見られる問題です。
id serviceuser
存在しない場合は作成します:
useradd --system --no-create-home --shell /usr/sbin/nologin serviceuser
共有ライブラリが不足している
バイナリがディスク上に存在していても、実行時に必要な .so ライブラリが見つからない場合は起動に失敗します。
ldd /usr/local/bin/myapp
not found と表示されるライブラリはインストールが必要です。不足しているパッケージをインストールするか、ユニットファイルの Environment= ディレクティブで LD_LIBRARY_PATH にライブラリパスを追加してください。
ステップ3:修正を適用してリロードする
/etc/systemd/system/myapp.service のユニットファイルを編集しましたか?必ずデーモンを先にリロードしてください — systemdはユニットファイルをメモリにキャッシュしており、そうしないと変更を反映しません:
systemctl daemon-reload
systemctl restart myapp.service
設定ファイル、権限、envファイルのみを変更した場合(ユニットファイル自体は変更していない場合)は、daemon-reload をスキップして直接再起動できます:
systemctl restart myapp.service
確認
ステータスを確認します:
systemctl status myapp.service
Active: active (running) と表示されれば成功です。遅延エラーを検出するために約30秒間ライブログを確認してください:
journalctl -u myapp.service -f
再起動後も有効にしたい場合は有効化します:
systemctl enable myapp.service
クイックデバッグチートシート
systemctl status myapp.service— 直近のログ数行と終了コードjournalctl -u myapp.service -n 100— ユニットの直近フルログjournalctl -xe— 障害周辺のシステム全体のコンテキストsystemctl cat myapp.service— 使用中の実際のユニットファイルを表示systemd-analyze verify myapp.service— ユニットファイルの構文を検証
得られた教訓
*「Control process exited with error code」*はsystemdが「プロセスが0以外で終了した」と言っているだけです。それだけです。毎回すぐに journalctl -u servicename を実行してください — ユニット固有のログはこの種の障害において journalctl -xe よりもはるかに有用です。また、独自のサービスを作成する場合は、stderrまたはstdoutにログを出力してください。systemdは両方をキャプチャするので、エラーメッセージが即座に journalctl に表示されます。

