web-dev-qa-db-ja.com

シェルスクリプトをデーモンとして実行する「適切な」方法

daemontoolsのような外部ツールを使用せずに、起動時にデーモンとして実行したいShellスクリプトを書いています または daemonize


Linuxデーモン執筆HOWTO

Linux Daemon Writing HOWTO によると、properデーモンには次の特性があります。

  • fork親プロセスから
  • closesすべてのファイル記述子(つまり、stdinstdoutstderr
  • 書き込み用にlogsを開きます(設定されている場合)
  • 作業ディレクトリを永続的なものに変更します(通常は/
  • ファイルモードマスク(umask)をリセットします
  • 一意のセッションID(SID)を作成します

daemonizeはじめに

daemonizeはじめに はさらに進んで、一般的なデーモンも次のように述べています。

  • その制御端子(存在する場合)との関連付けを解除し、すべての端子信号を無視します
  • プロセスグループとの関連付けを解除します
  • SIGCLDを処理します

一般的なLinuxツールのみを使用して、shdash、またはbashスクリプトでこれらすべてを行うにはどうすればよいですか?

Debianが主な焦点ですが、スクリプトは追加のソフトウェアなしでできるだけ多くのディストリビューションで実行できるはずです。


注:StackExchangeネットワークには、Nohupまたはsetsidの使用を推奨する多くの回答があります、しかしこれらの方法はいずれも上記の要件のすべてに対処していません。


EDIT:daemon(7)マンページ もいくつかのポインタを提供しますが、古いスタイルのSysVデーモンと新しいスタイルの間にはいくつかの違いがあるようですsystemd ones。さまざまなディストリビューションとの互換性が重要であるため、答えが違いを明確にするようにしてください。


25
user339676

systemd を使用すると、単純なユニットを作成することにより、スクリプトをデーモンとして実行できるはずです。さまざまな options を追加できますが、これは簡単に取得できます。

スクリプトがあるとします/usr/bin/mydaemon

#!/bin/sh

while true; do
  date;
  sleep 60;
done

ユニットを作成します/etc/systemd/system/mydaemon.service

[Unit]
Description=My daemon

[Service]
ExecStart=/usr/bin/mydaemon
Restart=on-failure

[Install]
WantedBy=multi-user.target 

悪魔を開始するには、実行します

systemctl start mydaemon.service 

起動時に開始するには、それを有効にします

systemctl enable mydaemon.service

if今日のLinuxディストリビューションの大部分であるsystemdベースのシステムでは、これは実際には外部ツールではありません。ただし、どこでも機能しない場合があります。

21
johnramsden

私はおそらくここで何かを見逃している。なぜNohupが適切ではないのですか?もちろん、それだけでは十分ではありませんaloneですが、補足するのは簡単なようです。

#!/bin/bash

if [ "$1" = "DAEMON" ]; then
    # is this necessary? Add other signals at will (TTIN TTOU INT STOP TSTP)
    trap '' INT
    cd /tmp
    shift
    ### daemonized section ######
    for i in $( seq 1 10 ); do
        date
        sleep 5
    done
    #### end of daemonized section ####
    exit 0
fi

export PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin
umask 022
# You can add Nice and ionice before Nohup but they might not be installed
Nohup setsid $0 DAEMON $* 2>/var/log/mydaemon.err >/var/log/mydaemon.log &

私が見る限り:

  • 出力は適切にリダイレクトされます(必要に応じて/ dev/nullを使用します)
  • umaskは継承されます
  • stdinは親スクリプトの最後で終了します。
  • daemon.shスクリプトの親はinit(またはsystemd)に変更されます

当たり前のところを逃してしまった気がします。反対票を投じますが、それを教えてください:-)

7
LSerni

ほとんどのディストリビューションに含まれるLinux screenコマンドは、シェルスクリプトをデーモン化できます。よく使います。切り離された画面セッションを開始、一覧表示、終了する簡単な例を次に示します...

# screen -dmS Session_Name  bash -c "while true; do date; sleep 60; done"

# screen -ls
There are screens on:
        8534.Session_Name       (04/04/2018 08:46:27 PM)        (Detached)

# screen -S Session_Name -X quit
4
S.Haran