LASSIC Media らしくメディア

2026.10.09 らしくコラム

Linuxデーモンとは?プログラムを常に動かしておく設定方法

監修・編集責任者:牛尾 昭昌(株式会社LASSIC 執行役員)

iTerm2のターミナルに、Ubuntuのバージョンや稼働時間、プロセス数などのシステム情報が表示されている画面の写真。

この記事の結論

  • Linuxデーモンは端末から離れて動き続けるプロセスで、いまは自分でforkせず、systemdに起動・監視・停止を任せる作り方が勧められています。
  • 常駐化で決めておくのは、起動完了の伝え方(Type=)、SIGTERMでの後始末、異常終了時の再起動(Restart=)、ログの行き先の4つです。
  • つまずきやすいのは、daemon-reloadの忘れ、Type=simpleで起動失敗が見えないこと、再起動の回数制限、ジャーナルの保存先です。

※ 本記事は2026年10月時点の公式情報(省庁・公的機関、および製品やサービスを提供する事業者が公開している資料)に基づきます。

Linuxデーモンとは、端末から切り離されてバックグラウンドで動き続け、システムを見張ったり、ほかのプロセスに機能を提供したりするプロセスのことです。Webサーバーやデータベース、ログの収集、監視のエージェントなど、サーバーで常に動いているソフトウェアの多くがこの形をとります。

ところが作り方を調べると、二重のforkといった古い作法と、systemdのユニットファイルによる新しい作法が混ざっていて迷いがちです。本記事では、システム開発やIT運用に携わる方に向けて、デーモンの仕組み、サービスとの違い、常駐させる具体例、つまずきやすい点、外部に頼むときの確認点を、Linuxのman-pagesをもとに整理します。

Linuxデーモンとは

Linuxのman-pagesのdaemon(7)は、デーモンを「バックグラウンドで動き、システムを監督する、またはほかのプロセスに機能を提供するサービスのプロセス」と説明しています。*1 作り方には、SysV(UNIX System V)に由来する従来の方式と、systemdが実装している新しい方式があり、いまは新しい方式に従うべきだとしています。

ふつうのコマンドは端末を閉じれば一緒に終わりますが、デーモンは端末に結びつかずに動くため、ログアウトしても止まりません。

理解の鍵は、デーモンそのものと、それを起動して見張るサービスマネージャーを分けて考えることです。本記事はサービスマネージャーとしてsystemdを前提に説明します。プロセスそのものの仕組みは「プロセスとスレッドの違い」で扱っています。

従来のデーモン化の手順

従来のSysV方式では、プログラムが自分の力でデーモンになります。daemon(7)は、起動時に踏むべき手順を15項目挙げています。*1 主なものは次のとおりです。

  • 標準入力・標準出力・標準エラー以外のファイル記述子をすべて閉じ、シグナルの設定を既定に戻す
  • fork()で子を作り、子でsetsid()を呼んで端末から離れ、新しいセッションを作る
  • もう一度fork()し、最初の子は終了する。残った孫がデーモンになり、init(PID 1)の子に付け替えられる
  • 標準入出力を/dev/nullにつなぎ、umaskを0に戻し、作業ディレクトリをルート(/)に移す
  • PIDファイルを書いて二重起動を防ぎ、可能なら権限を落とし、起動した元のプロセスに初期化の完了を知らせる

2回forkするのは、デーモンが端末をふたたび制御端末として持たないようにするためです。C言語のdaemon()関数はこの処理をまとめたものですが、glibcの実装は二重のforkを行わず、できたデーモンはセッションリーダーのままになるとdaemon(3)は注意しています。*2

新しい方式では、これらの手順はどれも要りません。systemdは環境変数やシグナルの設定を整えた状態でデーモンを起動し、標準出力と標準エラーはログを集めるsystemd-journaldにつながります。*1 手順の一部はプロセスの監視を妨げるので、実行しないよう勧められています。

サービスとの違い

「デーモン」と「サービス」は混同されがちですが、systemdの用語では指すものが違います。デーモンは動き続けるプロセスそのものです。一方、サービスは名前が.serviceで終わるユニットファイルで、systemdが制御し監督するプロセスの情報を書いたものです。*3

デーモンとsystemdのサービスユニットの違い(この記事の整理)
観点 デーモン サービスユニット
実体 動き続けるプロセス .serviceで終わる設定ファイル
書く内容 処理そのもの(要求を待つ、見張るなど) 起動の方法、実行するユーザー、再起動の条件、依存関係
操作の窓口 シグナルを受けて止まる・設定を読み直す systemctlで起動・停止・自動起動の登録をする
ログ 標準出力・標準エラーに書く journaldが集め、journalctlで見る

サービスがいつもデーモンとは限りません。Type=oneshotのサービスは、メインのプロセスが終わった時点で起動済みと見なされ、常駐しません。「サービスを作る」と頼まれたら、常駐させたいのか、一度動けばよいのかを先に確かめます。

具体例:ユニットファイルで常駐化

daemon(7)は、新しい方式のデーモンに、SIGTERMでの終了、SIGHUPでの設定の読み直し、正しい終了コードを勧めています。*1 これを満たす最小のプログラムをPythonで書くと次のようになります。forkはせず、前面で動き続けるだけです。

import signal, sys, time

running = True

def on_term(signum, frame):
    global running
    running = False              # 終了の要求:ループを抜けて後始末する

def on_hup(signum, frame):
    print("設定を読み直します", flush=True)   # 設定ファイルの再読み込みを行う

signal.signal(signal.SIGTERM, on_term)
signal.signal(signal.SIGHUP, on_hup)
print("起動しました", flush=True)         # 標準出力はjournalに届く
while running:
    time.sleep(1)                # ここで本来の処理を行う
print("停止します", flush=True)
sys.exit(0)

flush=Trueは、Pythonの標準出力が対話的でないときはブロック単位でためて書き出されるためです。*9 付けないとログが遅れて届きます。-uオプションや環境変数PYTHONUNBUFFEREDでも同じです。このプログラムを/opt/report-agent/agent.pyに置くと、ユニットファイルは次のようになります。

[Unit]
Description=Report agent (sample)

[Service]
Type=exec
User=reportagent
ExecStart=/usr/bin/python3 /opt/report-agent/agent.py
ExecReload=kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
TimeoutStopSec=30
NoNewPrivileges=yes
ProtectSystem=full

[Install]
WantedBy=multi-user.target

Type=execは、実行に成功した時点で起動済みと見なす設定で、実行ファイルが無ければ起動の失敗として返ります。Restart=on-failureは異常終了のときに再起動する設定で、長く動き続けるサービスに勧められています。*3 User=を書かないとrootで動くので、専用のユーザーを指定します。

NoNewPrivileges=yesは子のプロセスまで含めて権限の引き上げを禁じ、ProtectSystem=fullは/usr、/boot、/etcなどを読み取り専用にします。*5 WantedBy=multi-user.targetは起動時に自動で立ち上げるための記述です。ExecReload=はman-pagesの例に沿った書き方ですが、完了を待たない再読み込みはふつう良い選び方ではないとも書かれており、順番をそろえたいならType=notify-reloadを検討します。

sudo cp report-agent.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now report-agent.service
systemctl status report-agent.service
journalctl -u report-agent.service -f

/etc/systemd/systemは管理者が作ったユニットを置く場所です。enableは[Install]の記述に沿ってシンボリックリンクを作るだけで起動はせず、–nowを付けると同時に起動します。*7 statusは状態と直近のログを表示し、journalctlの-uはそのユニットのログに絞り、-fは新しいログを流し続けます。

停止と再起動の流れ

systemdのサービスが起動から停止までたどる流れの図。systemctl startで起動し、Type=execならプログラムを実行できた時点で稼働中になる。0以外の終了コードなどで異常終了すると、Restart=on-failureによりRestartSec=だけ待って再起動し、短い時間に起動が続くと起動を止めて失敗の状態になる。systemctl stopではSIGTERMを送り、TimeoutStopSec=を過ぎても残るプロセスにはSIGKILLを送る。

systemctl stopを受けると、systemdはまずKillSignal=のシグナル(既定はSIGTERM)を送り、TimeoutStopSec=の時間が過ぎても残っているプロセスにはSIGKILLを送ります。KillMode=の既定はcontrol-groupで、メインのプロセスだけでなく、そのサービスから生まれた残りのプロセスもまとめて止めます。*6 シグナルそのものは「シグナルとは」で説明しています。

異常終了したときの扱いはRestart=で決まります。on-failureでは、終了コード0や、SIGHUP・SIGINT・SIGTERM・SIGPIPEによる終了は正常と見なされ、再起動しません。0以外の終了コード、それ以外のシグナル、処理の時間切れのときに再起動し、systemctl stopで止めた場合は再起動しません。*3

再起動には回数の上限もあります。StartLimitIntervalSec=の時間内にStartLimitBurst=を超えて起動されたユニットは、それ以上起動できなくなります。*4 上限に達すれば失敗の状態で止まり、RestartSec=が長く上限に届かなければ再起動をくり返し続けます。どちらの場合も、監視で拾う仕組みが要ります。

業務での使いどころ

常駐に向くのは、常に要求を待ち受ける処理です。社内向けのWebアプリケーションやAPI、キューを処理するワーカー、監視のエージェントなどが典型です。

決まった時刻にだけ動けばよい処理を、ループで常駐させる必要はありません。daemon(7)は、定期的な後片付けの仕事には.timerユニットによる起動が向くとしています。夜間のバッチなどの運用設計は「バッチ運用の勘所」で扱っています。

要求が来たときだけ起動したい処理には、systemdが待ち受けのソケットを先に作り、通信が届いた時点でデーモンを起動するソケット起動があります。再起動の間も要求はためられるので、DNSやsyslogのような状態を持たないプロトコルなら要求を一つも落とさずに再起動できるとされています。*1

つまずきやすい点

一つ目は、自分でデーモン化する古いプログラムをそのまま載せることです。この場合のType=forkingは勧められておらず、使うならPIDFile=の指定が求められます。前面で動かすオプションがあれば、それを使います。

二つ目は、daemon-reloadの忘れです。systemctlのreloadはサービス自身の設定(Apacheならhttpd.conf)を読み直させるもので、ユニットファイルを読み直すのはdaemon-reloadです。取り違えると、直した設定が効きません。

三つ目は、Type=simpleで起動の失敗が見えないことです。simpleはforkの直後に起動済みと見なすため、実行ファイルが無くてもsystemctl startは成功を返します。Type=execかType=notifyを選べば、失敗をその場で拾えます。

四つ目は、ログと作業ディレクトリです。journaldのStorage=がautoなら、/var/log/journalが無いとログはメモリー上にしか残りません。*8 保存期間の決め方は「ログはいつまで残す?」が参考になります。また、WorkingDirectory=を書かないと作業ディレクトリはルートになり、相対パスでファイルを開くプログラムは想定と違う場所を探して失敗します。

外部に委託するときに確認しておきたい点

開発を外部に頼むときは、プログラム本体だけでなくユニットファイルも納品物に含めてもらい、実行ユーザー、Type=、再起動の条件、停止を待つ時間をなぜその値にしたのか説明できるかを見ます。

次に、止め方です。SIGTERMで処理中の仕事をどう終えるか、異常のときに0以外の終了コードを返すかを仕様に書いてもらいます。ここがあいまいだと、再起動の設定が意図どおりに働きません。

最後にログと試験です。ログをどこに何日残すか、失敗の状態を誰が知るかを決め、強制終了からの再起動、サーバー再起動後の自動起動、停止時の後始末の3つを、本番と同じユニットファイルで試す計画があるかを確かめます。

まとめ:Linuxデーモンで確かめておきたい3つの点

Linuxデーモンを業務で常駐させるうえで、確かめておきたい点は3つです。第一に、プログラムに自分でforkさせず、systemdのサービスユニットに起動と監視を任せること。第二に、Type=、SIGTERMでの後始末、Restart=と回数の上限を意図を持って決めること。第三に、ログの保存先、失敗の状態を拾う監視、強制終了と再起動を含む試験までを用意することです。既存の常駐プログラムの移行や運用設計に迷いがあれば、外部の手を借りるのも一つの選択肢です。

LASSICに相談するメリット

LASSICは、元請(プライムベンダー)としてシステムの開発と保守・運用を受託しています。常駐プログラムをLinuxで動かす場合は、systemdのサービスユニットとタイマー、journaldによるログの集約、Ansibleによるユニットファイルの配布、PrometheusとGrafanaによる監視を、要件に合わせて組み立てます。設計では、Type=の選び方、SIGTERMでの後始末と停止を待つ時間、Restart=と回数の上限、実行ユーザーと権限の絞り方を発注者と決めます。検証と運用では、CI/CDでsystemd-analyze verifyによるユニットファイルの検査と自動テストを回し、失敗の状態を監視で拾って通知する仕組みまで整えます。

よくある質問

nohupで起動しておくのとは何が違いますか

nohupは、端末の切断を知らせるシグナルを無視してコマンドを動かすものです。ログアウトしても止まらなくはなりますが、落ちたときの再起動や、サーバー起動時の自動起動、ログの集約はしてくれません。業務で動かし続けるプログラムは、systemdのサービスとして登録するのが確実です。

デーモンが動いているかを、スクリプトで確かめるにはどうしますか

systemctl is-activeを使います。指定したユニットが動いていれば終了コード0を、そうでなければ0以外を返すので、シェルスクリプトや監視の仕組みから判定に使えます。自動起動の登録を確かめるなら、同じくis-enabledが使えます。

Type=notifyは、どのようなときに使いますか

起動してから実際に要求を受けられるまでに時間がかかるデーモンに使います。デーモンが準備を終えた時点でsd_notify()などによりREADY=1を送り、systemdはそれを受けてから後に続くユニットを起動します。データベースへの接続や設定の読み込みを終えてから起動済みと見なしたいときに向きます。

ユニットファイルは、どこに置けばよいですか

管理者が作るユニットは/etc/systemd/systemに置きます。パッケージが入れたユニットの設定を一部だけ変えたいときは、元のファイルを書き換えず、foo.service.d/のような「ドロップイン」のディレクトリに.confのファイルを置くと、元のファイルの後に読み込まれます。

Linuxの常駐プログラムの開発と運用のご相談

元請(プライムベンダー)として、常駐プログラムの開発からsystemdでの常駐化、監視とログの設計、保守・運用までご提案します。

Remoguとリラシクなら、Linuxサーバーの構築や運用に加わるITエンジニアも探せます。

Remoguは、リモート前提で全国から即戦力のITプロ人材を調達するサービスです。リラシクは、扱う求人がすべてリモートワークのITエンジニア専門転職エージェントです。どちらもLASSICが運営しています。

無料相談はこちら

出典

  1. *1 参考:Linux man-pages「daemon(7) — Writing and packaging system daemons」(https://man7.org/linux/man-pages/man7/daemon.7.html)。出典:DESCRIPTION(デーモンの定義、SysV Daemonsの15の手順、New-Style Daemonsの推奨事項)、ACTIVATION(ソケット・パス・タイマーによる起動)、INTEGRATION WITH SYSTEMDを参照(2026年10月確認)
  2. *2 参考:Linux man-pages「daemon(3) — run in the background」(https://man7.org/linux/man-pages/man3/daemon.3.html)。出典:DESCRIPTIONとBUGS(glibcの実装が二重のforkを行わずセッションリーダーになる点)を参照(2026年10月確認)
  3. *3 参考:systemd「systemd.service(5) — Service unit configuration」(man7.org掲載版)(https://man7.org/linux/man-pages/man5/systemd.service.5.html)。出典:DESCRIPTION、Type=(simple・exec・forking・oneshot・notify・notify-reload)、ExecReload=、TimeoutStopSec=、Restart=と表1(終了の原因とRestart=の効果)を参照(2026年10月確認)
  4. *4 参考:systemd「systemd.unit(5) — Unit configuration」(man7.org掲載版)(https://man7.org/linux/man-pages/man5/systemd.unit.5.html)。出典:ユニットの読み込み先の表(/etc/systemd/system、/usr/lib/systemd/system)、StartLimitIntervalSec=とStartLimitBurst=を参照(2026年10月確認)
  5. *5 参考:systemd「systemd.exec(5) — Execution environment configuration」(man7.org掲載版)(https://man7.org/linux/man-pages/man5/systemd.exec.5.html)。出典:WorkingDirectory=、User=、NoNewPrivileges=、ProtectSystem=、StandardOutput=を参照(2026年10月確認)
  6. *6 参考:systemd「systemd.kill(5) — Process killing procedure configuration」(man7.org掲載版)(https://man7.org/linux/man-pages/man5/systemd.kill.5.html)。出典:KillMode=(既定のcontrol-group)、KillSignal=(既定のSIGTERM)とSIGKILLへの切り替えを参照(2026年10月確認)
  7. *7 参考:systemd「systemctl(1) — Control the systemd system and service manager」(man7.org掲載版)(https://man7.org/linux/man-pages/man1/systemctl.1.html)。出典:status、reload、enable、is-active、is-enabled、daemon-reload、–nowの説明を参照(2026年10月確認)
  8. *8 参考:systemd「journald.conf(5) — Journal service configuration files」(man7.org掲載版)(https://man7.org/linux/man-pages/man5/journald.conf.5.html)。出典:Storage=(volatile・persistent・auto・none と既定値)の説明を参照(2026年10月確認)
  9. *9 参考:Python Software Foundation「sys — System-specific parameters and functions」(https://docs.python.org/3/library/sys.html)。出典:sys.stdout のバッファリング(対話的でないときはブロック単位)と -u・PYTHONUNBUFFERED の説明を参照(2026年10月確認)




View