很多时候,我们需要将一些服务在Linux系统启动时即自动运行,省得每次都要去手动启动一遍,如Redis, MySQL, Nginx等。本文对CentOS与Ubuntu下开机自启动的配置方法进行整理,供参考查阅。

CentOS7的开机自启动配置

一. rc.local方式

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

  1. 编写需要开机自启动的脚本,并添加执行权限
1
2
3
4
5
6
7
[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文件中

  1. 在/etc/rc.d/rc.local配置文件中添加脚本运行命令(使用绝对路径)
1
2
3
4
5
6
7
[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
  1. 添加/etc/rc.d/rc.local文件的执行权限

在centos7中,/etc/rc.d/rc.local没有执行权限,需要手动授权

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

以上三步,即可使/root/test_rclocal.sh >/dev/null 2>/dev/null 命令在服务器系统启动时自动运行。

二. chkconfig方式

  1. 编写需要开机自启动的测试脚本,并添加执行权限
1
2
3
4
5
6
7
8
[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
  1. 在/etc/rc.d/init.d/目录下添加一个可执行脚本testchkconfig
1
2
3
4
5
6
7
8
9
[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:重新启动
  1. 加入开机启动服务列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[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的其它命令参考

1
2
3
4
5
$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文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[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名称。
  1. 开启开机自启动
1
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服务配置成了在操作系统启动时自动启动。

其它命令参考

1
2
3
4
5
6
7
8
9
10
11
12
13
$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.的错误,启动失败,日志如下

1
2
3
4
5
6
7
8
[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客户端为例,如

1
2
3
4
5
6
7
8
9
10
11
12
13
[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类似。然后将服务器加到自启动列表中并启动服务

1
2
$sudo systemctl enable frpc
$sudo systemctl start frpc

其它更多systemctl命令与CentOS类似。

也可以使用/lib/systemd/system/rc-local.service来执行一些开机需要执行的脚本,该文件内容为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#  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下

1
$ sudo ln -s /lib/systemd/system/rc-local.service /etc/systemd/system/rc-local.service

创建/etc/rc.local文件,并赋予可执行权限

1
2
3
4
5
$ vim /etc/rc.local
#!/bin/bash
echo "test rc " > /var/test.log

$ sudo chmod +x /etc/rc.local

<>

欢迎关注作者微信公众号:空山新雨的技术空间,查看更多关于Java、Spring Boot、Spring Cloud、Docker等技术实践文章

微信公众号

评论