一、說明
1.1 背景說明
剛工作時D運營商多用CentOS6,在很長的一段時間內搞不清這兩個問題:為什么yum安裝的mysql服務用service命令就能啟動了、如果自己rpm安裝的或自己寫的程序也想改成能用service命令啟動那又該怎么做。
后來更多用了CentOS7,CentOS7又改用systemctl,和service又有所不同。
自己對Linux時常有一些畏懼感,這種畏懼的由來是有些東西研究了很多次仍然研究不清楚,比如firewall就研究了很多次但現在仍不太會用,這進而導致一些只是看起來難的東西也不想去看了。systemctl就是如此。
最近經同事的提點,對systemctl有了些理解,在此記一記。
1.2 service和systemctl
是使用service還是systemctl,取決於操作系統初使化進程(即pid為1的進程)使用的是System V init還是Systemd,前者使用的服務管理命令是service后者使用的是systemctl。
總的而言Systemd在啟動速度等方面較System V init都具有優勢,雖然有一些反對的聲音,但Systemd取代System V init已是大勢所趨。更多內容可點擊鏈接。
在新版本的CentOS7中我們可以看到也是可以使用service命令的,但這個service命令其實只是systemctl的一個腳本封裝。
二、添加一個systemd服務
我們這使用nc沒安裝先用yum安裝一下:yum install nc -y
2.1 創建簡單的服務配置文件
cat > /usr/lib/systemd/system/lstestd.service << EOF [Unit] Description=it is a ls test service Documentation=man:nc After=network.target [Service] ExecStart=/usr/bin/nc -l 9998 ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartSec=42s [Install] WantedBy=multi-user.target EOF
其中其實最主要的就是systemctl start調用的ExecStart(其值就是正常的bash命令)和systemctl stop使用的KillMode,其他隨意看着填。(停止也可以用"ExecStop=/bin/kill -9 $MAINPID"這種暴力寫法)
2.2 啟動和停止服務
創建上邊配置文件后一個systemd服務就相當於配置完了,下邊直接用systemctl來啟動即可。我們文件名是lstestd,即用該名稱來調用即可。
# 查看服務狀態
systemctl status lstestd
# 啟動服務
systemctl start lstestd
# 停止服務
systemctl stop lstestd
如下圖所示可以成功使用systemctl進行控制
三、systemd服務的幾種情況
上邊的systemd服務配置還是很簡單的,事實上systemd還可以配置在服務啟動前(ExecStartPre)、啟動后(ExecStartPost)、停止后(ExecStopPost)等眾多情況做很多事情,可自行man systemd.service查看手冊進行學習。這只說自己疑惑的幾種情況
3.1 systemctl enable在做什么
我們知道systemctl enable lstestd表示將lstestd服務設為開機自啟動(service對應的是chkconfig lstestd on),那他到底是如何實現的呢。
man systemctl看了一下說就只是給配置文件創建了一個軟件鏈,且在執行systemctl enable時會直接輸出他做了什么,我們測試如下:
那所謂設置開機自啟動,那猜測就是系統啟動時會自動啟動/etc/systemd/system/目錄下的服務,在這目錄下創建/刪除軟鏈接即能設置/f去除開機自啟動。
另外要注意如果一個服務被設置為開機自啟動后,再去修改服務配置文件時,需要執行一下“systemctl daemon-reload”,不然后續操作該服務會報如下錯誤:
Warning: lstestd.service changed on disk. Run 'systemctl daemon-reload' to reload units.這
這個命令我還不太確定是做了什么事情,因為我們對配置文件的修改已經保存了,enable也只是做個軟鏈,那還需要額外做什么呢。
3.2 systemctl啟動命令時如何給服務傳遞參數
日常啟程序時我們常在命令行給程序傳遞參數,比如"nc -l 9998",那systemctl有沒有類似“systemctl start lstestd -l 9998”之類的寫法,能讓我們在命令行給服務傳遞參數呢。
首先結論是systemctl是不支持通過命令行給程序動態傳遞參數的,折中的做法是可以使用Environment/EnvironmentFile配置變量,然后在后邊的命令中就可以使用這些參數了。
直接定義變量:
Environment="ONE=one" 'TWO=two two' ExecStart=/bin/echo $ONE $TWO ${TWO}
變量定義在另外的配置文件中:
EnvironmentFile=/etc/sysconfig/testenv ExecStart=/bin/echo $ONE $TWO
/etc/sysconfig/testenv定義如下:
# define your vars like in bash file ONE=one TWO=two