探寻一下systemd服务

794 阅读6分钟

centos 7系统中,使用的是systemd作为默认的初始化系统,同时也包括了启动和管理系统服务

整理一下,systemd承担了2个角色:

  • 初始化系统(Init System):systemd将是centos 7默认的初始化系统,主要负责引导操作系统,取代了此前的SysV init(centos 5以及centos 6使用SysV Init初始化系统)。

  • 服务管理:systemd也负责管理系统服务,包括启动、停止、重启、查看等,这些可以使用systemctl来进行上述操作。

首先来介绍一下systemd作为默认的初始化系统。

systemd 初始化系统

这里只是提及一下systemd Init System

systemd初始化是在centos 7机器启动中,内核初始化后再进行的systemd初始化,这里可以使用dmesg命令查看详细的启动过程。

centos 7系统中,使用pstree可以看到当前系统中的进程树,命令如下:

# yum install psmisc -y
# pstree

其中,pstree是在软件包psmisc中,所依赖的源为base,若直接使用pstree发现没有该命令的时候,需要先安装一下psmisc

命令直接结果如下:

可以看到systemd是整个初始化进程树的根,所以,它的pid应当为1,可以使用如下命令来校验一下:

# ps -fp 1

其结果如下:

关于systemd初始化系统就介绍到这里,下面将介绍一下system所管理的服务了。

systemd 管理服务

centos 5centos 6系统中,使用的都是Sys Vinit脚本程序来启动各种服务,例如,所有的启动脚本都放到/etc/init.d下,启动服务的时候,需要执行各种命令,如: chkconfigservice等等。

但是在centos 7中,使用了systemd来管理各种服务,其管理服务优点如下:

  • 并行启动服务,加快开机流程。
  • systemd所管理的服务仅需要systemctl来调用即可,无需其他额外的命令。
  • 按照服务单位unit分类,方便管理和查看。
  • 服务依赖自启动,避免手动启动依赖。

systemd配置目录

使用systemd管理的服务主要存放以下三个目录,分别为:

  • /usr/lib/systemd/system: 每个服务的启动脚本。

  • /run/systemd/system: 用于存储服务启动过程中临时创建的systemd相关信息。

  • /etc/systemd/system/: 该目录是systemd单元文件的默认目录。

其优先级为:/etc/systemd/system/ —> /run/systemd/system —> /usr/lib/systemd/system

systemd服务分类

systemd管理中心,一个服务单位,通常称之为unitunit有专门的类型,正如上面介绍systemd优点所述,按照unit分类,可以方便查看和管理服务。

unit服务分类主要如下:

  • service:

一般类型服务,是最常见的类型。

  • target:

unit集合,例如:/etc/systemd/system/multi-user.target.wants记录的是一堆unit集合,用于开机自启动。

  • socket:

IPC通信服务。例如有些服务不经常启动,可以使用socket unit,它会先创建socket套接字,而不会启动后面的真实服务(daemon),当客户端请求该服务的时候,再由systemd启动该服务再将请求打到真实的服务上去。

  • mount:

文件系统的挂载点。

  • automount:

文件系统自动挂载点。

  • timer:

循环运行的服务。和crontanb类似,不过是由systemd提供并且维护运行的。

systemctl 常用的命令

systemctl是一个命令行工具,是用于管理systemd服务的,可以使用systemctl来启动、重启、停用以及查看系统服务的状态。

启动服务

systemctl start 服务名称

停止服务

systemctl start 服务名称

重启服务

systemctl restart 服务名称

查看服务状态

systemctl status 服务名称

设置服务开机自启

systemctl enable 服务名称

禁用服务开机自启

systemctl disable 服务名称

重新加载配置文件

systemctl daemon-reload

查看当前系统正在运行的服务

systemctl list-units --type=service

比如,将yum安装的nginx启动起来,并且设置为开机自启,可以使用如下命令来设置:

# systemctl start nginx
# systemctl enable nginx

命令执行结果如下:

在设置nginx开机自启的时候,会出现这样的一条日志:

Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.

在设置nginx开机后,就将该服务加入到了/etc/systemd/system/multi-user.target.wants/目录下,该目录包含了一系列unitmulti-user.targetsystemd中的一个运行级别,对应的运行级别是3。即多用户运行模式,当在该目录下,系统启动后,会执行该target

自己编写一个systemd服务

首先编写一个毫无意义的一段shell脚本,其脚本名称为:/root/testSystem.sh,内容如下:

#!/bin/bash

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/go/bin/:/root/go/bin/:/root/bin
export PATH

while true
do
        nowtime=$(date +"%F %T")

        echo "set key '$nowtime'"
        echo "set key '$nowtime'" | redis-cli

        echo "get key"
        echo "get key" | redis-cli

        sleep 10
done

这段脚本的作用是建立一个无限循环,而后再循环中定义一个变量nowtime,该变量的值是当前系统时间,而后将该值存入到redis中,完毕后再使用get获取其值。

手动运行脚本,效果如下:

当然前提我们需要使用yum安装一个redis服务在当前主机上。

而后再来编写systemd服务,服务的存放目录是在: /usr/lib/systemd/system 下,我们可以新建一个文件,名称是testSystem.service

除此之外,我们还需要写一个启动脚本和停止脚本,其名称为:/root/startTestSystem.sh,脚本内容如下:

#!/bin/bash

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/go/bin/:/root/go/bin/:/root/bin
export PATH

cd /root/

nohup bash testSystem.sh >> /root/testSystem.log &

该脚本运行后,会在后台启动/root/testSystem.sh脚本。

停止脚本名称:/root/stopTestSystem.sh,内容如下:

#!/bin/bash

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/go/bin/:/root/go/bin/:/root/bin
export PATH

pidCount=$(ps aux | grep testSystem.sh | grep -v grep | wc -l)

if [ 0 -eq $pidCount ];then
        echo "no killed"
else
        kill -9 $(ps aux | grep testSystem.sh | grep -v grep | awk '{print $2}')
fi

最后再来编写systemd service服务,我们新建文件:/usr/lib/systemd/system/testSystem.service,其内容如下:

[Unit]
Description=a bash test

[Service]
Type=forking
ExecStart=/usr/bin/bash /root/startTestSystem.sh
ExecStop=/usr/bin/bash /root/stopTestSystem.sh 

[Install]
WantedBy=multi-user.target

service的主要有三段组成,分别是:[Unit][Service]以及Install

其中:

  • Unit: 服务本身的说明,可以设置依赖关系,服务启动顺序等。
  • Service: 这是服务器本身,定义的是启动方式、启动和停止脚本定义。
  • Install:这里定义的是该脚本定义到哪个target去。

定义后,使用systemctl daemon-reload重新加载一下配置,而后就可以使用systemctl start testSystem.servic启动该服务了。

当然,上面的服务是强度依赖于redis的,如果redis也是使用systemd启动的话,可以修改service来增加一个依赖,当启动testSystem的时候,若redis未启动,会先启动redis,而后再启动testSystem,systemd服务修改如下:

[Unit]
Description=a bash test
Requires=redis.service

[Service]
Type=forking
ExecStart=/usr/bin/bash /root/startTestSystem.sh
ExecStop=/usr/bin/bash /root/stopTestSystem.sh 

[Install]
WantedBy=multi-user.target

上面的改动仅一点,就是在Unit下增加了一个Requires,值为: redis.service,这样当启动testSystem的时候,若发现redis未启动,会先启动redis,而后再启动testSystem的。

总结

systemd非常复杂,主要表示在2方面:

    1. 会进行初始化系统,
    1. 管理机器的各个服务。

不过一般维护使用不会涉及到初始化系统操作,而更多的使用是管理各项服务。

包括我们从yum安装各种包体,以及自己编写的服务,此外,systemd更好是管理服务器程序,而非用户自定义程序。

systemd中,由于各种服务很多,所有拆分为了以扩展名来定义的服务,比如:以service结尾的服务为一般服务,也是用的最多的服务,以timer结尾的服务,是定时服务,很少使用。

在每项服务中,又可以定义服务的依赖以及启动先后顺序等。目前本章只是简单的使用了service而已。