現在、systemdデーモンを開発しています。私が直面している問題は、フォークが検出されないため、起動後1分30秒後にデーモンが終了することです。
私はこのint daemon(int nochdir, int noclose)
関数を使ってプロセスをデーモン化します。
int main()
{
openlog("shutdownd", LOG_PID, LOG_DAEMON);
if(daemon(0, 0) != 0)
{
syslog(LOG_ERR, "Error daemonizing process : %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
syslog(LOG_NOTICE, "Daemon started !\n");
pthread_create(&threads[0], NULL, &alimThread, NULL);
pthread_create(&threads[1], NULL, &extinctThread, NULL);
pthread_create(&threads[2], NULL, &blinkThread, NULL);
while(1)
{
}
syslog(LOG_NOTICE, "Daemon stopped !\n");
exit(EXIT_SUCCESS);
}
サービスファイルです/etc/systemd/system/shutdownd.service
[Unit]
Description=Shutdown Daemon
After=syslog.target
[Service]
Type=forking
PIDFile=/var/run/shutdownd.pid
ExecStartPre=/bin/rm -f /var/run/shutdownd.pid
ExecStartPre=/usr/bin/shutdownd-exportGpio.sh
ExecStart=/usr/bin/shutdownd
Restart=on-abort
[Install]
WantedBy=multi-user.target
デーモン機能はプロセスを分岐して端末から切り離す必要があり、ファイル記述子を閉じて作業ディレクトリを/に変更します。
ただし、systemdは1分30秒後に実行中のデーモンを終了するため、フォークを検出できないようです。
Sep 8 13:52:50 raspberrypi systemd[1]: shutdownd.service: PID file /var/run/shutdownd.pid not readable (yet?) after start: No such file or directory
Sep 8 13:52:50 raspberrypi shutdownd[293]: Daemon started !
Sep 8 13:52:50 raspberrypi shutdownd[293]: [Extinct] Value changed to 0
Sep 8 13:52:50 raspberrypi shutdownd[293]: OFF
Sep 8 13:52:50 raspberrypi shutdownd[293]: [Alim] Value changed to 0
Sep 8 13:52:50 raspberrypi shutdownd[293]: OFF
Sep 8 13:53:46 raspberrypi shutdownd[293]: [Alim] Value changed to 1
Sep 8 13:53:46 raspberrypi shutdownd[293]: Toogle : ON
Sep 8 13:53:48 raspberrypi shutdownd[293]: Toogle : OFF
[...]
Sep 8 13:54:16 raspberrypi shutdownd[293]: [Extinct] Value changed to 1
Sep 8 13:54:16 raspberrypi shutdownd[293]: ON
Sep 8 13:54:20 raspberrypi systemd[1]: shutdownd.service: Start operation timed out. Terminating.
Sep 8 13:54:20 raspberrypi systemd[1]: shutdownd.service: Unit entered failed state.
Sep 8 13:54:20 raspberrypi systemd[1]: shutdownd.service: Failed with result 'timeout'.
systemdがフォークを検出できない理由を知っている人はいますか?
fork()
私のコードを明示的に呼び出す必要がありますか?
この場合、デーモン化関数を直接作成する必要がありますが、これは難しくありませんが、この目的のためにac関数がすでに存在するため、完全に役に立たず重複します。
答え1
しないでください。
絶対にしないでください。どちらにしても、ライブラリ機能を通じても、自分だけのコードをローリングしても構いません。すべてのサービス管理システムに適しています。これは1990年代から誤った認識でした。
あなたのデーモンはすでにサービスコンテキストで実行され、サービス管理者はこの方法で呼び出します。あなたのプログラムは何もしなかったこれに関して。このようにしてプログラムの作成を完全に中止してください。
forking
そして準備プロトコルを使用しないでください。あなたのプログラムはマルチスレッドであり、準備されたforking
プロトコルを追加しようとすると、ほとんど間違いなく正しく実行されません。プロトコルを正しく取得することはフォークを意味するからです。後ろにすべてのスレッドの開始を含むすべての初期化が完了しました。ほとんどなし実際にforking
現場で使用するための準備プロトコル。別のプロトコルを使用してください。
追加読書
- https://unix.stackexchange.com/a/200365/5132
- https://unix.stackexchange.com/a/194653/5132
- https://unix.stackexchange.com/a/211126/5132
- https://unix.stackexchange.com/a/336067/5132
- https://unix.stackexchange.com/a/283739/5132
- ジョナサン・ドボイン・ポラード(2001)。 」「デーモンを背景に置く」ためだけにfork()を使用しないでください。」。 Unixデーモンを設計する際に避けるべき間違い。よく与えられる答えです。
- ジョナサンデボインポラード(2015)。実際にデーモンは必要ありません。本当。。体系化された恐怖の家。
- ジョナサンデボインポラード(2015)。Unixデーモンの準備プロトコルの問題。よく与えられる答えです。