Golang建立daemon程式

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。## daemon的概念守護進程(daemon)就是一直在後台啟動並執行進程,它沒有控制終端,無法和前台的使用者互動。當我們開啟一個終端時會建立一個session會話(shell),從使用者登入開始到使用者退出為止,這段時間內在該終端執行的進程都屬於這一個會話。一個會話一般包含一個前台進程組、一個後台進程組和一個會話首進程(shell程式本身)。例如用以下命令啟動5個進程:> $ proc1 | proc2 &> $ proc3 | proc4 | proc5> proc1和proc2屬於同一個後台進程組,proc3、proc4、proc5屬於同一個前台進程組,Shell進程本身屬於一個單獨的進程組。這些進程組的控制終端相同,它們屬於同一個session。> **"背景工作"與"前台任務"的本質區別只有一個:是否繼承標準輸入。背景工作不再繼承當前 session 的標準輸入(stdin),你無法向背景工作輸入指令了,但是背景工作繼承了標準輸出(stdout)和標準錯誤(stderr)背景工作的所有輸出依然會同步地在命令列下顯示**當終端關閉或者檢測到網路連接斷開時會將掛斷訊號(SIGHUP)發送給終端控制進程(會話期首進程,shell進程)。如果會話期首進程接收到SIGHUP訊號後會終止,會同時給前台進程組發送SIGHUP訊號(進程接收到SIGHUP訊號預設處理是退出),shell的**huponexit**參數 `(shopt | grep huponexit)` 決定了shell退出時是否發送SIGHUP訊號給後台進程組。## 如何?守護進程守護進程要與從啟動它的父進程(一般是shell程式)的運行環境隔離開來,需要處理的內容大致包括會話、控制終端、進程組、檔案描述符、檔案許可權掩碼以及工作目錄等。```void init_daemon(){ pid_t pid; int i = 0;// 1. 建立子進程,父進程退出,父進程退出子進程變成孤兒進程,孤兒進程由init進程(pid為1)收養 if ((pid = fork()) == -1) { printf("Fork error !\n"); exit(1); } if (pid != 0) { exit(0); // 父進程退出 }// 2. 子進程調用**setsid**建立新會話,成為成為會話首進程,並且子進程成為一個新進程組的組長進程,而新的會話也脫離了控制終端的控制。//(組長進程調用 setsid會出錯,所以第一步fork出子進程,fork出的子進程一定不會是組長進程) setsid(); //3. 子進程變成無終端的會話首進程,但是它仍然可以重新申請開啟一個控制終端。可以通過再次建立子進程結束當前進程,使進程不再是會話首進程來禁止進程重新開啟控制終端。 if ((pid = fork()) == -1) { printf("Fork error !\n"); exit(-1); } if (pid != 0) { exit(0); } //4. 改變目前的目錄為根目錄,重設檔案許可權掩碼,關閉檔案描述符 //因為這幾樣東西都是繼承自父進程的 chdir("/tmp"); // 改變工作目錄 umask(0); // 重設檔案掩碼 for (; i < getdtablesize(); ++i) { close(i); // 關閉開啟的檔案描述符 } return;}```##go語言如何?守護進程目前Go程式還不能完全實現daemon,因為go程式在啟動時runtime可能會建立多個線程(用於記憶體管理,記憶體回收,goroutine管理等),而fork與多線程環境並不能和諧共存。 [godaemon](https://github.com/VividCortex/godaemon)提供了一種解決方案(當然不是完美的daemon)程式碼範例:```func main() {godaemon.MakeDaemon(&godaemon.DaemonAttr{})}```1. 將stdin、stdout、stderr重新導向到/dev/null,調用os.StartProcess()函數再次啟動自身(fork 完後立即執行exec),通過設定Setsid使新開啟的子進程成為一個會話首領進程,並脫離終端的控制,父進程退出。2. 子進程再次調用StartProcess()建立孫子進程(這個過程主要是為了讓孫子進程不再是會話首進程來禁止進程重新開啟控制終端)3. 孫子進程就是最終的守護進程,然後改變目前的目錄為根目錄,重設檔案許可權掩碼等。> + **程式會反覆啟動,在godaemon.MakeDaemon()函數之前的語句會執行多次**+ **通過設定環境變數__DAEMON_STAGE程式能夠知道自己處在什麼階段**## 使用Supervisord搞那麼麻煩幹嘛,直接用Supervisor啊!## 參考資料[Linux 守護進程的實現](http://alfred-sun.github.io/blog/2015/06/18/daemon-implementation/)[daemon 進程為什麼要fork兩次 ](http://wanghaibo.m.blog.chinaunix.net/uid-27105712-id-3356916.html)[godaemon](https://github.com/VividCortex/godaemon)
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.