【systemd】使用systemctl管理守护进程详细教程

TangLu 运维 2019-07-15 16634 0

一、systemd介绍

systemd是目前Linux系统上主要的系统守护进程管理工具,由于init一方面对于进程的管理是串行化的,容易出现阻塞情况,另一方面init也仅仅是执行启动脚本,并不能对服务本身进行更多的管理。所以从CentOS 7开始也由systemd取代了init作为默认的系统进程管理工具。

systemd所管理的所有系统资源都称作Unit,通过systemd命令集可以方便的对这些Unit进行管理。比如systemctl、hostnamectl、timedatectl、localctl等命令,这些命令虽然改写了init时代用户的命令使用习惯,比如不再使用chkconfig、service等命令对服务进行管理,但确实也提供了更多的便捷性,所以非常值得学习和使用。


二、systemctl命令格式

systemctl [command] [unit]

# command可选项:
# start:启动指定的unit
# stop:关闭指定的unit
# restart:重启指定unit
# reload:重载指定unit
# enable:系统开机时自动启动指定unit,前提是配置文件中有相关配置
# disable:开机时不自动运行指定unit
# status:查看指定unit当前运行状态

# unit:配置的应用名称

三、systemd配置文件说明

· 每一个Unit都需要有一个配置文件用于告知systemd对于服务的管理方式

· 配置文件存放于/usr/lib/systemd/system/,设置开机启动后会在/etc/systemd/system目录建立软链接文件

· 每个Unit的配置文件配置默认后缀名为.service

· /usr/lib/systemd/system/目录中分为system和user两个目录,一般将开机不登陆就能运行的程序存在系统服务里,也就是/usr/lib/systemd/system

· 配置文件使用方括号分成了多个部分,并且区分大小写


四、systemctl命令示例

· systemctl status命令,查看指定Unit状态

sysystemctl status httpd.service  #显示单个Unit状态
systemctl is-active application.service  #显示某个Unit是否正在运行
systemctl is-enabled application.service  #显示某个Unit是否开机自启


· systemctl list-units命令,查看系统中Unit信息

systemctl list-units  #列出正在运行的Unit
systemctl list-units --all #列出所有Unit,包括缺失配置文件或启动失败的
systemctl list-units --all --state=inactive #列出所有没有运行的Unit
systemctl list-units --failed  #列出所有加载失败的Unit
systemctl list-units --type=service  #列出所有正在运行的类型为service的Unit


· systemctl启停service命令

systemctl start apache.service  #启动一个服务
systemctl stop apache.service  #停止一个服务
systemctl kill apache.service  #如果服务无法正常停止则使用kill方式终止
systemctl restart apache.service  #重启指定服务
systemctl reload apache.service  #重新加载指定服务的配置
systemctl daemon-reload  #重新加载所有被修改过的服务配置,否则配置不会生效


· systemctl list-dependencies命令,查看Unit依赖关系,比如A依赖于B则代表Systemd在启动A的时候同时会启动 B

systemctl list-dependencies nginx.service


· systemctl list-unit-filis命令,用于列出Unit配置文件与启用状态。STATE分为了enabled(已建立开机启动软链接)、disabled(没有建立开机启动)、static(该配置文件没有[Install]部分所以无法启动,只能作为其它Unit的依赖文件)、masked(禁止建立启动软链接文件)四种状态。

systemctl list-unit-files  #列出所有配置文件
systemctl list-unit-files --type=service  #列出指定类型的配置文件
# 命令结果
UNIT FILE              STATE
chronyd.service        enabled
clamd@.service         static clamd@scan.service     disabled


五、systemd配置文件详解以sshd服务为例)

systemctl1.png



[Unit]:通常是第一个区块,定义Unit元数据信息以及与其他服务的依赖关系

· Description:服务描述信息
· Documentation:服务文档地址

· Before:如果该字段指定了其它Unit则代表该Unit需要在其它Unit启动之前启动,但是没有严格的依赖关系
· After:如果该字段有指定了其它Unit则代表该Unit需要在其它Unit启动之后才能启动,但是没有严格的依赖关系
· Wants:与当前Unit配合的其他Unit,如果需要配合的Unit没有运行,当前Unit也能正常启动

· Requires:为当前Unit指定一个强依赖关系,如果该配置项所指定的Unit没有运行,则当前Unit无法启动。
· BindsTo:与Requires类似,如果指定的Unit发生退出,则当前Unit也会停止运行
· Conflicts:指定冲突Unit,这里指定的Unit不能与当前Unit同时运行
· Condition:当前Unit运行必须满足的条件,否则不会运行


关于Requires、After、Conflicts依赖的说明:

如果没有配置DefaultDependencies=no,那么该Unit会自动隐式添加Requires=sysinit.target, After=sysinit.target,After=basic.target, Conflicts=shutdown.target, Before=shutdown.target的依赖关系。这样是为了保证普通Unit在系统启动完毕之后才能启动、在关闭系统之前先被停止,只有需要在系统启动早期就必须启动的服务以及那些必须在关机动作的结尾才能停止的服务才需要设置DefaultDependencies=no。 


[Service]:如果Unit类型为Service,则通过该区域进行详细配置,如服务启动脚本、环境变量、配置文件名、重启方式等

· Type=simple:默认值,直接执行ExecStart选项所指定的命令
· Type=forking:多数服务会在启动后放入后台,systemd通过Type=forking来支持这种工作方式。如果启用该项,建议同时设置PIDFile选项,这样可以帮助systemd更准确的定位到服务进程

· Type=notify确保服务启动后发送一个通知消息给systemd,systemd会在启动后面的服务之前确保该进程已经成功的发送了这个消息
· Type=idle:若同时有其他任务在执行,需要等那些任务完成后才对当前服务进行处理

· PIDFile:配置Unit的PID文件路径,systemd将会在服务启动后从该文件中读取进程PID。建议Type=forking时明确配置该选项。如果设为相对路径表示相对于/run/目录。
· ExecStart:启动某个服务的具体命令,如果有变量的话则来自Environment所指定的配置文件,在所有的启动命令(Exec开头的命令)设置之前都可以加上一个连词号(-),表示抑制错误,即发生错误的时候不影响其他命令的执行。比如EnvironmentFile=-/etc/sysconfig/sshd表示即使/etc/sysconfig/sshd文件不存在,也不会抛出错误。
· ExecStartPre:启动某个服务之前执行的命令
· ExecStartPost:启动某个服务之后执行的命令
· ExecReload:重启服务时执行的命令,Unit需要重新载入配置时所执行的命令行,可通过kill命令结合一个环境变量$MAINPID来完成,如/bin/kill -HUP $MAINPID。如果服务有特定的重启命令,建议不要使用kill的方式
· ExecStop:停止服务时执行的命令,如果没有指定的话则会按照kill的方式终止
· ExecStopPost:服务停止之后需要执行的命令
· RestartSec:自动重启当前服务间隔的秒数,如RestartSec=20s代表systemd自动重启之前需要等20秒。
· Restart:定义Systemd自动重启当前服务的场景,比如always(除了使用命令systemctl stop停止服务,其他情况下都进行重启)、on-success、on-failure(发生意外退出就重启。如果是systemctl stop这种正常停止则不会重启)、on-abnormal、on-abort、on-watchdog

· RestartPreventExitStatus:指定Unit在什么情况下的退出不需要自动重启,该参数的值支持exit状态码以及信号名2种写法,多个状态以空格分隔

· TimeoutSec:定义Systemd停止当前服务时需要等待的秒数
· Environment:指定Unit所需的环境变量,如Environment="ONE=one",ExecStart=echo $ONE

· EnvironmentFile:指定Unit所需的环境变量配置文件,如ssh需要/etc/sysconfig/sshd


[Install]:通常是配置文件最后一个区块,定义服务如何启动以及是否开机启动

· WantedBy:指定一个或多个Target(Target就是Unit组,启动某个Target的时候会启动里面所有的Unit,它的作用有点类似init的runlevel),如WantedBy=multi-user.target代表服务所在的 Target是multi-user.target(多用户命令行状态专用Target,也是systemd默认Target)。这个设置比较重要,因为对某个Unit执行enable时,该Unit的软链接就会存放于/etc/systemd/system/multi-user.target.wants目录中(以Target名+.wants后缀构成)

· RequiredBy指定一个或多个Target,当Unit状态为enable时,服务的软连接文件会创建到/etc/systemd/system目录下面并以Target 名+.required后缀构成的子目录中
· Alias:Unit别名
· Also:当Unit设置为enable时,会被同时enable的其他Unit


六、systemd日志

Systemd使用journalctl命令管理了所有Unit日志以及内核日志

journalctl -k  # 查看内核日志(不显示应用日志)
journalctl -b  # 查看系统本次启动的日志

# 查看指定时间的日志
journalctl --since="2012-10-30 18:17:16"
journalctl --since "20 min ago"
journalctl --since yesterday
journalctl --since "2015-01-10" --until "2015-01-11 03:00"
journalctl --since 09:00 --until "1 hour ago"

journalctl -n  #显示尾部的最新10行日志
journalctl -n 20  #显示尾部指定行数的日志
journalctl -f  #实时滚动显示最新日志

journalctl /usr/lib/systemd/systemd  # 查看指定服务的日志

journalctl /usr/bin/bash  #查看某个路径的脚本的日志

journalctl -u nginx.service -f  #实时滚动查看Unit日志

$ sudo journalctl -b -u nginx.serviceqq
 -o json-pretty  #以JSON 格式(多行)输出,可读性更好


七、添加自定义systemd启动脚本

要自定义一个systemd脚本最便捷的方式就是复制一份已有的脚本进行修改,最后执行systemctl daemon-reload即可管理服务。

[Unit]
Description=Redis Sentinel
After=syslog.target network.target remote-fs.target nss-lookup.target
Wants=redis.service

[Service]
Type=forking
ExecStart=/data/redis/bin/redis-sentinel  /data/redis/etc/redis_sentinel.conf 
ExecStop=/data/redis/bin/redis-cli -p ${REDIS_PORT} -h ${REDIS_IP} -a ${REDIS_PASS} shutdown 
Restart=always
RestartSec=30s
Environment=REDIS_PASS=123456
Environment=REDIS_PORT=26379
Environment=REDIS_IP=172.22.8.81

[Install]
WantedBy=multi-user.target



评论