Linuxのsystemd入門|systemctlでサービスを起動・自動起動する【初心者向け】

前の記事では、VPS を借りたら最初にやることを、チェックリストにまとめました。今回は、サーバーでプログラムを動かし続けるための systemd を学びます。

もし、VPS で Python のスクリプトを nohup で動かしていたら…。VPS 会社のメンテナンスでサーバーが再起動されると、スクリプトは止まったままになります。しかも、自分で見に行くまで気づけません。「サーバーが起動したら、自動でまた動き出してほしい」をかなえてくれるのが systemd です。

この記事では、自分のパソコンで、練習用のサービスを1つ作って、起動・停止・自動起動の設定までを試します。最後にきれいに消すので、安心して試してください。

💡
この記事でわかること
  • systemd とサービス(unit)とは何か
  • systemctl status・start・stop・restart の使い方
  • 自分のスクリプトをサービスにする .service ファイルの書き方
  • enable(自動起動)と start(今すぐ起動)のちがい
  • 止まったときに自動で立ち上げ直す Restart= の考え方
🔰
この記事の前提
  • シェルスクリプトを作って実行できる(chmod +x)
  • nohup や tmux(=ターミナルの作業画面を残したまま切りはなし、あとでまた戻れる道具)で、プログラムを動かし続けたことがある
  • sudo と nano を使える

まだの方は、前の記事「VPSを借りたら最初にやること|ユーザー作成・SSHの強化・ufwのチェックリスト【初心者向け】」と、Lv3 の nohup・tmux の記事から読むのがおすすめです。

💡
用語メモ
  • 環境変数:シェルが覚えていて、そこから動かすプログラムにも渡される「名前つきの設定値」(PATH や HOME など)。自分で作るときは export をつけます。つけないものは「シェル変数」で、今のシェルの中だけで使えます
  • フルパス(絶対パス):/home/kaito/memo.txt のように、いちばん上の / から書いた場所
  • VPS:大きな物理サーバーを区切って作った、自分専用の仮想サーバーを、月額などで借りられるサービス。root 権限で自由に設定できます
  • スクリプト:やりたい処理を順番に書いておき、まとめて実行できるファイル(小さなプログラム)

用語で迷ったら、連載のまとめ記事の「よく出てくる用語ミニ辞典」でも確かめられます。


結論:start は「今」、enable は「次の起動から」

コマンド 意味
systemctl status 名前 動いているか・最近のログを見る
sudo systemctl start 名前 今すぐ起動する
sudo systemctl stop 名前 今すぐ止める
sudo systemctl restart 名前 止めてから起動し直す
sudo systemctl enable 名前 パソコン(サーバー)の起動時に自動で起動する
sudo systemctl disable 名前 自動起動をやめる
sudo systemctl daemon-reload .service ファイルを書きかえたら読み直す

systemd のしくみ

準備:すでに動いているサービスを見てみる

Linux では、たくさんのサービスが systemd に見守られながら動いています。まずは cron(定期実行のサービス)の様子を見てみましょう。

  • 1
  • 2
  • 3
systemctl status cron --no-pager
systemctl is-active cron
systemctl is-enabled cron

🖥️
この記事の出力例について

ここから先の出力例は、Debian 13での実行例です(ユーザー名 kaito・パソコン名 demo のダミー環境)。UbuntuやWSL(=Windows の中で Linux を動かせる、Microsoft のしくみ)では、表示が少し違うことがあります。

(例)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
kaito@demo:~/linux-practice$ systemctl status cron --no-pager
● cron.service - Regular background program processing daemon
     Loaded: loaded (/usr/lib/systemd/system/cron.service; enabled; preset: enabled)
     Active: active (running) since Sun 2026-11-01 03:40:05 JST; 2min 41s ago
 Invocation: de820a05982e426488f91755e510e9b9
       Docs: man:cron(8)
   Main PID: 131 (cron)
      Tasks: 1 (limit: 19197)
     Memory: 364K (peak: 1.7M)
        CPU: 4ms
     CGroup: /system.slice/cron.service
             └─131 /usr/sbin/cron -f

Warning: some journal files were not opened due to insufficient permissions.
kaito@demo:~/linux-practice$ systemctl is-active cron
active
kaito@demo:~/linux-practice$ systemctl is-enabled cron
enabled

検証環境(Debian 13)では、cron は最初から入っていて、動いていました。最後の Warning: some journal files were not opened due to insufficient permissions. は、「権限が足りないので、一部のログ(記録)は開けませんでした」という意味です。cron は root(システム)として動いているため、一般ユーザーの kaito にはそのログが見えず、ログの数行の代わりにこの注意が出ています。sudo systemctl status cron --no-pager のように sudo をつけると、ログも表示されます。

--no-pager は、結果を less で開かずにそのまま表示するオプションです。Loaded の行の enabled は「自動起動する設定」、Active の行の active (running) は「今動いている」という意味です。

動いているサービスの一覧も見られます。

  • 1
systemctl list-units --type=service --state=running --no-pager

(例)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
kaito@demo:~/linux-practice$ systemctl list-units --type=service --state=running --no-pager
  UNIT                     LOAD   ACTIVE SUB     DESCRIPTION
  console-getty.service    loaded active running Console Getty
  cron.service             loaded active running Regular background program processing daemon
  dbus.service             loaded active running D-Bus System Message Bus
  exim4.service            loaded active running exim Mail Transport Agent
  systemd-journald.service loaded active running Journal Service
  systemd-logind.service   loaded active running User Login Management
  user@1000.service        loaded active running User Manager for UID 1000

Legend: LOAD   → Reflects whether the unit definition was properly loaded.
        ACTIVE → The high-level unit activation state, i.e. generalization of SUB.
        SUB    → The low-level unit activation state, values depend on unit type.

7 loaded units listed.

どのサービスが動いているかは、パソコンによってちがいます。最後の Legend は、それぞれの列の意味の説明です。


STEP 1:サービスにするスクリプトを作る

練習用に、10秒ごとに時刻を表示し続けるスクリプトを作ります。

  • 1
  • 2
  • 3
mkdir -p ~/linux-practice/systemd-test
cd ~/linux-practice/systemd-test
nano hello-loop.sh

次の内容を書いて保存します。

  • 1
  • 2
  • 3
  • 4
  • 5
#!/bin/bash
while true; do
  echo "kaito-hello: $(date '+%H:%M:%S') に動いています"
  sleep 10
done

  • 1
  • 2
  • 3
chmod +x hello-loop.sh
ls -l hello-loop.sh
pwd

(例)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
kaito@demo:~/linux-practice$ mkdir -p ~/linux-practice/systemd-test
kaito@demo:~/linux-practice$ cd ~/linux-practice/systemd-test
kaito@demo:~/linux-practice/systemd-test$ nano hello-loop.sh
kaito@demo:~/linux-practice/systemd-test$ chmod +x hello-loop.sh
kaito@demo:~/linux-practice/systemd-test$ ls -l hello-loop.sh
-rwxrwxr-x 1 kaito kaito 107 Nov  1 03:43 hello-loop.sh
kaito@demo:~/linux-practice/systemd-test$ pwd
/home/kaito/linux-practice/systemd-test

x がついていれば、実行できます。検証環境では -rwxrwxr-x でしたが、-rwxr-xr-x になるパソコンもあります(新しいファイルにつく、最初のパーミッションの設定のちがいです)。

pwd の結果は、次の .service ファイルで使うので控えておきましょう。


STEP 2:.service ファイルを作る

自分で作るサービスの設定ファイルは、/etc/systemd/system/ に置きます。システムの場所なので sudo が必要です。名前は、ほかと重ならないように kaito-hello.service にします。

  • 1
sudo nano /etc/systemd/system/kaito-hello.service

次の内容を書いて保存します。User= と ExecStart= は、自分のユーザー名とパスに合わせてください。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
[Unit]
Description=kaito の練習用サービス

[Service]
User=kaito
ExecStart=/home/kaito/linux-practice/systemd-test/hello-loop.sh
Restart=on-failure

[Install]
WantedBy=multi-user.target

書く場所 意味
[Unit] の Description サービスの説明(status に表示される)
[Service] の User どのユーザーとして動かすか(root にしない)
ExecStart 動かすコマンド(絶対パスで書く)
Restart=on-failure エラーで止まったら、自動で起動し直す
[Install] の WantedBy enable したとき、ふつうの起動の流れに加える

Restart=on-failure の「エラーで止まったら」は、スクリプトがエラーの終了コード(0 以外。シェルスクリプトの記事で見た $?)で終わったときや、強制的に止められたときのことです。systemctl stop で自分から止めたときや、スクリプトが最後まで進んで 0 で終わったときは、起動し直しません。止めたはずのサービスが勝手に動き出すことはないので、安心してください。

ファイルを作ったら、systemd に読み直してもらいます。

  • 1
  • 2
sudo systemctl daemon-reload
systemctl status kaito-hello --no-pager

(例)

  • 1
  • 2
  • 3
  • 4
  • 5
kaito@demo:~/linux-practice/systemd-test$ sudo systemctl daemon-reload
kaito@demo:~/linux-practice/systemd-test$ systemctl status kaito-hello --no-pager
○ kaito-hello.service - kaito の練習用サービス
     Loaded: loaded (/etc/systemd/system/kaito-hello.service; disabled; preset: enabled)
     Active: inactive (dead)

disabled は「自動起動しない」、inactive (dead) は「今は止まっている」という意味です。Description に書いた日本語も、そのまま表示されます。


STEP 3:start と stop を試す

  • 1
  • 2
sudo systemctl start kaito-hello
systemctl status kaito-hello --no-pager

(例)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
kaito@demo:~/linux-practice/systemd-test$ sudo systemctl start kaito-hello
kaito@demo:~/linux-practice/systemd-test$ systemctl status kaito-hello --no-pager
● kaito-hello.service - kaito の練習用サービス
     Loaded: loaded (/etc/systemd/system/kaito-hello.service; disabled; preset: enabled)
     Active: active (running) since Sun 2026-11-01 03:43:19 JST; 26s ago
 Invocation: ac16cea9b91e443a9021fe2d318156ca
   Main PID: 1851 (hello-loop.sh)
      Tasks: 2 (limit: 19197)
     Memory: 604K (peak: 1.8M)
        CPU: 14ms
     CGroup: /system.slice/kaito-hello.service
             ├─1851 /bin/bash /home/kaito/linux-practice/systemd-test/hello-loop.sh
             └─1857 sleep 10

Nov 01 03:43:19 demo hello-loop.sh[1851]: kaito-hello: 03:43:19 に動いています
Nov 01 03:43:29 demo hello-loop.sh[1851]: kaito-hello: 03:43:29 に動いています
Nov 01 03:43:39 demo hello-loop.sh[1851]: kaito-hello: 03:43:39 に動いています

CGroup の下には、サービスの中で動いているプログラム(スクリプトと、その中の sleep 10)が並びます。最後の3行が、スクリプトの echo の表示です。10秒おきに増えていきます。

Debian 13での実行画面

echo で表示した内容は、systemd がログとして預かっています。ログだけを見るときは journalctl(=systemd が集めたログを見るコマンド)を使います(くわしくは Lv4 のログの記事で)。

  • 1
journalctl -u kaito-hello -n 5 --no-pager

(例)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
kaito@demo:~/linux-practice/systemd-test$ journalctl -u kaito-hello -n 5 --no-pager
Hint: You are currently not seeing messages from other users and the system.
      Users in groups 'adm', 'systemd-journal' can see all messages.
      Pass -q to turn off this notice.
Nov 01 03:43:19 demo hello-loop.sh[1851]: kaito-hello: 03:43:19 に動いています
Nov 01 03:43:29 demo hello-loop.sh[1851]: kaito-hello: 03:43:29 に動いています
Nov 01 03:43:39 demo hello-loop.sh[1851]: kaito-hello: 03:43:39 に動いています

💡
最初の3行の「Hint」は、エラーではありません

一般ユーザーで journalctl を使うと、最初に Hint: から始まる3行が出ることがあります。「ほかのユーザーやシステムのログは見えていません。adm か systemd-journal グループ(=ユーザーをまとめたチーム)に入っているユーザーなら全部見られます。-q をつけるとこの表示を消せます」という意味です。今回の kaito-hello は User=kaito で動かしているので、kaito のままでもログを見られます。このあとの記事でも出てきますが、気にせず読み進めてください。

検証では、起動してから約25秒後に見たので、ログは3行でした(-n 5 は「最大5行」という意味です)。

止めて、止まったことを確かめます。

  • 1
  • 2
sudo systemctl stop kaito-hello
systemctl is-active kaito-hello

(例)

  • 1
  • 2
  • 3
kaito@demo:~/linux-practice/systemd-test$ sudo systemctl stop kaito-hello
kaito@demo:~/linux-practice/systemd-test$ systemctl is-active kaito-hello
inactive

STEP 4:enable で自動起動にする

enable は「次にパソコンを起動したときから、自動で起動する」設定です。今すぐは起動しないのがポイントです。

  • 1
  • 2
  • 3
sudo systemctl enable kaito-hello
systemctl is-enabled kaito-hello
systemctl is-active kaito-hello

(例)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
kaito@demo:~/linux-practice/systemd-test$ sudo systemctl enable kaito-hello
Created symlink '/etc/systemd/system/multi-user.target.wants/kaito-hello.service' → '/etc/systemd/system/kaito-hello.service'.
kaito@demo:~/linux-practice/systemd-test$ systemctl is-enabled kaito-hello
enabled
kaito@demo:~/linux-practice/systemd-test$ systemctl is-active kaito-hello
inactive

Debian 13での実行画面

「自動起動にして、今すぐ起動もする」は、--now をつけると1回でできます。

  • 1
  • 2
sudo systemctl enable --now kaito-hello
systemctl is-active kaito-hello

(例)

  • 1
  • 2
  • 3
kaito@demo:~/linux-practice/systemd-test$ sudo systemctl enable --now kaito-hello
kaito@demo:~/linux-practice/systemd-test$ systemctl is-active kaito-hello
active

この時点ではすでに enable 済みなので、enable --now は何も表示せず、今すぐの起動だけが行われました。まだ enable していないサービスなら、Created symlink … の行も表示されます。

本当に再起動後に動き出すかは、パソコンを再起動して systemctl status kaito-hello を見れば確かめられます。再起動してよいタイミングで、試してみてください。

🚫
ssh や ネットワークのサービスを止めない(文章だけで説明します)

sudo systemctl stop ssh や、ネットワーク関係のサービスを止めると、SSH でつないで作業している場合はその場で切断され、戻れなくなります。disable すると、次の起動からも動かなくなります。この記事で止めたり消したりするのは、自分で作った kaito-hello だけにしてください。どのサービスか自信がないときは、systemctl status で見るだけにしましょう。

🚫
サービスを root で動かさない

User= を書かないと、サービスは root として動きます。スクリプトに不具合があったとき、システム全体を壊すおそれがあります。自分で作るサービスには、User= に作業用のユーザーを書いておきましょう。

💡
Python のスクリプトをサービスにするときの3つのポイント(文章だけで説明します)

Lv3 で作った Python のスクリプト(venv と .env を使うもの)をサービスにするときは、[Service] の書き方に3つ気をつけます。

  1. venv の Python を絶対パスで書く:サービスでは source .venv/bin/activate が使えません。ExecStart=/home/kaito/プロジェクト/.venv/bin/python /home/kaito/プロジェクト/main.py のように、venv の中の python を直接指定します(venv の記事の「activate しなくても .venv/bin/python で動く」と同じ考え方です)。
  2. 作業フォルダを決める:WorkingDirectory=/home/kaito/プロジェクト を書くと、スクリプトの中の open("data.csv") のような短いパスが、そのフォルダから数えられます。cron の記事で cd してから動かしたのと同じ理由です。
  3. API キーは .service に直接書かない:EnvironmentFile=/home/kaito/プロジェクト/.env と書くと、.env(=APIキーなどの秘密の設定を書いておくファイル)の 名前=値 を環境変数として読みこめます。APIキーは、Web のサービスを使うときに本人の代わりになる、合言葉のような文字列です。.service ファイルはだれでも読める場所にあるので、キーを Environment= に直接書くより安全です(.env は chmod 600 にしておきます)。

もう1つ、Python は、画面ではなくログに出すとき、print の内容をためてから少しずつ出すことがあります。journalctl にすぐ表示されないときは、ExecStart の python のあとに -u をつける(.venv/bin/python -u main.py)か、Environment=PYTHONUNBUFFERED=1 を足すと、すぐに出るようになります。

🤖 詰まったらAIに聞こう:サービスが起動しない

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
Linuxの初心者です。systemdで自分のスクリプトをサービスにしましたが、起動しません。
原因の候補と、確かめる順番を教えてください。

【.serviceファイルの中身】ここに貼る(パスワードやトークンは消す)
【systemctl status 名前 --no-pager の結果】ここに貼る
【journalctl -u 名前 -n 30 --no-pager の結果】ここに貼る
【手で直接スクリプトを実行したときの結果】例:動く / エラーになる

🔒
AIに貼る前に:秘密情報やパスワードは貼らない

.service ファイルの Environment= に、API キーやパスワードを書いていることがあります。貼る前に「***」に置き換えてください。ログに、メールアドレスや IP アドレスが出ている場合も伏せましょう。


後片づけ

自動起動をやめて止め、.service ファイルを消してから、systemd に読み直してもらいます。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
sudo systemctl disable --now kaito-hello
sudo rm /etc/systemd/system/kaito-hello.service
sudo systemctl daemon-reload
systemctl status kaito-hello --no-pager
cd ~/linux-practice
rm -r systemd-test
ls

(例)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
kaito@demo:~/linux-practice/systemd-test$ sudo systemctl disable --now kaito-hello
Removed '/etc/systemd/system/multi-user.target.wants/kaito-hello.service'.
kaito@demo:~/linux-practice/systemd-test$ sudo rm /etc/systemd/system/kaito-hello.service
kaito@demo:~/linux-practice/systemd-test$ sudo systemctl daemon-reload
kaito@demo:~/linux-practice/systemd-test$ systemctl status kaito-hello --no-pager
Unit kaito-hello.service could not be found.
kaito@demo:~/linux-practice/systemd-test$ cd ~/linux-practice
kaito@demo:~/linux-practice$ rm -r systemd-test
kaito@demo:~/linux-practice$ ls
archive-test  chmod-test  edit-test  find-test  grep-test  link-test  perm-test  redirect-test

よくある質問

Q. status に「status=203/EXEC」と出て、起動しません。

systemd が ExecStart のコマンドを実行できなかった、という意味です。よくある原因は、パスのまちがい(絶対パスになっていない、つづりがちがう)、スクリプトに実行権限(x)がない、1行目の #!/bin/bash がない、の3つです。ls -l でパスと権限を確かめ、手で直接スクリプトを動かしてみましょう。

Q. .service ファイルを直したのに、前の内容のまま動きます。

systemd は、.service ファイルを直しただけでは読み直しません。直したあとは sudo systemctl daemon-reload をしてから、sudo systemctl restart 名前 で起動し直します。読み直しを忘れると、systemctl status に「changed on disk」のような、読み直しをすすめる表示が出ることがあります。

Q. WSL で systemctl を打つと、エラーになります。

WSL では、systemd が動いていない設定になっている場合があります(WSL のバージョンや設定など、環境により異なります)。Microsoft の説明では、WSL の中の /etc/wsl.conf に [boot] と systemd=true を書き、Windows 側で wsl --shutdown してから開き直すと、systemd が使えるようになります。また、WSL はウィンドウをすべて閉じると、しばらくして Linux ごと止まる場合があるため、「ずっと動かしておく」用途には VPS が向いています。


まとめ

  • systemd は、Linux のサービスを起動・見守る係。systemctl で操作する
  • start・stop は「今」、enable・disable は「次の起動から」。両方は enable --now
  • 自分のサービスは /etc/systemd/system/名前.service に書き、daemon-reload で読み直す
  • ExecStart は絶対パス、User= は作業用ユーザー、Restart=on-failure で止まっても起動し直す
  • 止めたり消したりするのは、自分で作ったサービスだけ

次の記事では、systemd のもう1つの便利な機能、systemd timer を学びます。cron とどうちがうのか、どちらを使えばいいのかを比べます。


次に読む記事


関連する記事