1. 程式人生 > >Linux守護程序設計規範及python實現

Linux守護程序設計規範及python實現

守護程序

守護程序是生存期長的一種程序。它們獨立於控制終端並且週期性的執行某種任務或等待處理某些發生的事件。他們常常在系統引導裝入時啟動,在系統關閉時終止。unix系統有很多守護程序,大多數伺服器都是用守護程序實現的。比如,網路服務inetd、Web服務http等。同時,守護程序完成許多系統任務。比如,作業規劃程序crond、列印程序lqd等。

這裡主要說明守護程序的程序結構,以及如何編寫守護程序程式。因為守護程序沒有控制終端,所以我們還要介紹在守護程序執行時錯誤輸出的方法。

守護程序及其特性

守護程序最重要的特性是後臺執行。在這一點上,DOS下的常駐記憶體程式TSR與之相似。

其次,守護程序必須與其執行前的環境隔離開來。這些環境包括未關閉的檔案描述符、控制終端、會話和程序組、工作目錄以及檔案建立掩碼等。這些環境通常是守護程序從執行它的父程序(特別是shell)中繼承下來的。

最後,守護程序的啟動方式有其特殊之處。它可以在系統啟動時從啟動指令碼/etc/rc.d中啟動,可以由inetd守護程序啟動,可以有作業規劃程序crond啟動,還可以由使用者終端(通常是shell)執行。

總之,除開這些特殊性以外,守護程序與普通程序基本上沒有什麼區別。因此,編寫守護程序實際上是把一個普通程序按照上述的守護程序的特性改造成為守護程序。如果大家對程序的認識比較深入,就對守護程序容易理解和程式設計了。

首先我們來察看一些常用的系統守護程序,看一下他們和幾個概念:程序組、控制終端和對話期有什麼聯絡。p s命令列印系統中各個程序的狀態。該命令有多個選擇項,有關細節請參考系統手冊。為了察看所需的資訊,執行:
ps –axj

PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 1 0 0 ? -1 S 0 0:04 init
1 2 1 1 ? -1 SW 0 0:00 [keventd]
1 3 1 1 ? -1 SW 0 0:00 [kapm-idled]
0 4 1 1 ? -1 SWN 0 0:00 [ksoftirqd_CPU0]
0 5 1 1 ? -1 SW 0 0:00 [kswapd]
0 6 1 1 ? -1 SW 0 0:00 [kreclaimd]
0 7 1 1 ? -1 SW 0 0:00 [bdflush]
0 8 1 1 ? -1 SW 0 0:00 [kupdated]
1 9 1 1 ? -1 SW< 0 0:00 [mdrecoveryd]
1 17 1 1 ? -1 SW 0 0:02 [kjournald]
1 92 1 1 ? -1 SW 0 0:00 [khubd]
1 573 573 573 ? -1 S 0 0:03 syslogd -r -x
1 578 578 578 ? -1 S 0 0:00 klogd -2
1 598 598 598 ? -1 S 32 0:00 portmap

程序號為1、2的這些程序非常特殊,存在於系統的整個生命期中。它們沒有父程序ID ,沒有組程序ID ,也沒有對話期ID 。syslogd 守護程序可用於任何為操作人員記錄系統訊息的程式中。可以在一臺實際的控制檯上列印這些訊息,也可將它們寫到一個檔案中。sendmail 是標準郵遞守護程序。update 程式定期將核心快取中的內容寫到硬碟上(通常是每隔30 秒)。為了做到這一點,該程式每隔30 秒呼叫sync(2 )函式一次。cron 守護程序在指定的日期和時間執行指定的命令。許多系統管理任務是由cron 定期地使相關程式執行而得以實現的。inetd程序監聽系統的網路介面,以輸入對各種網路伺服器的請求。最後一個守護程序,lpd 處理對系統提出的各個列印請求。

注意,所有守護程序都以超級使用者(使用者ID為0)的優先權執行。沒有一個守護程序具有控制終端,終端名稱設定為問號(?)、終端前臺程序組ID設定為-1。缺少控制終端是守護程序呼叫了setsid的結果。除update以外的所有守護程序都是程序組的首程序,對話期的首程序,而且是這些程序組和對話期中的唯一程序。最後,應當引起注意的是所有這些守護程序的父程序都是init程序。

在接觸實際程式設計前,我們來看看編寫守護程序要碰到的概念:程序組合會話期。

程序組

每個程序除了有一程序ID之外,還屬於一個程序組(在討論訊號時就會涉及程序組)程序組是一個或多個程序的集合。每個程序有一個唯一的程序組ID。程序組ID類似於程序ID——它是一個正整數,並可存放在pid_t資料型別中。

每個程序組有一個組長程序。組長程序的標識是,其程序組ID等於其程序ID,程序組組長可以建立一個程序組,建立該組中的程序,然後終止,只要在某個程序組中有一個程序存在,則該程序就存在,這與其組長程序是否終止無關。從程序組建立開始到其中最後一個程序離開為止的時間區間稱為程序組的生命期。某個程序組中的最後一個程序可以終止,也可以參加另一程序組。

前面已經提到程序呼叫setgid可以參加一個現存的組或者建立一個新程序組(setsid也可以建立一個新的程序組,後面將用到)

會話期

會話期(session)是一個或多個程序組的集合。其中,在一個會話期中有3個程序組,通常是有shell的管道線將幾個程序編成一組的。

下面說明有關會話期和程序組的一些特性:

一個會話期可以有一個單獨的控制終端(controlling terminal),這一般是我們在其上登入的終端裝置(終端登入)或偽終端裝置(網路登入),但這個控制終端並不是必需的。

建立與控制終端連線的會話期首程序,被稱之為控制程序(contronlling process)。以及一個會話期中的幾個程序組可被分為一個前臺程序組(foreground process group)以及一個或幾個後臺程序組(background process group)

如果一個會話期有一個控制終端,則它有一個前臺程序組,其他程序組為後臺程序組。無論何時鍵入中斷鍵(常常是delete或ctrl-c)或退出鍵(通常是ctrl-/),就會造成將中斷訊號或退出訊號送至前途程序組的所有程序。

守護程序的程式設計規則

在不同Unix環境下,守護程序的具體程式設計細節並不一致。但所幸的是,守護程序的程式設計原則其實都一樣,區別僅在於具體的實現細節不同,這個原則就是要滿足守護程序的特性。程式設計規則如下:

1、在後臺執行

為避免掛起控制終端,要將daemon放入後臺執行,其方法是,在程序中呼叫fork使父程序終止,讓daemon在子程序中後臺執行。具體就是呼叫f o r k ,然後使父程序e x i t 。這樣做實現了下面幾點:
第一,如果該精靈程序是由一條簡單s h e l l 命令起動的,那麼使父程序終止使得s h e l l 認為這條命令已經執行完成。
第二,子程序繼承了父程序的程序組I D ,但具有一個新的程序I D ,這就保證了子程序不是一個程序組的首程序。這對於下面就要做的s e t s i d 呼叫是必要的前提條件。

2、脫離控制終端,登入會話和程序組

登入會話可以包含多個程序組,這些程序組共享一個控制終端,這個控制終端通常是建立程序的登入終端、控制終端,登入會話和程序組通常是從父程序繼承下來的。我們的目的就是要擺脫它們,使之不受它們的影響。

其方法是在第一點的基礎上,呼叫setsid()使程序成為會話組長:

需要說明的是,當程序是會話組長時,setsid()呼叫會失敗,但第一點已經保證程序不是會話組長。setsid()呼叫成功後,程序成為新的會話組長和新的程序組長,並與原來的登入會話和程序組脫離,由於會話過程對控制終端的獨佔性,程序同時與控制終端脫離。
具體是操作就是:
(a )成為新對話期的首程序
(b )成為一個新程序組的首程序
(c )沒有控制終端。

3、禁止程序重新開啟控制終端

現在,程序已經成為無終端的會話組長,但它可以重新申請開啟一個控制終端。

可以通過使程序不再成為會話組長來禁止程序重新開啟控制終端:

4、關閉開啟的檔案描述符

程序從建立它的父程序那裡繼承了開啟的檔案描述符。如不關閉,將會浪費系統資源,造成程序所在地檔案系統無法卸下以及無法預料的錯誤。一般來說,必要的是關閉0、1、2三個檔案描述符,即標準輸入、標準輸出、標準錯誤。因為我們一般希望守護程序自己有一套資訊輸出、輸入的體系,而不是把所有的東西都發送到終端螢幕上。呼叫fclose();

5、改變當前工作目錄

將當前工作目錄更改為根目錄。從父程序繼承過來的當前工作目錄可能在一個裝配的檔案系統中。因為精靈程序通常在系統再引導之前是一直存在的,所以如果精靈程序的當前工作目錄在一個裝配檔案系統中,那麼該檔案系統就不能被拆卸。


另外,某些精靈程序可能會把當前工作目錄更改到某個指定位置,在此位置做它們的工作。例如,行式印表機假離線精靈程序常常將其工作目錄更改到它們的s p o o l 目錄上。
可以呼叫chdir(“目錄”);

6、重設檔案建立掩碼

將檔案方式建立遮蔽字設定為0 。由繼承得來的檔案方式建立遮蔽字可能會拒絕設定某些許可權。例如,若精靈程序要建立一個組可讀、寫的檔案,而繼承的檔案方式建立遮蔽字,遮蔽了這兩種許可權,則所要求的組可讀、寫就不能起作用。

7、處理SIGCHLD 訊號

處理SIGCHLD訊號並不是必需的。但對於某些程序,特別是伺服器程序往往在請求到來時生產子程序出來請求。如果父程序不等待子程序結束,子程序將成為殭屍程序,(zombie)而仍佔用系統資源。如果父程序等待子程序結束,將增加父程序的負擔,影響伺服器程序的併發效能。在系統V下可以簡單的將SIGCHLD訊號的操作設為SIG-IGN:


signal(SIGCHLD,SIG_IGN);

這樣,核心在子程序結束時不會產生殭屍程序,這一點與BSD4不同,在BSD4下必須顯示等 待子程序結束才能釋放殭屍程序。

守護程序例項

守護程序例項包括兩部分:主程式test.c和初始化程式init.c。主程式每隔一分鐘向/tmp
目錄中的日誌test.log 報告執行狀態。初始化程式中的init_daemon 函式負責生成守護程序

void make_daemon(void)
{
pid_t pid;
FILE * lockfd;
sigset_t sighup;
int i;

extern pid_t getsid(pid_t);
pid = fork();//第一個子程序生成
if (pid < 0) {
printinfo("fork error!",INFOERROR);
exit(FAILEXIT);
}else if (pid > 0) {
printinfo("fork 1 ok! ", INFOSCREEN);
exit(OKEXIT);//退出父程序,擺脫shell的控制
}
pid = getpid();//獲得子程序自身的id
lockfd = fopen(PIDFILE, "w");//以下是將pid寫入檔案
if (lockfd != NULL) {
fprintf(lockfd, "%d/n", pid);
fclose(lockfd);
}//寫入pid
if (getsid(0) != pid) {//建立新的會話期
if (setsid() < 0) {
printinfo("backupdaemon setsid error!",INFOERROR);
perror("setsid");
}
}
if(pid=fork()){//再次生成子程序,這時候是孫子程序
exit(0);//退出上一代程序
}else if(pid<0){
exit(1);
}
close(1);//關閉檔案
close(2);
chdir(rundir);//改變執行的目錄
umask(022);//改變檔案許可權
}

守護程序的錯誤輸出

守護程序不屬於任何終端,所以當需要輸出某些資訊時,它無法像一般程式那樣將資訊直接輸出到標準輸出和標準錯誤輸出中。我們很大時候也不希望每個守護程序將它自己的出錯訊息寫到一個單獨的檔案中。因為對於系統管理人員而言,要記住哪一個守護程序寫到哪一個記錄檔案中,並定期的檢查這些檔案,他一定會為此感到頭疼的。所以,我們需要有一個集中的守護程序出錯記錄機制。目前很多系統都引入了syslog記錄程序來實現這一目的。

自伯克利開發了BSD syslog並廣泛應用以來,BSD syslog 機制被大多數守護程序所使用。我們下面介紹BSD syslog 的用法。有三種方法產生記錄訊息:

1 核心例程可以呼叫log函式。任何一個使用者程序通過開啟和讀/dev/klog裝置就可以讀取這些訊息。因為我們無意編寫核心中的例程,所以不再進一步說明此函式。

2 大多數使用者程序(守護程序)呼叫syslog函式以產生記錄訊息。我們將在下面說明其呼叫序列。這使訊息傳送至Unix域資料報套介面/dev/log。

3 在此主機上,或通過TCP/IP網路連線到此主機的某一其他主機上的一個使用者程序可將記錄訊息發向UDP埠514。

注意:syslog 函式並不產生這些UDP資料報——它們要求產生此記錄訊息的程序具有顯式的網路程式設計。

通常,syslog守護程序讀取三種格式的記錄訊息。此守護程序在啟動時讀一個配置檔案。一般來說,其檔名為/etc/syslog.conf,該檔案決定了不同種類的訊息應送向何處。例如,緊急訊息可被送向系統管理員(若已登入),並在控制檯上顯示,而警告訊息則可記錄到一個檔案中。該機制提供了syslog函式,其呼叫格式如下

#include 
void openlog (char*ident,int option ,int facility);
void syslog(int priority,char*format,……)
void closelog();

呼叫openlog是可選擇的。如果不呼叫openlog,則在第一次呼叫syslog時,自動呼叫openlog。呼叫closelog也是可選擇的,它只是關閉被用於與syslog守護程序通訊的描述符。呼叫openlog 使我們可以指定一個ident,以後, 此ident 將被加至每則記錄訊息中。ident 一般是程式的名稱(例如 ,cron ,inetd 等)。option 有4種可能:

LOG_CONS 若日誌訊息不能通過Unix域資料報傳送至syslog,則將該訊息寫至控制檯。

LOG_NDELAY1 立即開啟Unix域資料報套介面至syslog守護程序,而不要等到記錄第一訊息。通常,在記錄第一條訊息之前,該套介面不開啟。

LOG_PERROR 除將日誌訊息傳送給syslog 外,還將它至標準出錯。此選項僅由4.3BSDReno及以後版本支援。

LOG_PID 每條訊息都包含程序ID。此選項可供對每個請求都fork一個子程序的守護程序使用。

在openlog中設定facility引數的目的是讓配置檔案可以說明,來自不同設施的訊息以不同的方式進行處理。如果不呼叫openlog,或者以facility 為0來呼叫它,那麼在呼叫syslog 時,可將facility作為priority引數的一個部分進行說明。呼叫syslog產生一個記錄訊息。其priority引數是facility和level的組合,它們可選取的值分別列於下面。level值按優先順序從高階到最低按序排列

python版本:

1. 呼叫fork()以便父程序可以退出,這樣就將控制權歸還給執行你程式的命令列或shell程式。需要這一步以便保證新程序不是一個程序組頭領程序(process group leader)。下一步,‘setsid()’,會因為你是程序組頭領程序而失敗。

2. 呼叫‘setsid()’ 以便成為一個程序組和會話組的頭領程序。由於一個控制終端與一個會話相關聯,而且這個新會話還沒有獲得一個控制終端,我們的程序沒有控制終端,這對於守護程式來說是一件好事。 

3. 再次呼叫‘fork()’所以父程序(會話組頭領程序)可以退出。這意味著我們,一個非會話組頭領程序永遠不能重新獲得控制終端

4. 呼叫‘chdir("/")’確認我們的程序不保持任何目錄於使用狀態。不做這個會導致系統管理員不能卸裝(umount)一個檔案系統,因為它是我們的當前工作目錄。 [類似的,我們可以改變當前目錄至對於守護程式執行重要的檔案所在目錄] 

5. 呼叫‘umask(0)’以便我們擁有對於我們寫的任何東西的完全控制。我們不知道我們繼承了什麼樣的umask。 [這一步是可選的](譯者注:這裡指步驟5,因為守護程式不一定需要寫檔案)

6. 呼叫‘close()’關閉檔案描述符0,1和2。這樣我們釋放了從父程序繼承的標準輸入,標準輸出,和標準錯誤輸出。我們沒辦法知道這些文描述符符可能已經被重定向去哪裡。注意到許多守護程式使用‘sysconf()’來確認‘_SC_OPEN_MAX’的限制。‘_SC_OPEN_MAX’告訴你每個程序能夠開啟的最多檔案數。然後使用一個迴圈,守護程式可以關閉所有可能的檔案描述符。你必須決定你需要做這個或不做。如果你認為有可能有開啟的檔案描述符,你需要關閉它們,因為系統有一個同時開啟檔案數的限制。 

7. 為標準輸入,標準輸出和標準錯誤輸出建立新的檔案描述符。即使你不打算使用它們,開啟著它們不失為一個好主意。準確操作這些描述符是基於各自愛好;比如說,如果你有一個日誌檔案,你可能希望把它作為標準輸出和標準錯誤輸出開啟,而把‘/dev/null’作為標準輸入開啟;作為替代方法,你可以將‘/dev/console’作為標準錯誤輸出和/或標準輸出開啟,而‘/dev/null’作為標準輸入,或者任何其它對你的守護程式有意義的結合方法。(譯者注:一般使用dup2函式原子化關閉和複製檔案描述符。

def createDaemon():    
        import os
        
        # create - fork 1
        try:
                if os.fork() > 0: 
                        os._exit(0)
        except OSError, error:
                print 'fork #1 failed: %d (%s)' % (error.errno, error.strerror)
            os._exit(1)
     
        # it separates the son from the father
        os.chdir('/')
        os.setsid()
        os.umask(0)
     
        # create - fork 2
        try:
                pid = os.fork()
            if pid > 0:
                print 'Daemon PID %d' % pid
                os._exit(0)
        except OSError, error:
            print 'fork #2 failed: %d (%s)' % (error.errno, error.strerror)
            os._exit(1)
     
        funzioneDemo() # function demo
        
def funzioneDemo():
     
        import time
     
        fd = open('/tmp/demone.log', 'w')
        while True:
                fd.write(time.ctime()+'\n')
            fd.flush()
            time.sleep(2)
        fd.close()
        
if __name__ == '__main__':
     
        createDaemon()


由於需要為OpenStack中的虛擬機器設計監控Agent,因此需要一個穩妥、可靠並簡單的守護程序實現作為基礎框架,故研究了一下Linux系統中的守護程序。

首先,守護程序是一類在後臺執行,生命週期較長的程序,它一般隨系統啟動執行,在系統關閉的時候停止。翻譯了一下《Advanced Programming in The Unix Environment  Section》的第13.3小節,此小節是一個關於守護程序的設計規範,羅列了守護程序設計實現的幾大原則:

翻譯《AdvancedProgrammingin The Unix Environment》Section 13.3 Page 583

守護程序編碼規範:

        本小節將介紹一些守護程序的基本編碼規範,這些規範將阻止守護程序與當前環境產生一些不必要的互動。本節將通過一個函式daemonize實現這些規範。

1.     首先要做的被稱為 umask這一步驟會將檔案建立掩碼重置為0。這一步的原因是守護程序繼承(inherited)得到的檔案掩碼有可能會拒絕某些特定的檔案操作許可權。如果守護程序想要建立檔案,那有可能它需要設定特定的檔案操作許可權。例如,如果守護程序想要建立允許組讀和寫(group-readand group-write)許可權的檔案,但繼承得到的檔案建立掩碼遮蔽了這個許可權,則建立操作不會成功。

2.    呼叫 fork 並使父程序退出(exit)。這一步驟的目的在於。首先,如果守護程序是通過一個簡單的shell命令建立的,那麼在父程序終止的時候shell會認為命令已經結束了繼而結束守護程序。其次,子程序繼承得到父程序的groupID同時也獲得了一個新的程序號,所以我們必須得保證子程序不能擔任groupleader的角色,這是下一步setsid 操作的前提。

注:此步是使得程在後臺執行。

3.    呼叫 setsid 建立一個新的會話。有三個步驟將會執行:(a)程序將成為這個新會話的sessionleader角色,(b)此程序將會成為一個新的程序組的groupleader,(c)此程序將不會有控制終端。

注:此步將使得程脫離控制端、登以及

·     在基於SystemV的系統中,有建議再一次呼叫fork 並使父程序退出。而新產生的程序將會成為真正的守護程序。這一步驟將保證守護程序不是一個sessionleader,進而阻止它獲取一個控制終端。或者另一種阻止守護程序獲取控制終端的方案是任意時刻開啟一個終端裝置的時候確保指定O_NOCTTY

注:此步將禁止程重新開啟控制端。

4.    將當前的工作目錄切換到系統根目錄下。因為從父程序整合來的當前工作目錄可能是一個被掛載的檔案系統。因為守護程序通常是直到系統重啟的時候才會退出,如果守護程序的工作目錄在一個掛載的檔案系統上,那麼這個檔案系統就不能被解除安裝(unmounted)。

·      有的守護程序可能會將當前的工作目錄切換到一些特定的路徑,在這些路徑下它們將完成它們的工作。例如,lineprinter spoolingdaemons 通常將工作目錄切換為spool目錄。

5.    一些不必要的檔案描述符將會被關閉。這個步驟將阻止守護程序保持從父程序整合到的任何已經開啟的檔案描述符(也可能是shell或其他程序)。我們可以使用 open_max 函式或 getrlimit 函式來查詢當前優先順序最高的檔案描述符並關閉此描述符之下的所有其他描述符。

注:保持開啟的描述符將會佔用系統資源並可能使某些檔案不能被卸

6.    有一些守護程序將開啟檔案描述符0, 1, 2 指向 /dev/null ,這樣一來所有試圖從標準輸入、輸出及錯誤讀取守護程序資訊的操作都不能成功。因為守護程序當前已經不與任何終端裝置相關聯,沒有地方顯示其輸出或接受使用者的輸入。即使守護程序是從一個互動式session建立的,守護程序也將執行在後臺,任何終端的登入與終止將不會影響守護程序。如果有其他使用者通過當前的終端登入,我們也不希望守護程序的輸出出現在終端上,並且該使用者的任何輸入也不會被守護程序接收。

總結起來就是:

1) 第一次fork將會建立父-子程序,同時使得父程序退出保證守護程序能夠執行在後臺。

2) 通過setsid步驟使得程序與控制終端、登入會話以及程序組脫離。

3) 第二次fork將確保程序重新開啟控制終端,並且產生子-孫程序,而子程序退出後孫程序將成為真正的守護程序。

4) 其他還有一些諸如工作目錄設定、關閉檔案描述符、設定檔案建立掩碼之類的操作。

最後看一個python實現的例子,程式碼來自:http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/

  1. #!/usr/bin/env python
  2. import sys, os, time, atexit  
  3. from signal import SIGTERM   
  4. class Daemon:  
  5.     """ 
  6.     A generic daemon class. 
  7.     Usage: subclass the Daemon class and override the run() method 
  8.     """
  9.     def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):  
  10.         self.stdin = stdin  
  11.         self.stdout = stdout  
  12.         self.stderr = stderr  
  13.         self.pidfile = pidfile  
  14.     def daemonize(self):  
  15.         """ 
  16.         do the UNIX double-fork magic, see Stevens' "Advanced  
  17.         Programming in the UNIX Environment" for details (ISBN 0201563177) 
  18.         http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16 
  19.         """
  20.         try:   
  21.             pid = os.fork()   
  22.             if pid > 0:  
  23.                 # exit first parent
  24.                 sys.exit(0)   
  25.         except OSError, e:   
  26.             sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))  
  27.             sys.exit(1)  
  28.         # decouple from parent environment
  29.         os.chdir("/")   
  30.         os.setsid()   
  31.         os.umask(0)   
  32.         # do second fork
  33.         try:   
  34.             pid = os.fork()   
  35.             if pid > 0:  
  36.                 # exit from second parent
  37.                 sys.exit(0)   
  38.         except OSError, e:   
  39.             sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))  
  40.             sys.exit(1)   
  41.         # redirect standard file descriptors
  42.         sys.stdout.flush()  
  43.         sys.stderr.flush()  
  44.         si = file(self.stdin, 'r')  
  45.         so = file(self.stdout, 'a+')  
  46.         se = file(self.stderr, 'a+'0)  
  47.         os.dup2(si.fileno(), sys.stdin.fileno())  
  48.         os.dup2(so.fileno(), sys.stdout.fileno())  
  49.         os.dup2(se.fileno(), sys.stderr.fileno())  
  50.         # write pidfile
  51.         atexit.register(self.delpid)  
  52.         pid = str(os.getpid())  
  53.         file(self.pidfile,'w+').write("%s\n" % pid)  
  54.     def delpid(self):  
  55.         os.remove(self.pidfile)  
  56.     def start(self):  
  57.         """ 
  58.         Start the daemon 
  59.         """
  60.         # Check for a pidfile to see if the daemon already runs
  61.         try:  
  62.             pf = file(self.pidfile,'r')  
  63.             pid = int(pf.read().strip())  
  64.             pf.close()  
  65.         except IOError:  
  66.             pid = None
  67.         if pid:  
  68.             message = "pidfile %s already exist. Daemon already running?\n"
  69.             sys.stderr.write(message % self.pidfile)  
  70.             sys.exit(1)  
  71.         # Start the daemon
  72.         self.daemonize()  
  73.         self.run()  
  74.     def stop(self):  
  75.         

    相關推薦

    Linux守護程序設計規範python實現

    守護程序 守護程序是生存期長的一種程序。它們獨立於控制終端並且週期性的執行某種任務或等待處理某些發生的事件。他們常常在系統引導裝入時啟動,在系統關閉時終止。unix系統有很多守護程序,大多數伺服器都是用守護程序實現的。比如,網路服務inetd、Web服務http等。同時,

    設計模式Python實現

    enter import == 功能 編程問題 設計模式的 技術 big 內部實現 設計模式是什麽? Christopher Alexander:“每一個模式描述了一個在我們周圍不斷重復發生的問題,以及該問題的解決方案的核心。這樣你就能一次又一次地使用該方案而不必做重復勞動

    Linux 守護程序建立原理簡易方法

    1:什麼是Linux下的守護程序   Linux daemon是運行於後臺常駐記憶體的一種特殊程序,週期性的執行或者等待trigger執行某個任務,與使用者互動斷開,獨立於控制終端。一個守護程序的父程序是init程序,它是一個孤兒程序,沒有控制終端,所以任何輸出,無論是向標準輸出裝置stdo

    linux守護程序詳解建立,daemon()使用

    Linux Daemon(守護程序)是執行在後臺的一種特殊程序。它獨立於控制終端並且週期性地執行某種任務或等待處理某些發生的事件。它不需要使用者輸入就能執行而且提供某種服務,不是對整個系統就是對某個使用者程式提供服務。Linux系統的大多數伺服器就是通過守護程序實現的。常見的守護程序包括系統日誌程序sysl

    淺談設計模式python實現

    設計模式及Python實現   設計模式是什麼? Christopher Alexander:“每一個模式描述了一個在我們周圍不斷重複發生的問題,以及該問題的解決方案的核心。這樣你就能一次又一次地使用該方案而不必做重複勞動。” 設計模式是經過總結、優化

    Linux程序程式替換簡單的shell的實現

    替換原理: 用fork建立程序後執行的是和父程序相同的程式(但有可能執行不同的程式碼分支),子程序往往要呼叫exec函式以執行另一個程式。當程序呼叫一種exec函式時,該程序的使用者空間程式碼和資料完全被新程式替換。從新程序的啟動例程開始執行,呼叫exec函式並不建立新程序

    多執行緒與多程序Python實現【理論部分】

    計算機的核心是CPU,它承擔了所有的計算任務。它就像一座工廠,時刻在執行。 假定工廠的電力有限,一次只能供給一個車間使用。也就是說,一個車間開工的時候,其他車間都必須停工。背後的含義就是,單個CPU一次只能執行一個任務。 程序就好比工廠的車間,它代表CPU所能處理的單個任務。任一時刻,CPU總是執行一個程序

    多執行緒與多程序Python實現Python實現程序

    上一篇部落格介紹了多執行緒與多程序的理論部分,這篇部落格將參考部落格以及各種教程完成Python多程序實現部分。 multiprocessing模組 Process 類 multiprocessing.Process(group=None, target=N

    Linux----網路程式設計(守護程序相關概念程式設計流程)

    一、守護程序的相關定義 守護程序:也稱為精靈程序,執行在後臺的一種特殊程序。守護程序獨立於控制終端並且週期性的執行某種任務或者等待處理髮生的事件。所以守護程序不因為使用者、終端或其他的變化而受影響。 守護程序的特點:  1. 執行週期長                 

    linux系統程式設計之程序(八):守護程序詳解建立,daemon()使用

    一,守護程序概述 Linux Daemon(守護程序)是執行在後臺的一種特殊程序。它獨立於控制終端並且週期性地執行某種任務或等待處理某些發生的事件。它不需要使用者輸入就能執行而且提供某種服務,不是對整個系統就是對某個使用者程式提供服務。Linux系統的大多數伺服器就是通過守護程序實現的。常見的守護程序包括系

    C++ 泛型程序設計與STL模板庫(1)---泛型程序設計簡介STL簡介與結構

    urn 向上 隊列 是把 鏈表 需要 input stack 特定 泛型程序設計的基本概念 編寫不依賴於具體數據類型的程序 將算法從特定的數據結構中抽象出來,成為通用的 C++的模板為泛型程序設計奠定了關鍵的基礎 術語:概念 用來界定具備一定功能的數據類型。例如:

    機器學習經典算法具體解釋Python實現--線性回歸(Linear Regression)算法

    ica single 方便 最好的 而且 == show des fun (一)認識回歸 回歸是統計學中最有力的工具之中的一個。機器學習監督學習算法分為分類算法和回歸算法兩種,事實上就是依據類別標簽分布類型為離散型、連續性而定義的。顧名思義。分類算法用於離散型分布

    常見的查找算法的原理python實現

    put arch img 字典 python實現 需要 技術 () one 順序查找 二分查找 練習 一、順序查找 data=[1,3,4,5,6] value=1 def linear_search(data,value): flag=False

    經典排序算法python實現

    設計 python get 排序。 技術 排好序 sort RR 第一部分 今天我們來談談幾種經典排序算法,然後用python來實現,最後通過數據來比較幾個算法時間 選擇排序 選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工作原理是每一次從待排序的數

    詳解AMD規範具體實現requireJS在工程中的使用

    當前頁 eid 資源 自己 一個數 中比 ocs 網站 重定位   由CommonJS組織提出了許多新的JavaScript架構方案和標準,希望能為前端開發提供統一的指引。AMD規範就是其中比較著名一個,全稱是Asynchronous Module Definition

    短時傅裏葉變換(Short Time Fourier Transform)原理 Python 實現

    src 參考 函數 ade block return 技術 數學公式 def 原理   短時傅裏葉變換(Short Time Fourier Transform, STFT) 是一個用於語音信號處理的通用工具.它定義了一個非常有用的時間和頻率分布類, 其指定了任意信號隨時間

    數據回歸分類預測的基本算法python實現

    sse 最小 die href cos xgboost 但是 預測 split 數據回歸分類預測的基本算法及python實現 關於數據的回歸和分類以及分析預測。討論分析幾種比較基礎的算法,也可以算作是比較簡單的機器學習算法。 一. KNN算法 鄰近算法,可以用

    線程池原理python實現

    source 實例 以及 代碼 let range python實現 queue 上界 https://www.cnblogs.com/goodhacker/p/3359985.html 為什麽需要線程池   目前的大多數網絡服務器,包括Web服務器、Email服務器以

    程序的原子性,python實現原子性,上鎖解鎖threading.Lock()

    執行 結束 錯誤 多個 加鎖 lease mut 同時 帳戶 A想要從自己的帳戶中轉1000塊錢到B的帳戶裏。那個從A開始轉帳,到轉帳結束的這一個過程,稱之為一個事務。在這個事務裏,要做如下操作:1. 從A的帳戶中減去1000塊錢。如果A的帳戶原來有3000塊錢,現在就變成

    FM算法解析Python實現

    line 類型檢查 lse pytho spl ont 核心 ict 作者 1. 什麽是FM? FM即Factor Machine,因子分解機。 2. 為什麽需要FM? 1、特征組合是許多機器學習建模過程中遇到的問題,如果對特征直接建模,很有可能會忽略掉特征與特征之間的關聯