使用PHP指令碼來寫Daemon程式

2022-02-12 18:53:50 字數 4259 閱讀 2151

什麼是daemon程序

這又是乙個有趣的概念,daemon在英語中是"精靈"的意思,就像我們經常在迪斯尼動畫裡見到的那些,有些會飛,有些不會,經常圍著動畫片的主人公轉來轉去,囉裡囉唆地提一些忠告,時不時倒霉地撞在柱子上,有時候還會想出一些小小的花招,把主人公從敵人手中救出來,正因如此,daemon有時也被譯作"守護神"。所以,daemon程序在國內也有兩種譯法,有些人譯作"精靈程序",有些人譯作"守護程序",這兩種稱呼的出現頻率都很高。

與真正的daemon相似,daemon程序也習慣於把自己隱藏在人們的視線之外,默默為系統做出貢獻,有時人們也把它們稱作"後台服務程序"。daemon程序的壽命很長,一般來說,從它們一被執行開始,直到整個系統關閉,它們才會退出。幾乎所有的伺服器程式,包括我們熟知的apache和wu-ftp,都用daemon程序的形式實現。很多linux下常見的命令如inetd和ftpd,末尾的字母d就是指daemon。

為什麼一定要使用daemon程序呢?linux中每乙個系統與使用者進行交流的介面稱為終端(terminal),每乙個從此終端開始執行的程序都會依附於這個終端,這個終端就稱為這些程序的控制終端(controlling terminal),當控制終端被關閉時,相應的程序都會被自動關閉。關於這點,讀者可以用x-window中的xterm試驗一下,(每乙個xterm就是乙個開啟的終端,)我們可以通過鍵入命令啟動應用程式,比如:$netscape 然後我們關閉xterm視窗,剛剛啟動的netscape視窗也會隨之一同突然蒸發。但是daemon程序卻能夠突破這種限制,即使對應的終端關閉,它也能在系統中長久地存在下去,如果我們想讓某個程序長命百歲,不因為使用者或終端或其他的變化而受到影響,就必須把這個程序變成乙個daemon程序。

daemon程序的程式設計規則

如果想把自己的程序變成daemon程序,我們必須嚴格按照以下步驟進行:

1、呼叫fork產生乙個子程序,同時父程序退出。我們所有後續工作都在子程序中完成。這樣做我們可以:

1.1 如果我們是從命令列執行的該程式,這可以造成程式執行完畢的假象,shell會回去等待下一條命令;

1.2 剛剛通過fork產生的新程序一定不會是乙個程序組的組長,這為第2步的執行提供了前提保障。

這樣做還會出現一種很有趣的現象:由於父程序已經先於子程序退出,會造成子程序沒有父程序,變成乙個孤兒程序(orphan)。每當系統發現乙個孤兒程序,就會自動由1號程序收養它,這樣,原先的子程序就會變成1號程序的子程序。

2、呼叫setsid系統呼叫。這是整個過程中最重要的一步。setsid的介紹見附錄2,它的作用是建立乙個新的會話(session),並自任該會話的組長(session leader)。如果呼叫程序是乙個程序組的組長,呼叫就會失敗,但這已經在第1步得到了保證。呼叫setsid有3個作用:

2.1 讓程序擺脫原會話的控制;

2.2 讓程序擺脫原程序組的控制;

2.3 讓程序擺脫原控制終端的控制;

總之,就是讓呼叫程序完全獨立出來,脫離所有其他程序的控制。

3、把當前工作目錄切換到根目錄。

如果我們是在乙個臨時載入的檔案系統上執行這個程序的,比如:/mnt/floppy/,該程序的當前工作目錄就會是/mnt/floppy/。在整個程序執行期間該檔案系統都無法被卸下(umount),而無論我們是否在使用這個檔案系統,這會給我們帶來很多不便。解決的方法是使用chdir系統呼叫把當前工作目錄變為根目錄,應該不會有人想把根目錄卸下吧。

關於chdir的用法,參見附錄1。

當然,在這一步裡,如果有特殊的需要,我們也可以把當前工作目錄換成其他的路徑,比如/tmp。

4、將檔案許可權掩碼設為0。

這需要呼叫系統呼叫umask,參見附錄3。每個程序都會從父程序那裡繼承乙個檔案許可權掩碼,當建立新檔案時,這個掩碼被用於設定檔案的預設訪問許可權,遮蔽掉某些許可權,如一般使用者的寫許可權。當另乙個程序用exec呼叫我們編寫的daemon程式時,由於我們不知道那個程序的檔案許可權掩碼是什麼,這樣在我們建立新檔案時,就會帶來一些麻煩。所以,我們應該重新設定檔案許可權掩碼,我們可以設成任何我們想要的值,但一般情況下,大家都把它設為0,這樣,它就不會遮蔽使用者的任何操作。

如果你的應用程式根本就不涉及建立新檔案或是檔案訪問許可權的設定,你也完全可以把檔案許可權掩碼一腳踢開,跳過這一步。

5、關閉所有不需要的檔案。

同檔案許可權掩碼一樣,我們的新程序會從父程序那裡繼承一些已經開啟了的檔案。這些被開啟的檔案可能永遠不被我們的daemon程序讀或寫,但它們一樣消耗系統資源,而且可能導致所在的檔案系統無法卸下。需要指出的是,檔案描述符為0、1和2的三個檔案(檔案描述符的概念將在下一章介紹),也就是我們常說的輸入、輸出和報錯這三個檔案也需要被關閉。很可能不少讀者會對此感到奇怪,難道我們不需要輸入輸出嗎?但事實是,在上面的第2步後,我們的daemon程序已經與所屬的控制終端失去了聯絡,我們從終端輸入的字元不可能達到daemon程序,daemon程序用常規的方法(如printf)輸出的字元也不可能在我們的終端上顯示出來。所以這三個檔案已經失去了存在的價值,也應該被關閉。 

使用php編寫gearman的worker守護程序

在我之前的文章中,介紹過gearman的使用。在我的專案中,我使用了php來編寫一直執行的worker。如果按照gearman官方推薦的例子,只是簡單的乙個迴圈來等待任務,會有一些問題,包括:1、當**進行過修改之後,如何讓**的修改生效;2、重啟worker的時候,如何保證當前的任務處理完成才重啟。

針對這個問題,我考慮了以下的解決方法:

2、在worker中設定,單次任務迴圈完成後,就對worker進行重啟。這個方案的問題在於消耗比較大。

3、在worker中新增乙個退出函式,如果需要worker退出的時候,在client端傳送乙個優先順序比較高的退出呼叫。這個需要客戶端配合,在使用後台類任務時,不太適合。

4、在worker中檢查檔案是否發生變化,如果發生了變化,退出並重啟自身。

5、為worker編寫訊號控制,接受重啟指令,類似於 http restart graceful 指令。

最後,結合4和5兩種方法,可以實現這樣乙個daemon,如果配置檔案發生了變化,他就會自動重啟;如果接受到了使用者的 kill  -1 pid 訊號,也會重新啟動。

**如下:

<?php

declare( ticks = 1 );

//this case will check the config file regularly, if the config file changed, it will restart it self

// if you want to restart the daemon gracefully, give it a hup signal

// by shiqiangat 2011-12-04

$init_md5 = md5_file( 'config.php');

//register signal handler

pcntl_signal( sigalrm, "signal_handler", true );

pcntl_signal( sighup, 'signal_handler', true );

$job_flag = false;    //

job status flag, to justify if the job has been finished

$signal_flag = false;    //

signal status flag, to justify whether we received the kill -1 signal

while( 1 )

function signal_handler( $signal ) else

break;

case sigalrm:

print

date('y-m-d h:i:s', time() ) . " caught signal : sigalrm - no : $signal \n";

//pcntl_exec( '/bin/ls' );

pcntl_alarm( 5 );

break;

default:

break;}}

function autostart( $signal = false, $filename = 'config.php' )else

if( $pid > 0 )else}}

1、php-daemon

2、ibm developers 系統呼叫跟我學

3、如何用php編寫daemon process

4、function exit

5、phpdaemon

6、stoping gearman worker nicely

7、doing the worker elsewhere

使用PHP指令碼來寫Daemon程式

什麼是daemon程序 這又是乙個有趣的概念,daemon在英語中是 精靈 的意思,就像我們經常在迪斯尼動畫裡見到的那些,有些會飛,有些不會,經常圍著動畫片的主人公轉來轉去,囉裡囉唆地提一些忠告,時不時倒霉地撞在柱子上,有時候還會想出一些小小的花招,把主人公從敵人手中救出來,正因如此,daemon有...

hive 使用php指令碼來完成map reduce

hive sql有個比較強大的功能就是可以使用外界指令碼來完成map reduce。用法如下 transform using as using裡面可以使用php指令碼來處理,具體使用方法看下面這個例子。建乙個表 hive create table member id int,user name st...

如何利用APC緩衝PHP指令碼來提高伺服器效能

原貼 http www.phpchina.com html 05 n 2005.html 我來說兩句 3765條 學會怎樣利用apc緩衝php指令碼來提高伺服器效能。希 望您的web伺服器發揮最大的效能嗎?如果您正在使用php指令碼,您可以很輕鬆地利用php的apc模組實現這一點,它對php opc...