2012-08-15 45 views
0

在Ubuntu 12.04與mod_wsgi的Python的3處理來自WSGI推出重啓後仍然運行/重裝服務器

我有一個正好與POPEN啓動外部程序的WSGI應用(實際上只是一個腳本)每個用戶會話(它實際上是一個小型的GTK程序,我正在試驗其HTML5後端)。

客戶端有一個Javascript循環,每隔幾秒向WSGI發送一個「保持活動」信號。如果WSGI在一段時間內沒有收到會話的任何信號,那麼它會殺死相關進程(並刪除會話)。

這很好,除了當我重新啓動/重新加載Apache或當我編輯WSGI腳本(該AFAIK自動重新加載應用程序)。 如果我這樣做,子流程不會被殺死。他們仍然運行(他們不是殭屍),我所能做的就是手動殺死他們(WSGI失去了前幾次會話,所以它不會殺死任何「舊」進程)。

所以我想執行下列操作之一:

  • 注意到服務器已停止/重啓/從WSGI側重裝,以便它可以清理它的子過程,而它知道他們的一種方式
  • 產生的進程應與mod_wsgi的死亡(目前似乎子過程重新連接到INIT時的mod_wsgi被殺害/再)

這裏是虛擬主機使用:

<VirtualHost *:80> 

WSGIDaemonProcess deckard_qh user=deckard group=deckard threads=5 
WSGIScriptAlias//home/deckard/wsgi/deckard_qh.wsgi 
Alias /ressources /home/deckard/ressources 

<Directory /home/deckard/wsgi> 
    WSGIProcessGroup deckard_qh 
    WSGIApplicationGroup %{GLOBAL} 
    Order deny,allow 
    Allow from all 
</Directory> 

<Directory /home/deckard/ressources> 
    Order deny,allow 
    Allow from all 
</Directory> 

我嘗試添加WSGIProcessGroup deckardWSGIApplicationGroup %{GLOBAL}(按this answer),但它並沒有改變任何東西。 我還在我的WSGI腳本的開頭添加了os.setsid(),但沒有結果。

+0

我覺得它可能與您在腳本中如何啓動它們更相關。你能舉一個例子說明你的wsgi腳本是如何啓動進程的? – jdi 2012-08-15 18:55:27

+0

他們是否正在運行,還是他們處於僵局(殭屍)狀態?如果直接父母死亡並且不能等待進程結束狀態並且他們稍後完成,那麼他們可以像殭屍一樣四處閒逛,直到整個Apache被關閉。除了在進程表中輸入外,它們在該狀態下不消耗資源。 – 2012-08-15 21:56:50

+0

我重申了這個問題。我希望現在更清楚。 @jdi這只是一個簡單的Popen。如果我在shell中的Python腳本中運行相關的代碼並殺死shell,那麼子進程也會被終止。我想mod_wsgi會對子進程做一些特殊的事情。 如果你仍然需要一些代碼,我會盡量縮短我的內容,然後再發布。 – 2012-08-15 22:07:22

回答

2

這只是一個草圖,但一個簡單的解決方案(孩子自己管理自己,我最喜歡的那股子解決方案!)將加入殺超時到POPEN過程,所以如果他們沒有在5分鐘內(或者你認爲是正確的)接受了「保持活力」,他們會保存狀態(如果適用)並終止?

我猜gtk_main_quit()是你用來終止事件循環,但在我離開基地的情況下,替換任何會終止你的子進程=)另外,我猜測gtk偶循環可能有它自己的定時器函數將會是一個與線程不同的實現,但我想測試我發佈的內容。

import datetime 
from threading import Timer 

# dummy timestamp for testing, gong should be the 
# timestamp of the last keepAlive signal 
gong = datetime.datetime(2012, 8, 16, 16, 3, 18, 341121) 

#seconds before kill check is performed 
idle = 5 

def bringOutYourDead(): 
    """If the last keep alive time stamp is more than 5 minutes ago, I am Audi 500.""" 
    stoneDeadIn = 5 
    if datetime.datetime.now() - datetime.timedelta(minutes=stoneDeadIn) >= gong: 
     # I used print for whatever command for testing 
     print('save_state_or_whatever()') 
     print('gtk_main_quit()') 
    else: 
     print("I'm not dead yet!'") 
    # recurse this as you see fit 

dung = Timer(idle, bringOutYourDead) 
dung.start() 
+0

事實上,「自殺」的孩子是一個簡單的解決方法。但是,這意味着您必須控制子代碼才能添加超時。所以這不是一個「通用」解決方案。我寧願如果這些孩子可能與他們的父母死在一起;)。但是,如果沒有人有更好的想法,我可能會使用類似的東西。謝謝。 – 2012-08-17 21:44:29

+0

當然我剛剛發現它,但[此線程](http://stackoverflow.com/a/11318000/602581)聲稱,如果你這樣做: 'p = subprocess.Popen([sys.executable,' /path/to/script.py'],stdout = subprocess.PIPE,stderr = subprocess.STDOUT)' 孩子們在apache的時候會死掉。 – 2012-08-18 01:57:31

+0

不幸的是,它在這裏不起作用。我想這隻適用於CGI。雖然很好找! – 2012-08-18 08:51:39

1

你試過sudo service apache2 graceful

USR1或優雅信號會導致父進程通知孩子在他們當前請求後退出(或者如果他們沒有提供任何服務,立即退出)。父母重新讀取其配置文件並重新打開其日誌文件。當每個孩子死亡時,父母將其替換爲新一代配置中的孩子,該孩子立即開始提供新的請求。

http://httpd.apache.org/docs/2.4/stopping.html#graceful

+0

這可能只適用於apache產生的進程,而不是從wsgi應用程序中產生的進程。 apache兒童進程是否立即終止,或者「優雅」不應該對這些孩子的孩子產生影響。 – jdi 2012-08-15 18:56:23

+0

和_restart_一樣。產生的進程在使用優雅之後仍然運行。 – 2012-08-15 21:37:34

相關問題