centos7 systemctl配置开机自启动服务

centos7使用systemctl替代原来/etc/init.d,按官方的说法是提高系统服务的运行效率、服务配置更加简单易用,对于一些自定义的服务来配置开机自启动,是真的香!

1. 概念理解

  • 它是服务管理工具,融合之前service和chkconfig功能于一体
  • 有系统(system)和用户(user)之分,系统(/usr/lib/systemd/system/)、用户(/etc/lib/systemd/user/)
  • 以.service结尾,一般分为3部分:Unit、Service、Install

2. 参数说明

2.1 [Unit]

主要对服务的说明

  • Description:用于描述服务而已
  • Documentation : 服务文档
  • Before、After:定义启动顺序。Before=xxx.service,代表本服务在xxx.service启动之前启动。After=xxx.service,代表本服务在xxx.service之后启动。
  • Requires:这个单元启动了,它需要的单元也会被启动;它需要的单元被停止了,这个单元也停止了。
  • Wants:推荐使用。这个单元启动了,它需要的单元也会被启动;它需要的单元被停止了,对本单元没有影响。

2.2 [Service]

关键部分,服务运行的具体配置

参数太多,下面只列出几个常用的关键参数,其它根据需要自行百度:
常用Type的几种类型:

Type=simple

systemd认为该服务将立即启动。服务进程不会fork。如果该服务要启动其他服务,不要使用此类型启动,除非该服务是socket激活型。

Type=forking

systemd认为当该服务进程fork,且父进程退出后服务启动成功。对于常规的守护进程(daemon),除非你确定此启动方式无法满足需求,使用此类型启动即可。使用此启动类型应同时指定 PIDFile=,以便systemd能够跟踪服务的主进程。

Type=notify

与 Type=simple 相同,但约定服务会在就绪后向 systemd 发送一个信号。这一通知的实现由 libsystemd-daemon.so 提供。

Type=oneshot

这一选项适用于只执行一项任务、随后立即退出的服务。可能需要同时设置 RemainAfterExit=yes 使得 systemd 在服务进程退出之后仍然认为服务处于激活状态。

Type=idle

systemd会等待所有任务(Jobs)处理完成后,才开始执行idle类型的单元。除此之外,其他行为和Type=simple 类似。

Type=dbus

若以此方式启动,当指定的 BusName 出现在DBus系统总线上时,systemd认为服务就绪。

  • User:是设置服务运行的用户
  • Group:是设置服务运行的用户组
  • PIDFile:为存放PID的文件路径
  • ExecStart:指定启动单元的命令或者脚本,ExecStartPre和ExecStartPost节指定在ExecStart之前或者之后用户自定义执行的脚本。Type=oneshot允许指定多个希望顺序执行的用户自定义命令。
  • ExecReload:指定单元停止时执行的命令或者脚本。
  • ExecStop:指定单元停止时执行的命令或者脚本。
  • Restart:这个选项如果被允许,服务重启的时候进程会退出,会通过systemctl命令执行清除并重启的操作
  • Environment:指定环境变量
  • PrivateTmp:True表示给服务分配独立的临时空间
  • RemainAfterExit:如果设置这个选择为真,服务会被认为是在激活状态,即使所以的进程已经退出,默认的值为假,这个选项只有在Type=oneshot时需要被配置。

注意:所有命令要求使用绝对路径,使用相对路径会报错。

2.3 [Install]

服务安装的相关设置,用来定义启动以及是否开机启动

  • Alias:为单元提供一个空间分离的附加名字。
  • RequiredBy:单元被允许运行需要的一系列依赖单元,RequiredBy列表从Require获得依赖信息。
  • WantedBy:单元被允许运行需要的弱依赖性单元,Wantby从Want列表获得依赖信息。
  • Also:指出和单元一起安装或者被协助的单元。
  • DefaultInstance:实例单元的限制,这个选项指定如果单元被允许运行默认的实例。

3. 常用命令

## 启动服务
systemctl start nginx.service
  
## 停止服务
systemctl stop nginx.service
  
## 重启服务
service nginx restart
systemctl restart nginx.service
  
## 服务自启动
systemctl enable nginx.service
  
## 服务关闭自动启动
systemctl disable nginx.service
  
## 检查服务状态
systemctl status nginx.service
  
## 显示所有已启动的服务
systemctl list-units  --type=service

4. 使用案例

nginx

[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=mixed
PrivateTmp=true

[Install]
WantedBy=multi-user.target
  • 添加可执行权限:
chmod +x /usr/lib/systemd/system/nginx.service
systemctl daemon-reload

java

xxl-job

[Unit]
Description=xxl-job
Documentation=http://xxl-job

[Service]
User=root
Group=root
Type=simple
Restart=no
KillMode=process
ExecStart=/home/ces/xxl-job/app.sh start
ExecStop=/home/ces/xxl-job/app.sh stop
ExecReload=/home/ces/xxl-job/app.sh restart
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

nacos 自启动

[Unit]
Description=nacos
After=network.target

[Service]
Type=forking
Environment="JAVA_HOME=/usr/local/jdk1.8" #改成自己的jdk路径,因为服务脚本的环境和系统环境变量不能共享,所以还得设置才能生效。
ExecStart=/home/nacos/nacos/bin/startup.sh -m standalone #standalone 是单机,默认是集群cluster
ExecReload=/home/nacos/nacos/bin/shutdown.sh
ExecStop=/home/nacos/nacos/bin/shutdown.sh
PrivateTmp=true

[Install]
WantedBy=multi-user.target

问题 Executable path is not absolute

https://stackoverflow.com/questions/48684468/executable-path-is-not-absolute-ignoring-which-node

# auth wmh
# time 2019/1/3
 
[Unit]
Description=brill_lab
After=multi-user.target
 
[Service]
Type=forking
AmbientCapabilities=CAP_SYS_RAWIO
ExecStart=/bin/bash -c 'nohup java -jar /home/brill_lab/brill_lab_starter-1.0.0-SNAPSHOT.jar & echo $! > /home/brill_lab/brill_lab.pid'
ExecStop=/bin/bash -c 'kill \'cat /home/brill_lab/brill_lab.pid\''
 
[Install]
WantedBy=multi-user.target

注意:systemd 不接受非绝对路径执行命令,需要依赖bush-ism,如下

/bin/bash -c ‘nohup java -jar /home/brill_lab/brill_lab_starter-1.0.0-SNAPSHOT.jar & echo $! > /home/brill_lab/brill_lab.pid’

否则会出现 Executable path is not absolute 的问题 (systemctl status brillilab.service 中)

mqbroker

[Unit]
Description=mqbroker
After=network.target

[Service]
Type=forking
Environment="JAVA_HOME=/usr/local/jdk"
ExecStart=/bin/bash -c 'nohup /home/software/rocketmq-5.1.3/bin/mqbroker -c /home/software/rocketmq-5.1.3/conf/broker.conf > /dev/null 2>&1 &'
#ExecReload=/home/nacos/nacos/bin/shutdown.sh
ExecStop=/home/software/rocketmq-5.1.3/bin/mqshutdown broker
PrivateTmp=true

[Install]
WantedBy=multi-user.target