Googleで検索 x2コードスニペットが表示されます。最初の結果は このコードレシピ になります。これには、その下にある有用な説明とともに、多くのドキュメントと説明があります。
ただし、 別のコードサンプル には、あまりドキュメントがありませんが、start、stop、restartなどのコマンドを渡すためのサンプルコードが含まれています。また、デーモンがすでに実行されているかどうかなどをチェックするのに便利なPIDファイルも作成します。
これらのサンプルは両方ともデーモンの作成方法を説明しています。考慮する必要があるその他のものはありますか?あるサンプルは他のサンプルよりも優れていますか、そしてそれはなぜですか?
現在の解決策
PEP 3143(標準デーモンプロセスライブラリ) の参照実装は python-daemon として利用可能になりました。
過去の回答
Sander Marechalの コードサンプル は、もともと2004年に投稿されたオリジナルよりも優れています。私はかつてPyroのデーモン化プログラムを提供しましたが、それをやり直さなければならない場合はおそらくSanderのコードを使用します。
行儀の良いデーモンプロセスになるときに気をつけるべき面倒なことはたくさんあります :
コアダンプを防止する(多くのデーモンはrootとして実行され、コアダンプには機密情報が含まれる可能性があります)
chroot
gaol内で正しく動作する
ユースケースに合わせて、UID、GID、作業ディレクトリ、umask、およびその他のプロセスパラメータを適切に設定します。
昇格されたsuid
、sgid
特権を放棄する
ユースケースに応じて除外して、開いているすべてのファイル記述子を閉じます。
init
、inetd
など、すでに切り離されているコンテキスト内で起動した場合は正しく動作します。
賢明なデーモンの振る舞いのためにシグナルハンドラを設定しますが、ユースケースによって決定された特定のハンドラも使用します
デーモンプロセスに制御端末がなくなったため、標準ストリームstdin
、stdout
、stderr
をリダイレクトします。
pIDファイルを協調的なアドバイザリロックとして扱う。これは それ自体でワームの全体的な可能性がある /多くの矛盾するが有効な振る舞いを伴う
プロセスが終了したときに適切なクリーンアップを許可する
標準的なUNIXの文献( UNIX環境での高度なプログラミング)で説明されているように、これらのいくつかは標準です。後期W. Richard Stevens、Addison-Wesley、1992)。ストリームリダイレクションや PIDファイル処理 などの他のものは、ほとんどのデーモンユーザが期待する従来の動作ですが、標準化されていません。
これらすべてはPEP 3143 「標準デーモンプロセスライブラリ」仕様でカバーされています。 python-daemon reference実装は、Python 2.7以降、およびPython 3.2以降で動作します。
これは私が新しいデーモンアプリケーションを開発するときに使う私の基本的な 'Howdy World' Pythonデーモンです。
#!/usr/bin/python
import time
from daemon import runner
class App():
def __init__(self):
self.stdin_path = '/dev/null'
self.stdout_path = '/dev/tty'
self.stderr_path = '/dev/tty'
self.pidfile_path = '/tmp/foo.pid'
self.pidfile_timeout = 5
def run(self):
while True:
print("Howdy! Gig'em! Whoop!")
time.sleep(10)
app = App()
daemon_runner = runner.DaemonRunner(app)
daemon_runner.do_action()
python-daemon
ライブラリが必要になるでしょう。あなたはそれをインストールすることができます:
pip install python-daemon
それから./howdy.py start
で始めて、そして./howdy.py stop
でそれを止めなさい。
箱から出してすぐにデーモンの背後にある多くの問題を解決する python-daemon パッケージに注意してください。
他の機能の中でも、(Debianパッケージの説明から):
別の方法 - 通常のデーモン化されていないPythonプログラムを作成してから、 supervisord を使用して外部的にデーモン化します。これは多くの頭痛の種を減らすことができ、そして* nixおよび言語移植可能です。
おそらく質問に対する直接的な答えではありませんが、systemdを使用してアプリケーションをデーモンとして実行することができます。これが一例です。
[Unit]
Description=Python daemon
After=syslog.target
After=network.target
[Service]
Type=simple
User=<run as user>
Group=<run as group group>
ExecStart=/usr/bin/python <python script home>/script.py
# Give the script some time to startup
TimeoutSec=300
[Install]
WantedBy=multi-user.target
多くの作業があなたのために行われ、そしてあなたのデーモンスクリプトがあなたのシステムの他の部分と同様に振る舞うので私はこの方法を好む。
- オービー
YapDi はHacker Newsに登場した比較的新しいpythonモジュールです。かなり便利に見えますが、Pythonスクリプトをスクリプト内からデーモンモードに変換するために使用できます。
python-daemonはpython 3.xをまだサポートしていないので、そしてメーリングリストで読むことができるものから、それは決してしないかもしれないので、私はPEP 3143の新しい実装を書きました: pep3143daemon
pep3143デーモンは少なくともpython 2.6、2.7および3.xをサポートするべきです。
PidFileクラスも含まれています。
ライブラリは標準ライブラリと6つのモジュールにのみ依存します。
これはpython-daemonに代わるドロップインとして使用できます。
これが ドキュメント です。
この関数はアプリケーションをデーモンに変換します。
import sys
import os
def daemonize():
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
except OSError as err:
sys.stderr.write('_Fork #1 failed: {0}\n'.format(err))
sys.exit(1)
# decouple from parent environment
os.chdir('/')
os.setsid()
os.umask(0)
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
except OSError as err:
sys.stderr.write('_Fork #2 failed: {0}\n'.format(err))
sys.exit(1)
# redirect standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
si = open(os.devnull, 'r')
so = open(os.devnull, 'w')
se = open(os.devnull, 'w')
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
@Dustinによって言及されたデーモンモジュールが私のために働かなかったことを恐れています。代わりに python-daemon をインストールして以下のコードを使いました。
# filename myDaemon.py
import sys
import daemon
sys.path.append('/home/ubuntu/samplemodule') # till __init__.py
from samplemodule import moduleclass
with daemon.DaemonContext():
moduleclass.do_running() # I have do_running() function and whatever I was doing in __main__() in module.py I copied in it.
走りやすい
> python myDaemon.py
完全を期して、samplemoduleディレクトリの内容はここにあります
>ls samplemodule
__init__.py __init__.pyc moduleclass.py
Moduleclass.pyの内容は次のようになります。
class moduleclass():
...
def do_running():
m = moduleclass()
# do whatever daemon is required to do.
Pythonでデーモン化するときに考えるべきもう1つのこと:
あなたがpython loggingを使っていて、デーモン化した後もそれを使い続けたいのなら、ハンドラ(特にファイルハンドラ)でclose()
を呼ぶようにしてください。
そうしなければ、ハンドラはまだファイルが開いていると考えることができ、メッセージは単に消えます。
これはあなたがデーモン化したときにすべての開いているファイルディスクリプタを無差別に閉じようとしていることを前提としています - 代わりにログファイル以外のすべてを閉じてみましょう.