文章目录
- systemctl针对service类型的配置文件
- systemctl配置文件相关目录简介
- systemctl配置文件的设置项目简介
- 两个vsftpd运行的实例
- 多重的重复设置方式:以getty为例
- 将tty数量由6个降低为4个
- 暂时新增vsftpd到1212端口
- 自己做个服务
systemctl针对service类型的配置文件
systemctl配置文件相关目录简介
现在我们知道服务的管理是通过systemd来完成,而systemd的配置文件大部分放置于/usr/lib/systemd/system/
目录中,但是Red Hat官方文件指出,该目录的文件主要是原本软件所提供的设置,建议不要修改。而要修改的位置应该放置于/etc/systemd/system
目录中。举例来说你想要额外修改vsftpd.service的话,官方建议你放在哪些地方呢?
-
/usr/lib/systemd/system/vsftpd.service
:官方发布的默认配置文件 -
/etc/systemd/system/vsftpd.serivce.d/custom.conf
:在/etc/systemd/system 下面建立于配置文件相同的目录,但是要加上.d的扩展名,然后在该目录下建立配置文件即可。另外,配置文件的扩展名最好使用.conf。在这目录下的文件会【累加其他设置】到 /usr/lib/systemd/system/vsftpd.service中。 -
/etc/systemd/system/vsftpd.service.wants/*
:此目录内的文件为链接文件,设置依赖服务的链接,意思是启动vsftpd.service之后,最好再加上该目录下面建议的服务。 -
/etc/systemd/system/vsftpd.service.requires/*
:此目录内的文件为链接文件,设置依赖服务的链接。意思就是在启动vsftpd.service 之前,需要事先启动哪些服务的意思。
基本上,在配置文件里你都可以自由设置依赖服务的检查,并且设置加入到哪些target里面。但是如果是已经存在的配置文件,或是官方提供的配置文件,Red Hat建议你不要修改原设置,而是到上面提到的几个目录去进行额外的自定义设置比较好,如果你硬要修改原始的/usr/lib/systemd/system 下面的配置文件,那也是没问题的。
systemctl配置文件的设置项目简介
了解完目录在了解一下文件本身的内容,让我们来看看sshd.service的内容。
[root@localhost ~]# cat /usr/lib/systemd/system/sshd.service
[Unit] # 这个项目与此unit的解释、执行服务依赖性有关。
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.service
Wants=sshd-keygen.service
[Service] # 这个项目与实际执行的命令参数有关
Type=notify
EnvironmentFile=/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s
[Install] # 这个项目说明此unit要挂载哪个到target下面。
WantedBy=multi-user.target
[Service]、[Socket]、[Timer]、[Mount]、[Path]
:不同的unit类型就得要使用相对应的设置项目。我们使用sshd.service来当模板,所以这边就使用[service]来设置。
分析上面的配置文件,大概可以将整个设置分为3个部分
[Unit]
部分包含了服务的元数据,Description
字段说明了服务的描述信息,即 OpenSSH 服务器守护进程。Documentation
字段指定了服务的文档信息,即 sshd 服务的 man 页面。After
字段指定了服务需要在network.target
和sshd-keygen.service
启动之后启动,Wants
字段指定了服务需要依赖于sshd-keygen.service
服务。[Service]
部分定义了服务的具体行为,Type
字段指定了服务的类型为notify
,表示当服务准备就绪时会发送一个通知给 systemd。EnvironmentFile
字段指定了服务需要读取的环境变量文件,ExecStart
字段指定了服务的启动命令和选项,ExecReload
字段指定了服务的重载命令。KillMode
字段指定了服务的停止策略,Restart
字段指定了服务的重启策略为在失败时重启,RestartSec
字段指定了服务重启的时间间隔为 42 秒。[Install]
部分定义了服务的安装方式,WantedBy
字段指定了服务需要在multi-user.target
启动之后启动。
此外每个部分里面还有很多的设置,如下所示
unit部分
设置参数 | 参数意义说明 |
---|---|
Description | 是当我们使用【systemctl list-units】时,会输出给管理员看的建议说明信息。 |
Documentation | 这个项目在提供给管理员能够进行进一步的文件查询的功能。提供的文件可以是如下内容: Documentation=http://www… Documentation=man:sshd(8) Documentation=file:/etc/ssh/sshd_config |
After | 说明此unit是在哪个daemon启动之后才启动的意思。基本上仅是说明服务启动顺序而已,并没有强制要求里面的服务一定启动后,此unit才能启动。 |
Before | 与After的意义相反,是在什么服务启动前最好启动这个服务的意思。仅是规范服务启动顺序,并非强制要求的意思 |
Requires | 明确的定义unit需要在哪个daemon启动后才能够启动,就是设置依赖服务。如果在此项设置的前导服务没有启动,那么此unit就不会被启动 |
Wants | 与Requires刚好相反,规范的是这个unit之后最好还要启动什么服务比较好的意思。如果Wants后面接的服务没有启动,其实不会影响到这个unit本身 |
Conflicts | 代表冲突的服务。就是这个项目后面接的服务如果有启动,那么我们这个unit本身就不能启动。如果我们unit有启动,则此项目后面的服务就不能启动。就是冲突性的检查 |
Service部分
设置参数 | 参数意义说明 |
---|---|
Type | 该字段指定了服务的类型,一般来说有如下几种类型: 1. simple:最常用的类型,用于启动一个进程,systemd会等待这个进程运行完毕后再启动下一个服务。 2. forking:用于启动一个进程,但是systemd会等待这个进程fork出一个子进程,然后父进程退出,而子进程则继续运行。常用于一些需要后台运行的服务,比如nginx。 3. oneshot:用于只需要执行一次的服务,systemd会等待这个服务执行完毕后就退出。 4. dbus:用于启动一个dbus服务。 5. notify:用于启动一个进程,但是这个进程会在运行完毕后向systemd发送一个通知,告诉它服务已经启动完毕了。 6. idle:用于启动一个进程,但是会等待一段时间,直到系统处于空闲状态时再启动服务。 |
EnvironmentFile | 指定启动脚本需要读取的环境配置文件。 |
ExecStart | 字段指定了服务的启动命令和选项 |
ExecStop | 与systemctl stop 的执行有关,关闭此服务时所运行的命令 |
ExecReload | 与systemctl reload 有关的命令操作 |
Restart | 指定服务的重启策略 |
RemainAfterExit | 当设置RemainAfterExit=1时,则当这个daemon所属的所有进程都终止之后,此服务会再尝试启动,如果设置为0,则服务再退出后视为不再启动。 |
TimeoutSec | 若这个服务在启动或关闭时,因为某些缘故导致无法顺利【正常启动或正常结束】的情况下,则我们要等多久才进入【强制结束】的状态。 |
KillMode | 字段指定了服务的停止策略 |
RestartSec | 字段指定了服务重启的时间 |
Install部分
设置参数 | 参数意义说明 |
---|---|
WantedBy | 指定服务需要在哪个target启动之后启动,而且这个服务必须是启动的 |
Also | 指定与此服务一起启动的服务。 |
Alias | 运行一个链接的别名的意思 |
接下来根据上面这些数据来进行一些简易的操作
两个vsftpd运行的实例
因为某些原因,你可能会使用到两个端口,分别是正常的21以及特殊的555.这两个port都启用的情况下,你可能使用到两个配置文件以及两个启动脚本设置。假设是这样:
- 默认的21端口:使用/etc/vsftpd/vsftpd.conf 配置文件,以及/usr/lib/systemd/system/ vsftpd.service设置脚本
- 特殊的2121端口:使用/etc/vsftpd/vsftpd2.conf 配置文件,以及 /etc/systemd/system/ vsftpd2.service 设置脚本。
我们可以这样做
- 先建立好需要的配置文件
[root@localhost ~]# cd /etc/vsftpd/
[root@localhost vsftpd]# cp vsftpd.conf vsftpd2.conf
[root@localhost vsftpd]# vim vsftpd.conf
#listen_port=2121
[root@localhost vsftpd]# vim vsftpd2.conf
listen_port=2121
[root@localhost vsftpd]# diff vsftpd.conf vsftpd2.conf
129c129
< #listen_port=2121
---
> listen_port=2121
# 注意这两个配置文件的差别,只有这一行不同而已
- 开始处理启动脚本设置
[root@localhost vsftpd]# cd /etc/systemd/system/
[root@localhost system]# cp /usr/lib/systemd/system/vsftpd.service vsftpd2.service
[root@localhost system]# vim vsftpd2.service
[Unit]
Description=Vsftpd ftp daemon
After=network.target
[Service]
Type=forking
ExecStart=/usr/sbin/vsftpd /etc/vsftpd/vsftpd2.conf
[Install]
WantedBy=multi-user.target
- 重新加载systemd的脚本配置文件内容
[root@localhost system]# systemctl daemon-reload
[root@localhost system]# systemctl list-unit-files --all |grep vsftpd
vsftpd.service enabled
vsftpd2.service disabled
vsftpd@.service disabled
vsftpd.target disabled
[root@localhost system]# systemctl status vsftpd2.service
● vsftpd2.service - Vsftpd ftp daemon
Loaded: loaded (/etc/systemd/system/vsftpd2.service; disabled; vendor preset: disabled)
Active: inactive (dead)
[root@localhost system]# systemctl restart vsftpd.service vsftpd2.service
[root@localhost system]# systemctl enable vsftpd.service vsftpd2.service
Created symlink from /etc/systemd/system/multi-user.target.wants/vsftpd2.service to /etc/systemd/system/vsftpd2.service.
很简单地将你的systemd所管理的vsftpd做了另一个相同的服务。如果你有需求按照上面的方法做就行了。
多重的重复设置方式:以getty为例
我们的Centos 7启动完成后,不是说有6个终端可以使用吗?就是tty1~tty6,这个东西是有agetty命令完成的。那么这个终端的功能又是哪个项目所提供的呢?其实,这个东西涉及很多层面,主要管理的是getty.target 这个target unit,不过,实际产生tty1~tty6的则是由getty@.service所提供。
先来看看/usr/lib/systemd/system/getty@.service的内容
[root@localhost ~]# cat /usr/lib/systemd/system/getty@.service
[Unit]
Description=Getty on %I
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=http://0pointer.de/blog/projects/serial-console.html
After=systemd-user-sessions.service plymouth-quit-wait.service getty-pre.target
After=rc-local.service
Before=getty.target
IgnoreOnIsolate=yes
ConditionPathExists=/dev/tty0
[Service]
ExecStart=-/sbin/agetty --noclear %I $TERM
Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes
[Install]
WantedBy=getty.target
当然比较重要的就是ExecStart项目。那么我们去man agetty时,发现到它的语法应该是【agetty --noclear tty1】之类的字样,因此,我们如果要启动6个tty的时候,基本上应该有6个启动配置文件。就是可能会用到getty1.service、getty2.service…getty6.service才对。但是这样管理很麻烦,所以,才会出现 @ 的项目。这个@是怎么回事呢?先来看看getty@.service 的上游
[root@localhost ~]# systemctl show getty.target
Names=getty.target
Wants=getty@tty1.service
WantedBy=multi-user.target
Conflicts=shutdown.target
Before=multi-user.target
After=getty@tty2.service getty@tty1.service getty@tty3.service getty@tty4.service getty@tty6.service getty@tty5.service
.....
......
....
你会发现,怎么多出了6个怪异的service呢?我们拿getty@tty1.service 说明一下。当我们执行完getty.target之后,它会持续要求 getty@tty1.service 等 6个服务继续启动。那我们的systemd就会这么做
- 先看 /usr/lib/systemd/system/、/etc/systemd/system/ 有没有getty@tty1.service 的设置,若有就执行,若没有则执行下一步
- 找getty@.service的设置,若有则将@后面的数据带入成%I 的变量,进入getty@.service执行。
也就是说,其实getty@tty1.service实际上是不存在的。主要是通过getty@.service来执行。也就是说,getty@.service的目的是为了要简化多个执行的启动设置,它的命名方式是这样的
原始文件:执行服务名称@.service
执行文件:执行服务名称@范例名称.service
因此当有范例名称带入时,则会有一个新的服务名称产生。你再回头看看getty@.service的启动脚本
ExecStart=-/sbin/agetty --noclear %I $TERM
上表中那个 %I 指定就是【范例名称】。根据getty.target 的信息输出来看,getty@tty1.service 的 %I 就是tty1,因此执行脚本就会变成【/sbin/agetty --noclear tty1】。所以我们才有办法以一个配置文件来启动多个tty1给用户登录。
将tty数量由6个降低为4个
现在你应该会感到困扰的是,那么【6个tty是谁规定的】?为什么不是5个或是7个?这是由systemd的登录配置文件 /etc/systemd/logind.conf 里面规范的。加入你想要tty数量降低到剩下4个的话,可以这样实验
- 修改默认的logind.conf内容,将原本6个终端改为4个
[root@localhost ~]# vim /etc/systemd/logind.conf
[Login]
NAutoVTs=4
ReserveVT=0
....
# 原本是6个而且还注释,请取消注释,然后改成4
- 关闭不小心启动的tty5、tty6并重新启动getty.target
[root@localhost ~]# systemctl stop getty@tty5.service
[root@localhost ~]# systemctl stop getty@tty6.service
[root@localhost ~]# systemctl restart systemd-logind.service
现在你再到桌面环境下,按下[ctrl]+[Alt]+[F1]~[F6]就会发现,只剩下4个可用tty,后面的tty5、tty6已经被废弃,不再被启动。那么我暂时需要启动tty8时,又该如何处理?可以这样做
[root@localhost ~]# systemctl start getty@tty8.service
无须额外建立其他的启动服务配置文件
暂时新增vsftpd到1212端口
不知道你有没有发现,其实再/usr/lib/systemd/system/ 下面还有个特别的 vsftpd@.service 。来看看它的内容
[root@localhost ~]# cat /usr/lib/systemd/system/vsftpd@
@::1 @localhost4 @localhost6 @localhost.localdomain
@localhost @localhost4.localdomain4 @localhost6.localdomain6
[root@localhost ~]# cat /usr/lib/systemd/system/vsftpd@.service
[Unit]
Description=Vsftpd ftp daemon
After=network.target
PartOf=vsftpd.target
[Service]
Type=forking
ExecStart=/usr/sbin/vsftpd /etc/vsftpd/%i.conf
[Install]
WantedBy=vsftpd.target
根据前面getty@.service的说明,我们知道在启动的脚本设置当中,%i或%I 就是代表@后面接的范例文件名的意思。那么能不能建立vsftpd3.conf文件,如何通过该文件来启动新的服务?下面试试看
[root@localhost ~]# cd /etc/vsftpd/
[root@localhost vsftpd]# cp vsftpd.conf vsftpd3.conf
[root@localhost vsftpd]# vim vsftpd3.conf
listen_port=1212
因为我们启用了vsftpd@vsftpd3.service,代表要实验的配置文件在 /etc/vsftpd/vsftpd3.conf 的意思,所以可以直接通过vsftpd@.service 而无须重新设置启动脚本。这样设置会比前面一个小节中的方法要简单,不过你要注意到 @ 这个东西。
自己做个服务
我们自己做个服务。假设我要制作一个可以备份自己系统的服务,这个脚本放在/backups下面,内容如下
[root@localhost ~]# vim /backups/backup.sh
#!/bin/bash
source="/home /root /var/lib /var/spool/{cron,at,mail}"
target="/backups/backup-system-$(date +%Y-%m-%d).tar.gz"
[ ! -d /backups ] && mkdir /backups
tar -zcvf ${target} ${source} &> /backups/backup.log
脚本解释:
这是一个bash脚本,用于备份系统的重要文件和目录。下面是每个部分的解释:
- source=“/home /root /var/lib /var/spool/{cron,at,mail}”:这个变量定义了需要备份的目录,包括/home、/root、/var/lib、/var/spool/cron、/var/spool/at和/var/spool/mail。
- target=“/backups/backup-system-$(date +%Y-%m-%d).tar.gz”:这个变量定义了备份文件的路径和名称,其中$(date +%Y-%m-%d)表示当前日期,tar.gz表示压缩格式。
- [ ! -d /backups ] && mkdir /backups:如果/backups目录不存在,则创建这个目录。
- tar -zcvf ${target} ${source} &> /backups/backup.log:使用tar命令将source变量定义的目录打包成一个压缩文件,保存到target变量定义的位置。-z表示使用gzip进行压缩,-c表示创建新的存档文件,-v表示显示打包的详细过程,-f表示指定存档文件的名称。使用&>将tar命令的输出和错误信息都重定向到/backups/backup.log文件中,以便记录备份过程中出现的任何问题。
[root@localhost ~]# chmod a+x /backups/backup.sh
[root@localhost ~]# ll /backups/backup.sh
-rwxr-xr-x. 1 root root 215 5月 14 23:29 /backups/backup.sh
# 记得要赋予它可执行权限才行
那么接下来如何设计一个名为backup.service的启动脚本设置?可以如下这样做
[root@localhost ~]# vim /etc/systemd/system/backup.service
[Unit]
Description=backup my server
Requires=atd.service
[Service]
Type=simple
ExecStart=/bin/bash -c "echo /backups/backup.sh | at now"
[Install]
WanteBy=multi-user.target
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl start backup.service
[root@localhost ~]# systemctl status backup.service
● backup.service - backup my server
Loaded: loaded (/etc/systemd/system/backup.service; static; vendor preset: disabled)
Active: inactive (dead)
5月 14 23:11:38 localhost.localdomain systemd[1]: [/etc/systemd/system/backup.service:8] Unknown lvalu...ll'
5月 14 23:11:38 localhost.localdomain systemd[1]: Started backup my server.
5月 14 23:11:38 localhost.localdomain bash[3022]: job 1 at Sun May 14 23:11:00 2023
5月 14 23:11:45 localhost.localdomain systemd[1]: [/etc/systemd/system/backup.service:8] Unknown lvalu...ll'
Hint: Some lines were ellipsized, use -l to show in full.
# 为什么Active是inactive?这是因为我们的服务仅是一个简单的脚本
# 因此执行完毕就完毕了,不会继续常驻在内存中。
[root@localhost backups]# cd /backups/
[root@localhost backups]# ls
backup.log backup.sh backup-system-2023-05-14.tar.gz
配置文件解释:
- [Unit]:这个部分是设置服务的描述信息和依赖关系,Description是服务的描述信息,Requires=atd.service 表示这个服务依赖于 atd.service 服务,也就是说,只有在 atd.service 运行的情况下,这个服务才能运行。
- [Service]:这个部分是设置服务的运行参数,Type=simple 表示这个服务是最常用的类型,即启动一个进程,systemd会等待这个进程运行完毕后再启动下一个服务。ExecStart=/bin/bash -c “echo /backups/backup.sh | at now” 表示启动这个服务时,会执行这个命令,即在当前时间调用 at 命令,将备份脚本 /backups/backup.sh 添加到任务队列中,并在任务队列中立即执行。
- [Install]:这个部分是设置服务的安装信息,WantedBy=multi-user.target 表示将这个服务添加到 multi-user.target 的依赖关系中,也就是说,系统启动时会自动启动这个服务。
完成上述的操作之后,以后你都可以直接实验【systemctl start backup.service 】进行系统的备份了。非常方便!