Linux開機自啟動配置

空山新雨的技術空間發表於2020-03-27

很多時候,我們需要將一些服務在Linux系統啟動時即自動執行,省得每次都要去手動啟動一遍,如Redis, MySQL, Nginx等。本文對CentOS與Ubuntu下開機自啟動的配置方法進行整理,供參考查閱。

CentOS7的開機自啟動配置

一. rc.local方式

rc.local是CentOS以前版本的方式,在CentOS7中仍然以相容的形式存在,雖仍可用,但不推薦(推薦使用systemd service)。

1、編寫需要開機自啟動的指令碼,並新增執行許可權

[root@dev-server-1 ~]# vim test_rclocal.sh

#!/bin/bash
time=`date +%F_%T`
echo $time' from rc.local' >> /tmp/test.log

[root@dev-server-1 ~]# chmod +x test_rclocal.sh複製程式碼

作為測試,上述指令碼列印一個時間到/tmp/test.log檔案中

2、在/etc/rc.d/rc.local配置檔案中新增指令碼執行命令(使用絕對路徑)

[root@dev-server-1 ~]# vim /etc/rc.d/rc.local 

#!/bin/bash
# ...註釋部分
touch /var/lock/subsys/local

/root/test_rclocal.sh >/dev/null 2>/dev/null
複製程式碼

3、新增/etc/rc.d/rc.local檔案的執行許可權

在centos7中,/etc/rc.d/rc.local沒有執行許可權,需要手動授權

[root@dev-server-1 ~]# chmod +x /etc/rc.d/rc.local複製程式碼

以上三步,即可使/root/test_rclocal.sh >/dev/null 2>/dev/null 命令在伺服器系統啟動時自動執行。

二. chkconfig方式

1、編寫需要開機自啟動的測試指令碼,並新增執行許可權

[root@dev-server-1 ~]# vim test_chkconfig.sh

#!/bin/bash

time=`date +%F_%T`
echo $time' from chkconfig' >> /tmp/test.log

[root@dev-server-1 ~]# chmod +x test_chkconfig.sh複製程式碼

2、在/etc/rc.d/init.d/目錄下新增一個可執行指令碼testchkconfig

[root@dev-server-1 ~]# vim /etc/rc.d/init.d/testchkconfig

#!/bin/bash
# chkconfig: 2345 90 10
# description: test chkconfig

/root/test_chkconfig.sh >/dev/null 2>/dev/null

[root@dev-server-1 ~]# chmod 755 /etc/rc.d/init.d/testchkconfig複製程式碼

上述testchkconfig指令碼的頭部必須遵循一定的格式 # chkconfig: 2345 90 10, 其中2345指定服務在哪些執行等級中開啟或關閉,90表示啟動的優先順序(0-100,越大優先順序越低),10表示關閉的優先順序。執行等級包括

  • 0:表示關機
  • 1:單使用者模式
  • 2:無網路連線的多使用者命令列模式
  • 3:有網路連線的多使用者命令列模式
  • 4:保留未使用
  • 5:帶圖形介面的多使用者模式
  • 6:重新啟動

3、加入開機啟動服務列表

[root@dev-server-1 ~]# chkconfig --add testchkconfig
[root@dev-server-1 ~]# chkconfig --list

Note: This output shows SysV services only and does not include native
      systemd services. SysV configuration data might be overridden by native
      systemd configuration.

      If you want to list systemd services use 'systemctl list-unit-files'.
      To see services enabled on particular target use
      'systemctl list-dependencies [target]'.

netconsole         0:off    1:off    2:off    3:off    4:off    5:off    6:off
network            0:off    1:off    2:on    3:on    4:on    5:on    6:off
testchkconfig      0:off    1:off    2:on    3:on    4:on    5:on    6:off複製程式碼

使用 chkconfig --list 可檢視當前加入開機自啟動的服務列表,但如Note部分所述,該命令只顯示SysV服務,不包含原生的systemd服務,檢視systemd服務可使用systemctl list-unit-files命令。

以上三步,即可使/root/test_chkconfig.sh >/dev/null 2>/dev/null 命令在伺服器系統啟動時自動執行。

chkconfig的其它命令參考

$chkconfig --list # 表示檢視所有服務在各個執行級別下的狀態。
$chkconfig testchkconfig on # 表示指定服務在所有的執行級別下都是開啟狀態。
$chkconfig testchkconfig off # 表示指定服務在所有的執行級別下都是關閉狀態。
$chkconfig --level 5 testchkconfig on # 表示指定服務在執行級別5圖形模式的狀態下開機啟動服務。
$chkconfig --level 5 testchkconfig off # 表示指定服務在執行級別5圖形模式的狀態下開機不啟動服務。複製程式碼

三. 自定義systemd service方式

CentOS7的systemd服務指令碼存放在:/usr/lib/systemd/system(系統級)/usr/lib/systemd/user(使用者級)下,以.service結尾。這裡以nginx為例

1、在/usr/lib/systemd/system目錄下建立nginx.service檔案

[devuser@test-server-1 ~]$ sudo vim /usr/lib/systemd/system/nginx.service

[Unit]
Description=nginx server
Documentation=http://nginx.org/en/docs/
# 依賴服務,僅當依賴的服務啟動之後再啟動自定義的服務
After=network.target remote-fs.target nss-lookup.target  

[Service]
# 啟動型別,包括simple、forking、oneshot、notify、dbus
Type=forking
# pid檔案路徑
PIDFile=/var/run/nginx.pid
# 啟動前執行的操作
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
# 啟動命令
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
# 過載命令
ExecReload=/usr/local/nginx/sbin/nginx -s reload
# 停止命令
ExecStop=/usr/local/nginx/sbin/nginx -s stop
# 是否給服務分配獨立的臨時空間
PrivateTmp=true

[Install]
# 服務安裝的使用者模式,一般使用multi-user即可
WantedBy=multi-user.target複製程式碼

其中Service部分的Type包括如下幾種型別:

  • simple:表示ExecStart啟動的程式是該服務的主程式。如果它需要為其他程式提供服務,那麼必須在該服務啟動之前先建立好通訊渠道,比如套接字,以加快後續單元的啟動速度。
  • forking:表示ExecStart程式將會在啟動時使用fork()函式,這是傳統Unix系統的做法,也就是說這個程式將由systemd程式fork出來,然後當該程式都準備就緒時,systemd程式退出,而fork出來的程式作為服務的主程式繼續執行,對於此型別的程式,建議設定PIDFile選項,以幫助systemd準確定位該服務的主程式。
  • oneshot:該程式會在systemd啟動後續單元之前退出,適用於僅需要執行一次的程式。比如清理磁碟,你只需要執行一次,不需要一直在後臺執行這個程式。
  • notify:與simple類似,不同之處在於該程式會在啟動完成之後通過sd_notify之類的介面傳送一個通知訊息。systemd在啟動後續單元之前,必須確保該程式已經成功地傳送了一個訊息。
  • dbus:該程式需要在D-Bus上獲得一個由BusName指定的名稱,systemd將會在啟動後續單元之前,首先確保該程式已經成功獲取了指定D-Bus名稱。

2、 開啟開機自啟動

[devuser@test-server-1 ~]$ sudo systemctl enable nginx.service
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.複製程式碼

以上兩步,就將nginx服務配置成了在作業系統啟動時自動啟動。

其它命令參考

$sudo systemctl start nginx.service # 啟動
$sudo systemctl restart nginx.service # 重啟
$sudo systemctl reload nginx.service # 過載
$sudo systemctl stop nginx.service # 停止
$sudo systemctl status nginx.service # 檢視服務狀態
$sudo systemctl cat nginx.service # 檢視服務配置

$systemctl list-unit-files |grep nginx # 檢視服務enabled狀態
$sudo systemctl disable nginx.service # 關閉開機自啟動


$sudo journalctl -f -u nginx.service # 檢視日誌
$sudo systemctl daemon-reload # 配置修改後,重新載入複製程式碼

根據以上配置,通過start啟動nginx服務時,報PID file /var/run/nginx.pid not readable (yet?) after start.的錯誤,啟動失敗,日誌如下

[devuser@test-server-1 ~]$ sudo journalctl -f -u nginx.service
-- Logs begin at Wed 2020-03-25 09:14:55 CST. --
Mar 25 11:02:27 test-server-1 nginx[14144]: nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
Mar 25 11:02:27 test-server-1 systemd[1]: PID file /run/nginx.pid not readable (yet?) after start.
Mar 25 11:04:29 test-server-1 systemd[1]: nginx.service start operation timed out. Terminating.
Mar 25 11:04:29 test-server-1 systemd[1]: Failed to start nginx.
Mar 25 11:04:29 test-server-1 systemd[1]: Unit nginx.service entered failed state.
Mar 25 11:04:29 test-server-1 systemd[1]: nginx.service failed.複製程式碼

從字面看是PID檔案不可讀,檢視/var/run/nginx.pid,該檔案也確實不存在,檢視nginx.conf配置檔案,發現是pid /var/run/nginx.pid;這行配置被註釋掉了, 如果不指定pid檔案位置,nginx預設會把pid檔案儲存在logs目錄中。所以出現systemd啟動服務時找不到pid檔案而報錯,將nginx.conf中的pid配置註釋去掉,重啟nginx.service即可。

Ubuntu18.04的開機自啟動配置

在Ubuntu18.04中,主要也是以systemd服務來實現開機自啟動,systemd預設讀取/etc/systemd/system/下的配置檔案,該目錄下的一些檔案會連結到/lib/systemd/system/下的檔案。

因此可以在/etc/systemd/system/目錄下面建立一個自啟動服務配置,以內網穿透服務frp客戶端為例,如

[Unit]
Description=frpc
After=network.target
Wants=network.target

[Service]
TimeoutStartSec=30
ExecStart=/home/devuser/apps/frp/frpc -c /home/devuser/apps/frp/frpc.ini
ExecStop=/bin/kill $MAINPID
Restart=1

[Install]
WantedBy=multi-user.target複製程式碼

各配置項與CentOS類似。然後將伺服器加到自啟動列表中並啟動服務

$sudo systemctl enable frpc
$sudo systemctl start frpc複製程式碼

其它更多systemctl命令與CentOS類似。

也可以使用/lib/systemd/system/rc-local.service來執行一些開機需要執行的指令碼,該檔案內容為

#  SPDX-License-Identifier: LGPL-2.1+
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

# This unit gets pulled automatically into multi-user.target by
# systemd-rc-local-generator if /etc/rc.local is executable.
[Unit]
Description=/etc/rc.local Compatibility
Documentation=man:systemd-rc-local-generator(8)
ConditionFileIsExecutable=/etc/rc.local
After=network.target

[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0
RemainAfterExit=yes
GuessMainPID=no複製程式碼

從Description看它是為了相容之前版本的/etc/rc.local的,該服務啟動命名就是/etc/rc.local start,將該檔案連結到/etc/systemd/system下

$ sudo ln -s /lib/systemd/system/rc-local.service /etc/systemd/system/rc-local.service  複製程式碼

建立/etc/rc.local檔案,並賦予可執行許可權

$ vim /etc/rc.local
#!/bin/bash  
echo "test rc " > /var/test.log  

$ sudo chmod +x /etc/rc.local複製程式碼

<>

作者:空山新雨,一枚仍在學習路上的IT老兵 近期作者寫了幾十篇技術部落格,內容包括Java、Spring Boot、Spring Cloud、Docker,技術管理心得等
歡迎關注作者微信公眾號:空山新雨的技術空間,一起學習成長

微信公眾號

相關文章