2011-12-05 220 views
8

對於一個網站,我需要能夠啓動和停止守護進程。我目前在做的是從PHP啓動一個守護進程

exec("sudo /etc/init.d/daemonToStart start"); 

守護進程已啓動,但Apache/PHP掛起。做一個ps aux透露sudo本身變成殭屍進程,有效地殺死所有進一步的進展。試圖從PHP啓動daeomon時,這是正常行爲嗎?

是的,Apache有權執行/etc/init.d/daemonToStart命令。我修改了/ etc/sudoers文件以允許它這樣做。不,我沒有讓Apache能夠執行任何類型的命令,只有有限的幾個讓網站能夠工作。

無論如何,回到我的問題,有沒有辦法允許PHP啓動守護進程的方式,沒有創建殭屍進程?我問這個,因爲當我做相反的事時,停止一個已經啓動的守護進程,工作得很好。

+0

不應該有一個'start'說法? – ZeissS

+0

沒錯,我忘了在這個問題上加上那個。在我的代碼中,我確實擁有它。但是,我會編輯完整性的問題。 – ThaMe90

回答

10

嘗試追加> /dev/null 2>&1 &到該命令。

所以這樣的:

exec("sudo /etc/init.d/daemonToStart > /dev/null 2>&1 &"); 

以防萬一你想知道那是什麼/爲什麼:

  • > /dev/null - stdout重定向到/ dev/null的(忽略它,換句話說)
  • 2>&1 - 將STDERR重定向到STDOUT(黑洞也是如此)
  • &分離進程並在後臺運行
+0

謝謝,那就是訣竅! – ThaMe90

+0

感謝您的進一步解釋,但由於輸出是黑色的,任何應該在守護進程啓動後執行的代碼也會被髮送。我必須檢查過程是否已經開始,但是這段代碼永遠不會被觸發...... – ThaMe90

+1

當你使用這種方法啓動一個進程時,它應該輸出已經創建的進程的PID。你可以拿這個,然後(例如)執行'ps | grep $ pidOfProcessYouJustStarted'以確保它正在運行。 – DaveRandom

0

我從來沒有試過從PHP啓動一個守護進程,但我嘗試運行其他shell命令,很麻煩。以下是我已經嘗試了幾件事情,在過去的:

  • 按DaveRandom的答案,追加/dev/null 2>&1 &到命令的末尾。這會將錯誤重定向到標準輸出。然後你可以使用這個輸出來調試。
  • 確保您的web服務器的用戶PATH包含守護程序腳本中的所有引用二進制文件。您可以通過撥打exec('echo $PATH; whoami;)來完成此操作。這會告訴你用戶正在運行PHP,它是當前的PATH變量。
2

我有同樣的問題。

我同意DaveRandom,你必須壓制每一個輸出(stdout和stderr)。但是不需要在結束'&'的另一個進程中啓動:exec()函數不能再檢查返回代碼,並且即使出現錯誤也會返回正常...

而且我更喜歡存儲輸出臨時文件,而不是「blackhole」。 工作的解決方案:

$temp = tempnam(sys_get_temp_dir(), 'php'); 
exec('sudo /etc/init.d/daemonToStart >'.$temp.' 2>&1'); 

只要閱讀文件內容後,並刪除臨時文件:

$output = explode("\n", file_get_contents($temp)); 
@unlink($temp);