Python デーモンのパッケージ化のベスト プラクティス
-
09-09-2019 - |
質問
Python で作成したツールがあり、通常はデーモンとして実行する必要があります。このツールを配布用にパッケージ化する際のベスト プラクティスは何ですか?特に設定ファイルとデーモンの実行可能ファイル/スクリプトはどのように処理すべきですか?
関連して、特定のプラットフォームに応じてブート時に実行するデーモンをセットアップするための共通ツールはありますか (つまり 初期化 Linux 上のスクリプト、Windows 上のサービス、 起動 OS X 上)?
解決
あなたの質問の一部に答えると、Windows や Mac OS X はもちろん、Linux システム間でもデーモンのセットアップを移植可能に実行できるツールは私が知っている限りではありません。
ほとんどの Linux ディストリビューションは使用しているようです start-stop-daemon
init スクリプト内では、まだファイルシステムのレイアウトに小さな違いがあり、パッケージ化に大きな違いが存在します。autotools/configure を使用するか、プロジェクトがすべて Python である場合は distutils/easy_install を使用すると、さまざまな Linux/BSD ディストリビューション用のパッケージを簡単にビルドできるようになります。
Windows はまったく別のゲームなので、 マーク・ハモンドの勝利32 拡張機能とおそらく ティム・ゴールデンの WMI 拡張子。
Launchd については、「上記のどれも関係ない」ということ以外は知りません。
Python スクリプトのデーモン化に関するヒントについては、実際に現実世界 (たとえば Twisted 内) でデーモン化を実行している Python アプリに注目します。
他のヒント
私はinit.dのスクリプトを手伝っ見つかり最良のツールは、「スタート・ストップ・デーモン」です。それはデーモン、設定プロセスのユーザー/グループID、およびでもバックグラウンドあなたのプロセスを停止する方法を提供し、必要なときにそれらを作成し、任意のアプリケーション、モニタの実行/ PIDファイルを実行します。
たとえば、これはWSGIサーバを停止/起動することができますスクリプトです。
#! /bin/bash
case "$1" in
start)
echo "Starting server"
# Activate the virtual environment
. /home/ali/wer-gcms/g-env/bin/activate
# Run start-stop-daemon, the $DAEMON variable contains the path to the
# application to run
start-stop-daemon --start --pidfile $WSGI_PIDFILE \
--user www-data --group www-data \
--chuid www-data \
--exec "$DAEMON"
;;
stop)
echo "Stopping WSGI Application"
# Start-stop daemon can also stop the application by sending sig 15
# (configurable) to the process id contained in the run/pid file
start-stop-daemon --stop --pidfile $WSGI_PIDFILE --verbose
;;
*)
# Refuse to do other stuff
echo "Usage: /etc/init.d/wsgi-application.sh {start|stop}"
exit 1
;;
esac
exit 0
また、そこに私はいつも推薦するvirtualenvの、とそれを使用する方法の例を見ることができます。
インターネット上には、純粋な Python (bash スクリプトなし) でデーモンを作成することを提案するスニペットが多数あります。
http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/きれいに見えます...
自分で書きたい場合は、
原理は bash デーモン機能と同じです。
基本的に:
開始時:
- 別のプロセスにフォークする
- logfileを開いて、stdoutとstderrをリダイレクトします
- pid をどこかに保存します。
停止中:
- pidfile に保存されている pid を使用して SIGTERM をプロセスに送信します。
- signal.signal(signal.SIGTERM, sigtermhandler) で、停止中の プロシージャを SIGTERM シグナルに渡します。
ただし、これを行う広く使用されているパッケージを私は知りません。
ベン・フィニーのデーモンモジュールを確認してください。彼は、Pythonの3.XをターゲットPEPを書き始めています:
http://www.python.org/dev/peps/pep-3143 / の
しかし、実装は、ここですでに提供されています:
あなたが求めているもののためではない特効薬はなく、 supervisord にチェックしてください。これは、プロセスを管理するすべての楽しみのビットを処理します。私は、大規模な生産環境に多額のそれを使用します。また、それはPythonで書かれています!
私はそれをダウンロードした私は覚えていないことができます...しかし、これは私が見つけた最高のdaemonizingスクリプトです。これは、(MacとLinux上で。)美しく動作します(daemonize.pyとして保存)
import sys, os
def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
# Perform first fork.
try:
pid = os.fork( )
if pid > 0:
sys.exit(0) # Exit first parent.
except OSError, e:
sys.stderr.write("fork #1 failed: (%d) %sn" % (e.errno, e.strerror))
sys.exit(1)
# Decouple from parent environment.
os.chdir("/")
os.umask(0)
os.setsid( )
# Perform second fork.
try:
pid = os.fork( )
if pid > 0:
sys.exit(0) # Exit second parent.
except OSError, e:
sys.stderr.write("fork #2 failed: (%d) %sn" % (e.errno, e.strerror))
sys.exit(1)
# The process is now daemonized, redirect standard file descriptors.
for f in sys.stdout, sys.stderr: f.flush( )
si = file(stdin, 'r')
so = file(stdout, 'a+')
se = file(stderr, 'a+', 0)
os.dup2(si.fileno( ), sys.stdin.fileno( ))
os.dup2(so.fileno( ), sys.stdout.fileno( ))
os.dup2(se.fileno( ), sys.stderr.fileno( ))
あなたのスクリプトでは、あなたは、単に希望ます:
from daemonize import daemonize
daemonize()
そして、あなたはまた、標準入出力をリダイレクトする場所を指定することができERR、等...
Linuxシステムでは、システムのパッケージマネージャ(PortageのGentooのため、Ubuntuの/ Debianのための適性、yumはFedoraのため、など)は、通常、右の場所でinitスクリプトを配置するなどのプログラムをインストールするの面倒を見ます。あなたがLinux用のプログラムを配布したい場合は、さまざまなディストリビューションのパッケージ管理のための適切な形式にそれを束ねに見たいと思うかもしれません。
このアドバイスは(WindowsおよびMacは、私は思う)パッケージマネージャを持たないシステム上で明らかに無関係です。
これ ブログの記事 Python プログラムをデーモンとして実行するには、実際には 2 つの一般的な方法があることが明らかになりました (既存の回答からはそれほど明確に理解できませんでした)。
サーバーのようなデーモンアプリケーションを書くには、2つのアプローチがあります Pythonで。
- 1つ目は、 sartingのすべてのタスクを処理し、 Pythonコード自体のデーモンの停止. 。これを行う最も簡単な方法は、 を
python-daemon
最終的にその道を歩むかもしれないパッケージ を Python ディストリビューションに
ポールジャポンの答え これはこの 1 番目のアプローチの例ですが、 python-daemon
パッケージですが、カスタムだが非常にクリーンな Python スクリプトにリンクしています。
- もう 1 つのアプローチは、 ツールの使用 オペレーティング・システムによって供給される. 。Debainの場合、これは init スクリプトを書く
start-stop-daemon
プログラム。
アリ・アフシャールの答え は、2 番目のアプローチのシェル スクリプトの例です。 start-stop-daemon
.
私が引用したブログ エントリには、シェル スクリプトの例と、システム起動時のデーモンの起動や、何らかの理由で停止した場合のデーモンの自動的な再起動などに関する追加の詳細が記載されています。
間違ったなら、私を修正し、私は質問がデーモンを展開する方法であると考えています。ピップ経由でインストールするアプリケーションを設定し、entry_point cli(daemon())
します。そして、単に$app_name &
を実行するinitスクリプトを作成します。
"は、一般的にデーモンとして実行すべきですか?"
はありません - 表面に - 多くの意味を作ります。 「一般」賢明ではありません。それはデーモンかのどちらかです。あなたの質問を更新したい場合があります。
は、デーモンの例については、Apacheのhttpdのまたは全てのデータベースサーバー(彼らはデーモンをしている)か、SMTPDのメールデーモンなどのデーモンをよく読んでます。
または、おそらく、FTPデーモンのような単純なもの、SSHデーモン、Telnetデーモンをよく読んでます。
Linuxの世界では、アプリケーションのインストールディレクトリに、いくつかの作業ディレクトリに加え、設定ファイルのディレクトリを持っています。
私たちは(それはPythonのですが、私たちはPythonの/opt/ourapp
にはインストールしない)アプリケーションのためのlib/site-packages
を使用する
私たちは、作業ファイルと私たちの設定ファイルを/var/ourapp
を使用しています。
私たちは、設定ファイルを/etc/ourapp
を使用することができます - それは一致するであろう - 。しかし、我々はしないでください。
私たちはそうではない - まだ - スタートアップのためのinit.d
スクリプトを使用しています。しかし、それは最後の部分、自動化されたスタートアップです。今のところ、我々は、SYS管理者はデーモンを起動しています。
これは http://www.pathname.com/fhs/と http://tldp.org/LDP/ Linuxのファイルシステム--階層/ HTML / Linuxのファイルシステム--Hierarchy.htmlするます。