Python創建daemon

    參考《Linux/Unix 系統編程手冊》

    變成daemon,一個程序需要完成以下步驟:

    1、執行一個fork(),父進程退出,子進程繼續執行。(daemon成爲了init進程的子進程)  

    --假設daemon是從命令行啓動,父進程的終止會被shell發現,之後shell會顯示出另一個shell提示符並讓子進程在後臺運行;

    --子進程被確保不會成爲一個進程組的首進程(它從父進程繼承了進程組ID,並擁有了自己唯一的進程ID,該進程ID與繼承來的進程組ID是不同的,這樣才能成功執行下面一個步驟)

    2、子進程調用setsid()開啓一個新會話並釋放它與控制終端之間的所有關聯;

    3、對於終端設備的處理:

    --daemon從未打開過終端設備,不需做任何處理;

    --daemon後面可能會打開一個終端設備,必須採取措施確保該設備不會成爲控制終端,具體措施:

      1、在所有可能應用到一個終端設備上的open() 調用中指定O_NOCTTY標記;

      2、在setsid()調用之後執行第二個fork(),再次讓父進程退出並讓孫子進程繼續執行,(這樣確保了子進程不會成爲會話組長,進程永遠不會重新請求一個控制終端--根據SystemV中獲取終端規則)

    4、清除進程的umask(確保daemon創建文件和目錄時擁有必要的權限)

    5、修改進程當前工作目錄(通常改爲根目錄 /,保證根目錄的文件系統不會被卸載即可,如:cron會將自身放在/var/spool/cron 目錄下)

    6、關閉daemon從父進程繼承而來的所有打開着的文件描述符(由於daemon失去了控制終端,對0,1,2描述符完全可以關閉;無法卸載長時間運行的daemon打開的文件所在的文件系統----文件描述符是一種有限資源)

    7、關閉0,1,2文件描述符後,daemon通常會打開/dev/null,並讓所有描述符都指向該設備

    --這樣確保了當daemon調用在這些文件描述符上執行IO的庫函數時不會出乎意料的失敗;

實例:

import sys,os,time

def main():
    """ A demo daemon main routine, write a datestamp to /tmp/daemon-log every 10 seconds."""

    f = open("/tmp/daemon-log", "w") 
    while 1: 
        f.write('%s/n' % time.ctime(time.time())) 
        f.flush() 
        time.sleep(10) 

if __name__ == "__main__":
    # do the UNIX double-fork magic
    try: 
        pid = os.fork() 
        if pid > 0:
            # exit first parent
            sys.exit(0) 
    except OSError, e: 
        print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror) 
        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, print eventual PID before
            print "Daemon PID %d" % pid 
            sys.exit(0) 
    except OSError, e: 
        print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror) 
        sys.exit(1) 
		
    # start the daemon main loop
    main()


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章