駱小剛:Linux後臺服務啓動方式systemd、daemon、nohup大比拼

作者簡介

駱小剛,現就職於深圳市普康電子有限公司,高級軟件工程師。負責arm下u-boot、kernel開發,APP框架搭建,底層軟件開發,算法開發,性能優化等。對開源軟件有濃厚興趣。

本文主要用實例剖析systemd、daemon()、nohup啓動服務的差異。

環境:ubuntu 1804 x86_64, linux 5.0,  gcc 8.3.0 

1. systemd啓動服務

systemd是最新linux發行版管理後臺的服務的默認形式,用以取代原有的init。

1.1 編寫服務程序

vim simple-server.c

gcc simple-server.c  -o simple-server

1.2 配置服務

編輯服務配置文件simple-server.service

vim simple-server.service 

解析:

[Unit] :服務單元

Description:對該服務進行簡單的描述

[Service]:服務運行時行爲配置

ExecStart:程序的完整路徑

Restart:重啓配置,no、always、on-success、on-failure、on-abnormal、on-abort、on-watchdog

[Install]:安裝配置

WantedBy:多用戶等

其他配置選項請參考:

https://www.freedesktop.org/software/systemd/man/systemd.service.html

將配置拷貝到/lib/systemd/system/目錄下:

sudo cp simple-server.service /lib/systemd/system/

1.3 啓用服務

sudo systemctl enable simple-server

會創建一個指向配置文件/lib/systemd/system/simple-server.service的符號鏈接

/etc/systemd/system/multi-user.target.wants/simple-server.service

1.4 開啓服務

sudo systemctl start simple-server

1.5 服務狀態

1.5.1服務與終端的關係

pstree

可以看到systemd啓動的服務直接是pid=1的systemd進程的子進程。

可以看到服務程序忽略了SIGPIPE信號。

服務沒有控制終端(tty爲“?”)。

1.5.3 服務的運行日誌

sudo lsof -p 6213

用lsof可以看到服務的用戶爲root,當前目錄和根目錄都是“/”,輸入被重定向到/dev/null,輸出和出錯被重定向到socket。

1.5.4 服務的運行狀態

sudo systemctl status simple-server

我可以看到simple-server服務已經loaded,並且處於active狀態。還可以看到PID、Tasks數量、服務管理日誌等。

1.6 關閉服務

sudo systemctl stop simple-server

1.7 停用服務

 sudo systemctl disable simple-server

2. daemon啓動服務

2.1 編寫代碼

vim daemon.c 

gcc  daemon.c -o daemon

 

2.2 啓動服務

./daemon

2.3 服務狀態

2.3.1 服務與終端的關係

服務把自己設置爲會話首領,父進程是當前用戶級的systemd(subreaper ),完全脫離終端。

2.3.2 服務的信號處理

ps -C daemon s

沒有屏蔽信號。

控制終端tty爲“?”

2.3.3 服務的運行日誌

當前目錄和根目錄都是“/”,用戶爲普通用戶,輸入、輸出、出錯都重定向到/dev/null

2.4 停止服務

killall  daemon 

3. nohup 啓動服務

3.1 編寫代碼

vim nohup.c

gcc nohup.c -o nohup

3.2 啓動服務

nohup命令啓動這個名字也叫nohup的程序

(注意後面一個nohup是上面寫的那個很簡單的程序的名字)

nohup ./nohup

3.3 服務狀態

3.3.1服務與終端的關係

服務的父進程是啓動該服務的bash,和bash在一個會話組。

3.3.2 服務的信號處理

普通用戶,屏蔽SIGHUP信號,依賴終端bash。由於屏蔽了SIGHUP,終端關閉的時候,會忽略終端發送的SIGHUP信號,繼續運行服務。

3.3.3服務的運行日誌

輸入被重定向到/dev/null,輸出、出錯爲當前目錄下的nohup.out,格式沒有帶時間,不便於分析問題。

3.4 服務關閉

killall nohup

4. 總結

4.1 後臺運行服務的基本需求

基本需求:

  •  脫離終端(終端關閉時,服務不能關閉)

  •  處理輸入、輸出、出錯描述符

4.1.1  systemd

自己本身就是一個init或者user級的subreaper;

系統級systemd啓動的服務以root權限運行;

重定向輸入到/dev/null,輸出、出錯通過socket發給系統日誌模塊。

4.1.2 daemon

通過fork後父進程exit,讓子進程託孤給subreaper,實現在後臺運行服務。

重定向輸入、輸出、出錯到/dev/null.

源碼參考:

https://github.com/lattera/glibc/blob/master/misc/daemon.c

4.1.3 nohup

  通過忽略終端關閉時的廣播信號SIGHUP,實現在後臺運行服務。

重定向輸入到/dev/null,輸出、出錯重定向到當前目錄下的nohup.out文件,

4.2 後臺運行服務的高級需求

高級需求:

  • 方便分析問題的服務運行日誌記錄

  •  服務管理的日誌

  •  異常退出時可以根據需要重新啓動

daemon不能實現上面的高級需求。

nohup 只能記錄服務運行時的輸出和出錯日誌。

只有systemd能夠實現上述所有需求。

 

默認的日誌中增加了時間、用戶名、服務名稱、PID等,非常人性化。

還能看到服務運行異常退出的日誌。

還能通過/lib/systemd/system/下的配置文件定製各種需求。

還有非常非常多強大的功能等着你去探索:

https://www.freedesktop.org/software/systemd/man/systemd.html

4.3 systemd是目前linux管理後臺服務的主流方式

Linux閱碼場原創精華文章彙總

更多精彩,盡在"Linux閱碼場",掃描下方二維碼關注

點一點右下角”在看”,爲閱碼場打Call~

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