2009-01-23 30 views
210

Searching on Google顯示x2代碼片段。第一個結果是this code recipe,它有很多文檔和解釋,以及下面的一些有用的討論。你如何在Python中創建一個守護進程?

但是,another code sample雖然沒有包含太多文檔,但包含用於傳遞諸如啓動,停止和重新啓動之類的命令的示例代碼。它還會創建一個PID文件,用於檢查守護進程是否已在運行等。

這些示例都解釋瞭如何創建守護進程。還有什麼需要考慮的嗎?一種樣品比另一種好,爲什麼?

+1

我總是發現系統守護進程的代碼不必要的。爲什麼不讓殼體做到這一點? – 2010-11-13 20:12:22

+14

因爲它不會執行setsid或setpgrp。 – bmargulies 2011-03-24 01:26:56

+4

使用http://supervisord.org/。這樣你就不需要fork()或重定向你stdin/stderr。只需編寫一個正常的程序。 – guettli 2013-10-01 09:02:22

回答

131

Sander Marechal的code sample優於最初於2004年發佈的原始版本。我曾經貢獻過Pyro的一個守護進程,但如果必須完成它,可能會使用Sander的代碼。

+70

編輯:因爲我最初發布這個答覆,PEP 3143的參考實現在現已:http://pypi.python.org/pypi/python-daemon/ – 2011-01-28 18:45:05

+3

蟒蛇守護封裝使這項任務更容易... – Pankaj 2011-04-17 09:16:03

+0

@JeffBauer原始鏈接已經死亡,我記得它很有用,你不會知道一個活的鏈接,你會嗎? – CrazyCasta 2014-02-25 19:43:24

-24

80%的時間,當人們說「守護進程」時,他們只想要一臺服務器。由於這個問題在這方面完全不清楚,很難說可能的答案領域是什麼。由於服務器足夠,從那裏開始。如果實際需要一個實際的「守護進程」(這很少見),請閱讀nohup作爲守護進程服務器的一種方式。

在真正需要實際守護進程的時候,只需編寫一個簡單的服務器即可。

另請參閱WSGI reference實現。

也看看Simple HTTP Server

「還有什麼需要考慮的事情嗎?」是的。大約一百萬件事。什麼協議?有多少請求?每個請求需要多長時間?他們多久會抵達?你會使用專門的過程嗎?主題?子進程?編寫一個守護進程是一項很重要的工作。

-2

使用Python創建守護程序的最簡單方法是使用Twisted事件驅動框架。它爲你處理守護進程所需的所有東西。它使用Reactor Pattern來處理併發請求。

146

很多繁瑣的事情照顧成爲well-behaved daemon process時:

  • 防止核心轉儲(許多守護進程以root身份運行,並且核心轉儲可能包含敏感信息)

  • 內部正確運作chroot gaol

  • 設置UID,GID,工作目錄,umask和其他過程參數LY的使用情況

  • 才肯罷休升高suidsgid特權

  • 關閉所有打開的文件描述符,以根據不同的使用情況

  • 正確的行爲,如果啓動一個已經脫離上下文中排除,如initinetd等。

  • 設置爲明智的守護程序行爲的信號處理程序,也與通過用例

  • 確定的特定的處理程序重定向標準流stdinstdoutstderr因爲守護進程不再有控制終端

  • 處理PID文件作爲合作諮詢鎖,這是蠕蟲的一個整體,本身有許多相互矛盾的,但有效的方式運行

  • 允許時則終止該處理

  • 實際上成爲守護進程適當的清除,而不會導致殭屍

一些是標準,在典型的Unix文獻(在所描述的高級編程UNIX環境,W. Richard Stevens,Addison-Wesley,1992)。其他,如流重定向和PID file handling常規行爲大多數守護進程用戶會期望但不那麼標準化。

所有這些都由PEP 3143「標準守護進程庫」規範覆蓋。 python-daemon參考實現適用於Python 2.7或更高版本以及Python 3.2或更高版本。

43

請注意python-daemon包,它解決了開箱即用的守護進程背後的許多問題。

在其它特性中它能夠(從Debian軟件包說明):

  • 拆離的過程到它自己的進程組。
  • 設置適合在chroot中運行的進程環境。
  • 放棄suid和sgid權限。
  • 關閉所有打開的文件描述符。
  • 更改工作目錄,uid,gid和umask。
  • 設置適當的信號處理程序。
  • 打開stdin,stdout和stderr的新文件描述符。
  • 管理指定的PID鎖定文件。
  • 爲退出處理註冊清理函數。
6

YapDi是在Hacker News中彈出的一個相對較新的python模塊。看起來非常有用,可用於從腳本內部將python腳本轉換爲守護進程模式。

86

這是我開始使用的基本'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停止。

23

另一種方法 - 創建一個正常的非守護程序的Python程序,然後使用supervisord從外部守護進程。這可以節省許多麻煩,並且是* nix和便攜式語言。

2

一個更件事想在python daemonizing時:

如果您正在使用python 記錄,並要繼續daemonizing後使用它,請確保調用close()的處理程序(特別是文件處理程序)。

如果你不這樣做,處理程序仍然可以認爲它已打開文件,並且你的消息將簡單消失 - 換句話說,確保記錄器知道它的文件已關閉!

這個假設當你不加區分地關閉所有打開的文件描述符時 - 而是可以嘗試關閉除日誌文件以外的所有文件(但通常關閉所有文件然後重新打開你想要的文件更簡單)。

5

由於蟒蛇守護還不支持Python的3.x和從什麼可以在郵件列表中被讀取,它可能永遠不會,我已經寫了PEP的3143一個新的實現:pep3143daemon

pep3143daemon應支持至少python 2.6,2.7和3.x

它還包含一個PidFile類。

該庫只依賴於標準庫和六個模塊。

它可以用作python守護進程的替代品。

這裏是documentation

10

可能不是問題的直接答案,但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

2

恐怕由@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. 
3

該函數將改變一個應用程序到守護程序:

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()) 
1

我修改桑德馬雷夏的代碼示例(由@JeffBauer在the accepted answer提到的)在幾行添加quit()方法在守護進程停止前執行。這有時非常有用。

Here it is.

注:我不使用「蟒蛇守護程序」模塊,因爲文檔仍下落不明(見還有許多其他的做題),是相當模糊(如何啓動/停止一個正確守護進程從這個模塊的命令行?)

-1

經過幾年和許多嘗試,現在我認識到有一個更好的方法比想要直接從Python啓動,停止,重新啓動守護進程:使用操作系統工具!

而不是做python myapp startpython myapp stop總之,我這樣做是爲了啓動應用程序:

screen -S myapp python myapp.py  
CTRL+A, D to detach 

screen -dmS myapp python myapp.pystart and detach it in one command

然後:

screen -r myapp 

再次附接至該端子。一旦進入終端,可以使用CTRL + C來停止它。