一、Service服务配置文件详解
1.1 服务配置文件路径
对于那些支持Systemd的应用,安装的时候,会自动在/usr/lib/systemd/system
目录中添加一个以.service
后缀结尾的配置文件,这种情况常见于使用apt、yum软件仓库安装,或者通过软件官方提供的deb、rpm包安装的应用
如果是通过源码或或二进制方式安装的应用,需要用户自行在/usr/lib/systemd/system
目录中添加一个以.service
后缀结尾的配置文件,配置文件内容需要遵循一定的格式和定义
如果想要实现应用服务开机自动启动,需要执行systemctl enable server_name
,此时Linux会在/etc/systemd/system
目录下新增一个链接符号文件,目标路径指向/usr/lib/systemd/systemd
中的service文件
1.2 Systemd管理服务的常用命令
- 当新增/修改服务配置文件后,需载入配置信息,使其注册生效
systemctl daemon-reload
- 启动服务
systemctl start service_name
- 停止服务
systemctl stop service_name
- kill服务
# 有时候服务停止没有响应,服务停不下来,这时候就需要将进程kill掉了
systemctl kill service_name
- 重启服务
systemctl restart service_name
- 设置服务开机自启动
systemctl enable service_name
# 设置开机自启动,并启动服务
systemctl enable service_name
- 取消服务开机自启动
systemctl disable service_name
- 查看服务的配置文件
systemctl cat service_name
- 获取默认target
systemctl get-default
- 设置默认target
systemctl set-default <target>
1.3 服务配置文件的组成
以sshd的服务配置文件为例,其服务配置文件位于/usr/lib/systemd/system/sshd.service
[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.target
Wants=sshd-keygen.target
[Service]
Type=notify
EnvironmentFile=-/etc/crypto-policies/back-ends/opensshserver.config
EnvironmentFile=-/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS $CRYPTO_POLICY
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=multi-user.target
可以看出,配置文件主要由3部分组成,分别是[Unit]
、[Service]
、[Install]
- [Unit]区块:启动顺序与依赖关系
- [Service]区块:启动行为
- [Install]区块:定义如何安装这个配置文件,即怎样做到开机启动
1.3.1 Unit区块
Unit区块主要包括Description
、Documentation
、After
、Wants
等控制参数
(1)Description
当前服务的简单描述信息
(2)Documentation
指定服务相关说明文档存放路径
(3)启动顺序(After、Before)
After
和Before
参数定义的启动顺序主要是在系统启动(开机)时服务初始化的顺序>。它确保某些服务在其他服务启动完成后或启动完成前启动,从而保证系统的稳定性和依赖关系的正确处理
- After
表示如果network.target
或sshd-keygen.target
需要启动,那么sshd.service
应该在它们之后启动 - Before
Before和After相反,表示应该在哪些服务之前启动
注意,After和Before字段只涉及启动顺序,不涉及依赖关系。
举例,某Web应用需要MySQL数据库储存数据。在配置文件中,它只定义要在MySQL之后启动,而没有定义依赖MySQL。上线后,由于某种原因,MySQL需要重新启动,在停止服务期间,该Web应用就会无法建立数据库
(4)设置依赖关系(Wants、Requires)
- Wants
表示sshd.service
和sshd-keygen.service
之间存在“弱依赖”关系,即如果sshd-keygen.service
启动失败或停止运行,不影响sshd.service
继续执行。Wants
表示一种弱依赖关系。它表示当前单元希望另一个单元也被启动,但如果另一个单元未能启动,当前单元仍然可以启动。常用于非关键性依赖关系
。 - Requires
表示“强依赖”关系,即如果sshd-keygen.service
服务启动失败或异常退出,那么sshd.service
也会启动失败或停止启动。Requires
表示一种强依赖关系。它表示当前单元依赖于另一个单元,如果另一个单元未能启动或失败,当前单元也会失败并停止启动。常用于关键性依赖关系
。
注意,
Wants
和Requires
字段只涉及依赖关系,与启动顺序无关,默认情况下是同时启动的
- 结合使用
有时需要同时使用Wants
或Requires
与After
来确保启动顺序和依赖关系。
示例:
[Unit]
Description=My Service
Requires=network.service
After=network.service
[Service]
ExecStart=/usr/bin/my-service
[Install]
WantedBy=multi-user.target
在这个示例中:
Requires=network.service
确保network.service
必须成功启动,否则my-service.service
不会启动。After=network.service
确保my-service.service
在network.service
启动完成后再启动。总结:-Wants
: 弱依赖关系,表示希望另一个单元启动,但不强制要求。Requires
: 强依赖关系,表示必须依赖另一个单元,如果另一个单元未能启动,当前单元也不会启动。通过合理使用Wants
和Requires
,可以精细控制systemd
单元的启动顺序和依赖关系,确保系统服务按预期运行。
1.3.2 Service区块
Service
区块定义了如何启动当前服务,常用的字段有Type
、EnvironmentFile
、ExecStart
、ExecStop
、ExecReload
等
(1)服务类型
- Type
Type字段定义了服务启动类型,它可以设置的值如下:- simple(默认值):服务启动时,进程为主进程
适用于不会自行后台运行的长时间运行的服务。这是最简单的配置,通常用于不需要复杂启动过程的应用程序 - forking:服务采用
fork()
方式启动,此时父进程将会退出,子进程将成为主进程
适用于那些自行生成子进程并退出父进程的服务(即守护进程)。例如,传统的 Apache HTTP 服务器就是一个典型的forking
类型服务
示例:
[Unit] Description=Legacy Apache HTTP Server [Service] Type=forking ExecStart=/usr/sbin/httpd -k start ExecStop=/usr/sbin/httpd -k stop [Install] WantedBy=multi-user.target
- oneshot:类似
simple
,但只执行一次,执行完后服务退出
此类型用于一次性任务和脚本,服务启动后执行一次然后退出。适用于需要执行一次性任务(如初始化任务)的场景。通常与RemainAfterExit=yes
结合使用,使服务在任务完成后仍被视为活动
例如:笔记本电脑启动时,要把触摸板关掉,这种服务只需运行一次即可,不需要长期运行。配置可以这么写:
[Unit] Description=Switch-off Touchpad [Service] Type=oneshot ExecStart=/usr/bin/touchpad-off [Install] WantedBy=multi-user.target
上面的配置文件,启动类型设为
oneshot
,表示这个服务只需要运行一次就可以,不需要长期运行
如果想要达到服务关闭后,将来某个时候还想重新打开,配置文件修改如下:[Unit] Description=Switch-off Touchpad [Service] Type=oneshot ExecStart=/usr/bin/touchpad-off start ExecStop=/usr/bin/touchpad-off stop RemainAfterExit=yes [Install] WantedBy=multi-user.target
RemainAfterExit
字段设置为yes,表示进程退出以后,服务仍然保持执行。这样的做法是,一旦使用systemctl stop
命令停止服务,ExecStop
指定的命令就会执行,从而重新开启触摸板- dbus:类似
simple
,但会等待D-Bus信号后才启动
服务启动后,systemd
等待 D-Bus 服务在 D-Bus 总线上注册自己,然后认为服务已激活。适用于提供 D-Bus 服务的应用程序,如 GNOME 的各种组件。
常见的采用dbus方式启动的服务有NetworkManager
、Avahi Daemon
、Bluetooth service (bluetoothd)
、ModemManager
以下是NetworkManger的服务配置文件:
[Unit] Description=Network Manager Documentation=man:NetworkManager(8) Wants=network.target After=network-pre.target dbus.service Before=network.target network.service [Service] Type=dbus BusName=org.freedesktop.NetworkManager ExecReload=/usr/bin/busctl call org.freedesktop.NetworkManager /org/freedesktop/NetworkManager org.freedesktop.NetworkManager Reload u 0 ExecStart=/usr/sbin/NetworkManager --no-daemon Restart=on-failure KillMode=process CapabilityBoundingSet=CAP_NET_ADMIN CAP_DAC_OVERRIDE CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_MODULE CAP_AUDIT_WRITE CAP_KILL CAP_SYS_CHROOT ProtectSystem=true ProtectHome=read-only LimitNOFILE=65536 [Install] WantedBy=multi-user.target Also=NetworkManager-dispatcher.service Also=NetworkManager-wait-online.service
- notify:类似
simple
,启动结束后会发出通知信号,然后Systemd再启动其他服务
适用于需要精确控制启动过程,且能够发送通知的现代服务。这允许服务在完全初始化并准备好接受请求之前,不会被认为是活动的
常见使用notify方式启动的服务有docker
、journald(Systemd的日志服务)
、postsql
等
以docker为例,其Systemd配置文件内容如下:
[Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com After=network-online.target docker.socket firewalld.service containerd.service time-set.target Wants=network-online.target containerd.service Requires=docker.socket [Service] Type=notify ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ExecReload=/bin/kill -s HUP $MAINPID TimeoutStartSec=0 RestartSec=2 Restart=always StartLimitBurst=3 StartLimitInterval=60s LimitNPROC=infinity LimitCORE=infinity TasksMax=infinity Delegate=yes KillMode=process OOMScoreAdjust=-500 [Install] WantedBy=multi-user.target
- idle:类似
simple
,但是要等他其他任务都执行完,才会启动该服务。
主要使用场景是为该服务的输出,不与其他服务的输出相混合。适用于在系统空闲时运行的低优先级任务,这可以减少系统启动时的负载
一个典型的使用idle
类型的服务是updatedb
,它是用于更新locate
命令数据库的服务。这个服务可以配置为在系统空闲时运行,以减少对系统性能的影响。
以下是一个updatedb
服务的systemd
配置文件示例:
[Unit] Description=Update locate database Documentation=man:updatedb(8) ConditionACPower=true [Service] Type=idle ExecStart=/usr/bin/updatedb
- simple(默认值):服务启动时,进程为主进程
(2)启动用户和组
Systemd支持指定服务由哪个用户或组来运行,这样做的好处是进一步实现对权限的管理,增加系统的安全性。
如果在 systemd
服务配置文件中不设置 User
和 Group
参数,服务将默认以 root
用户的身份运行。这意味着服务进程将拥有系统的最高权限,可以访问和修改系统中的所有文件和资源。
推荐做法,为了提高系统的安全性,建议为每个服务设置专门的用户和组,限制其权限。当然,这需要根据实际情况灵活安排,因为有些服务由于涉及底层资源的调用,需要管理员权限才能正常启动。对于那些确认能以普通用户身份运行的服务,还是以普通用户运行
- User
指定以哪个用户运行服务。通过设置User
,可以限制服务进程的权限,确保它智能访问该用户有权限访问的文件和资源。
例如,如果你设置User=www
,那么,服务进程将以www
用户的身份运行 - Group
指定以哪个用户组运行服务。通过设置Group
,可以进一步限制服务进程的权限,确保它只能访问该组有权限访问的文件和资源。
例如,如果你设置Group=www
,服务进程将以www
组的身份运行
(3)环境变量
- Environment
在配置文件中定义内部变量,这样就可以在执行ExecStart
等操作的时候直接引用
Environment="ENV_VAR=value"
- EnvironmentFile
有些软件启动时需要读取自己的环境变量,EnvironmentFile
字段指定当前服务的环境参数文件。该环境参数文件内部的变量,可以用$key
的形式,在当前配置文件中引用。在上述配置文件中,sshd的环境参数文件是/etc/sysconfig/sshd
有些时候,我们可以看到EnvironmentFile
后面的文件前面会加上一个横杠“-”
,这是一个连词号,表示“抑制错误”,即发生错误的时候,不影响其他命令的执行。例如:EnvironmentFile=-/etc/sysconfig/sshd
,表示即使/etc/sysconfig/sshd
文件不存在,也不会抛出错误
(4)服务启动与停止
- ExecStart
定义启动进程时执行的命令。上面的例子中,启动sshd
,执行的启动命令是/usr/sbin/sshd -D $OPTIONS
,其中的变量$OPTIONS
就来自EnvironmentFile
字段指定的环境参数文件 - ExecStop
停止服务 - ExecRload
重启服务 - ExecStartPre
启动当前服务之前需要执行的命令 - ExecStartPost
启动当前服务之后需要执行的命令 - ExecStopPre
停止当前服务前需要执行的命令 - ExecStopPost
停止当前服务后需要执行的命令
(5)重启行为
Service
区块中定义了一些字段,服务在各种原因停止时,Systemd所执行的操作
- KillMode
用于定义Systemd如何停止sshd服务
上面的例子将KillMode
设置为process
,表示只停止主进程,不停止任何sshd子进程,即子进程打开的ssh session仍然保持连接的状态。这个设置不太常见,但对sshd很重要,否则当停止sshd服务时,会将自己打开的ssh session一起杀掉- control-group(默认值):当前控制组里面的所有子进程,都会被杀掉
- process:只杀掉主进程,子进程保留
- mixed:主进程将收到SIGTERM信号,子进程收到SIGKILL信号
- none:没有进程会被杀掉,只是执行服务的stop命令
- Restart
定义了服务退出后,Systemd的重启方式。它允许系统管理员精细控制服务在遇到不同退出情况时是否应该重启。这是确保关键服务可靠性的重要机制,尤其是在生产环境中,服务的持续运行对业务至关重要。
上面的例子中,Restart
设置为on-failure
,表示非正常情况服务异常停止或退出(例如内存溢出导致的程序崩溃),Systemd将会重启sshd。若是系统计划性的维护正常停止服务,或是开发人员出于调试程序目的停止服务,那么sshd服务将不会重启。
Restart
字段可以设置的值如下:- no(默认值):退出后不会重启
- on-success:只有正常退出时(退出状态为0),才会重启
- on-failure:非正常退出时(退出状态码非0),包括被信号终止和超时,才会重启。正常退出则不会重启
- on-abnormal:只有被信号终止和超时,才会重启
- on-abort:只有在收到没有捕捉到的信号终止时,才会重启
- on-watchdog:超时退出,才会重启
- always:服务无论是正常或非正常退出的情况,Systemd总是保持重启的行为
对于守护进程,建议设置为`on-failure`
- RestartSec
表示Systemd重启服务之前,需要等待的时间,单位是s
1.3.3 Install区块
Install区块定义如何安装这个配置文件,即怎样做到开机启动
- WantedBy
表示该服务所在的target
。target
的含义是服务组,表示一组服务。WantedBy=multi-user.target
指的是当前服务所属target
是multi-user.target
这个设置非常重要,如sshd的配置文件,当执行systemctl enable sshd
命令时,会在/etc/systemd/system
中的multi-user.target.wants
目录生成一个名字为sshd.service
的符号文件,指向/usr/lib/systemd/system/sshd.service
一般来说,常用的target有两个:
- multi-user.target
表示多用户命令状态 - graphical.target
表示图形用户状态,它依赖于multi-user.target
二、Target配置文件详解
在 systemd
系统中,target
文件是一种特殊类型的单位(unit),用于组织和管理系统中的其他服务和单位。target
文件本身不包含要执行的进程,而是作为一种逻辑分组,用于控制和协调其他单位的启动顺序和方式。它们类似于传统 init 系统中的运行级别,但提供了更细粒度的控制和更灵活的依赖关系处理。
作用和用途
target
文件的主要作用包括:
- 分组服务:将相关的服务和任务组织在一起,便于统一管理。
- 管理启动顺序:通过依赖关系(如
Wants
,Requires
),控制服务启动的顺序和条件。 - 同步点:在系统启动或其他操作中,提供一个同步点,确保在继续执行其他任务前,一组特定的服务已经启动或达到某种状态。
常见的 target 文件
systemd
中有几个常见的 target
文件,它们在系统启动和运行中扮演重要角色:
multi-user.target
:对应于传统的多用户运行级别,是标准的非图形用户界面多用户系统目标。graphical.target
:用于启动图形用户界面,通常在multi-user.target
的基础上添加了图形环境。network.target
:网络服务启动后达到的目标,许多依赖网络的服务都会在此目标之后启动。reboot.target
,poweroff.target
,halt.target
:这些目标用于管理系统的关机、重启和停机过程。
示例:multi-user.target
以下是一个 multi-user.target
的示例配置文件:
[Unit] Description=Multi-User System Documentation=man:systemd.special(7) Requires=basic.target Conflicts=rescue.service rescue.target After=basic.target rescue.service rescue.target AllowIsolate=yes
参数说明:
- Description:Target文件的简要描述
- Documentation:帮助指导文档路径
- Requires:要求和basic.target一起运行
- Conflicts:冲突字段,如果
rescue.service
或rescue.target
正在运行,multi-user.target
就不能运行,反之亦然 - After:表示
multi-user.target
在basic.target
、recue.service
、rescue.target
之后启动,如果它们有启动的话 - AllowIsolate:允许使用
systemctl isolate
命令切换到multi-user.target
使用场景
管理员可以通过 systemctl
命令来管理 target
,例如,切换当前目标或重新定义默认启动目标。这使得 systemd
非常灵活,能够适应各种不同的系统配置和需求。
通过理解和使用 target
文件,系统管理员可以更好地控制和优化系统的启动过程和运行状态。
三、Target和Service文件的关系和区别
target
和 service
文件是 Systemd
中的两种不同类型的单元文件,它们在系统启动和服务管理中扮演着不同的角色。
3.1 Service 文件
- 作用: 定义和管理具体的服务(即守护进程)。
- 内容: 包含服务的启动命令、运行时参数、依赖关系等。
- 示例:
nginx.service
、mysqld.service
等。
示例
[Unit] Description=My Example Service After=network.target [Service] ExecStart=/usr/bin/my-service User=myserviceuser Group=myservicegroup Restart=always [Install] WantedBy=multi-user.target
3.2 Target 文件
- 作用:组织和管理一组单元(包括
service
、socket
、device
等),类似于传统的运行级别(runlevels)。 - 内容:定义一组单元的集合,表示系统的某个状态或功能。
- 示例:
multi-user.target
、graphical.target
等。
示例
[Unit] Description=Multi-User System Requires=basic.target Conflicts=rescue.target After=basic.target rescue.target AllowIsolate=yes
3.3 关系和区别
- 功能:
service
文件用于定义和管理具体的服务。target
文件用于组织和管理一组单元,表示系统的某个状态或功能。
- 依赖关系:
service
文件可以依赖于target
文件。例如,一个服务可能需要在network.target
之后启动。target
文件可以包含多个service
文件。例如,multi-user.target
包含多个服务,表示系统处于多用户模式。
- 启动顺序:
service
文件通过After
、Before
等指令定义启动顺序。target
文件通过包含和依赖关系定义系统的启动顺序和状态。
示例关系
假设有一个 my-service.service
文件,它依赖于网络服务:
[Unit] Description=My Service After=network.target [Service] ExecStart=/usr/bin/my-service User=myserviceuser Group=myservicegroup Restart=always [Install] WantedBy=multi-user.target
在这个例子中:
my-service.service
文件定义了一个服务。- 该服务在
network.target
之后启动,确保网络服务已启动。 - 该服务被包含在
multi-user.target
中,表示它是多用户模式的一部分。
通过这种方式,service
和 target
文件共同协作,确保系统服务按正确的顺序启动,并达到预期的系统状态。