Searching on Google顯示x2代碼片段。第一個結果是this code recipe,它有很多文檔和解釋,以及下面的一些有用的討論。你如何在Python中創建一個守護進程?
但是,another code sample雖然沒有包含太多文檔,但包含用於傳遞諸如啓動,停止和重新啓動之類的命令的示例代碼。它還會創建一個PID文件,用於檢查守護進程是否已在運行等。
這些示例都解釋瞭如何創建守護進程。還有什麼需要考慮的嗎?一種樣品比另一種好,爲什麼?
Searching on Google顯示x2代碼片段。第一個結果是this code recipe,它有很多文檔和解釋,以及下面的一些有用的討論。你如何在Python中創建一個守護進程?
但是,another code sample雖然沒有包含太多文檔,但包含用於傳遞諸如啓動,停止和重新啓動之類的命令的示例代碼。它還會創建一個PID文件,用於檢查守護進程是否已在運行等。
這些示例都解釋瞭如何創建守護進程。還有什麼需要考慮的嗎?一種樣品比另一種好,爲什麼?
Sander Marechal的code sample優於最初於2004年發佈的原始版本。我曾經貢獻過Pyro的一個守護進程,但如果必須完成它,可能會使用Sander的代碼。
編輯:因爲我最初發布這個答覆,PEP 3143的參考實現在現已:http://pypi.python.org/pypi/python-daemon/ – 2011-01-28 18:45:05
蟒蛇守護封裝使這項任務更容易... – Pankaj 2011-04-17 09:16:03
@JeffBauer原始鏈接已經死亡,我記得它很有用,你不會知道一個活的鏈接,你會嗎? – CrazyCasta 2014-02-25 19:43:24
80%的時間,當人們說「守護進程」時,他們只想要一臺服務器。由於這個問題在這方面完全不清楚,很難說可能的答案領域是什麼。由於服務器足夠,從那裏開始。如果實際需要一個實際的「守護進程」(這很少見),請閱讀nohup
作爲守護進程服務器的一種方式。
在真正需要實際守護進程的時候,只需編寫一個簡單的服務器即可。
另請參閱WSGI reference實現。
「還有什麼需要考慮的事情嗎?」是的。大約一百萬件事。什麼協議?有多少請求?每個請求需要多長時間?他們多久會抵達?你會使用專門的過程嗎?主題?子進程?編寫一個守護進程是一項很重要的工作。
使用Python創建守護程序的最簡單方法是使用Twisted事件驅動框架。它爲你處理守護進程所需的所有東西。它使用Reactor Pattern來處理併發請求。
有很多繁瑣的事情照顧成爲well-behaved daemon process時:
防止核心轉儲(許多守護進程以root身份運行,並且核心轉儲可能包含敏感信息)
內部正確運作chroot
gaol
設置UID,GID,工作目錄,umask和其他過程參數LY的使用情況
才肯罷休升高suid
,sgid
特權
關閉所有打開的文件描述符,以根據不同的使用情況
正確的行爲,如果啓動一個已經脫離上下文中排除,如init
,inetd
等。
設置爲明智的守護程序行爲的信號處理程序,也與通過用例
確定的特定的處理程序重定向標準流stdin
,stdout
,stderr
因爲守護進程不再有控制終端
處理PID文件作爲合作諮詢鎖,這是蠕蟲的一個整體,本身有許多相互矛盾的,但有效的方式運行
允許時則終止該處理
實際上成爲守護進程適當的清除,而不會導致殭屍
一些是標準,在典型的Unix文獻(在所描述的高級編程UNIX環境,W. Richard Stevens,Addison-Wesley,1992)。其他,如流重定向和PID file handling,常規行爲大多數守護進程用戶會期望但不那麼標準化。
所有這些都由PEP 3143「標準守護進程庫」規範覆蓋。 python-daemon參考實現適用於Python 2.7或更高版本以及Python 3.2或更高版本。
請注意python-daemon包,它解決了開箱即用的守護進程背後的許多問題。
在其它特性中它能夠(從Debian軟件包說明):
YapDi是在Hacker News中彈出的一個相對較新的python模塊。看起來非常有用,可用於從腳本內部將python腳本轉換爲守護進程模式。
這是我開始使用的基本'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程序,然後使用supervisord從外部守護進程。這可以節省許多麻煩,並且是* nix和便攜式語言。
一個更件事想在python daemonizing時:
如果您正在使用python 記錄,並要繼續daemonizing後使用它,請確保調用close()
的處理程序(特別是文件處理程序)。
如果你不這樣做,處理程序仍然可以認爲它已打開文件,並且你的消息將簡單消失 - 換句話說,確保記錄器知道它的文件已關閉!
這個假設當你不加區分地關閉所有打開的文件描述符時 - 而是可以嘗試關閉除日誌文件以外的所有文件(但通常關閉所有文件然後重新打開你想要的文件更簡單)。
由於蟒蛇守護還不支持Python的3.x和從什麼可以在郵件列表中被讀取,它可能永遠不會,我已經寫了PEP的3143一個新的實現:pep3143daemon
pep3143daemon應支持至少python 2.6,2.7和3.x
它還包含一個PidFile類。
該庫只依賴於標準庫和六個模塊。
它可以用作python守護進程的替代品。
這裏是documentation。
可能不是問題的直接答案,但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
我喜歡這種方法,因爲很多工作都是爲你做的,那麼你的守護進程的腳本行爲類似於您的系統的其餘部分。
-Orby
恐怕由@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的內容。吡啶可以是
class moduleclass():
...
def do_running():
m = moduleclass()
# do whatever daemon is required to do.
該函數將改變一個應用程序到守護程序:
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())
我修改桑德馬雷夏的代碼示例(由@JeffBauer在the accepted answer提到的)在幾行添加quit()
方法在守護進程停止前執行。這有時非常有用。
注:我不使用「蟒蛇守護程序」模塊,因爲文檔仍下落不明(見還有許多其他的做題),是相當模糊(如何啓動/停止一個正確守護進程從這個模塊的命令行?)
經過幾年和許多嘗試,現在我認識到有一個更好的方法比想要直接從Python啓動,停止,重新啓動守護進程:使用操作系統工具!
而不是做python myapp start
和python myapp stop
總之,我這樣做是爲了啓動應用程序:
screen -S myapp python myapp.py
CTRL+A, D to detach
或screen -dmS myapp python myapp.py
到start and detach it in one command。
然後:
screen -r myapp
再次附接至該端子。一旦進入終端,可以使用CTRL + C來停止它。
我總是發現系統守護進程的代碼不必要的。爲什麼不讓殼體做到這一點? – 2010-11-13 20:12:22
因爲它不會執行setsid或setpgrp。 – bmargulies 2011-03-24 01:26:56
使用http://supervisord.org/。這樣你就不需要fork()或重定向你stdin/stderr。只需編寫一個正常的程序。 – guettli 2013-10-01 09:02:22