systemd服务单元unit及其配置


与 systemd 的 daemon 运作过程相关的目录简介

回到顶部
不过systemd管理的对象可不止是系统服务进程,systemd管理的对象还包括socket文件、系统快照、操作环境(运行等级)target等, 几乎将触角伸到了系统的每个角落。这也是systemd一开始并不为人接受的地方,违反了unix系统KISS(keep it simple, stupid)的哲学原则。
systemd将管理的对象称为服务单位(unit),这些服务单位又分为不同的类型(type),例如上面提到的socket、target等,而系统服务进程的unit类型为service。
unit由其相关配置文件进行定义和配置,可以通过unit配置文件的后缀扩展名识别unit类型,这些配置文件分布在多个目录下:
/usr/lib/systemd/system/:每个服务最主要的启动脚本设置,有点类似/etc/init.d目录下的文件;
/run/systemd/system/:系统执行过程中所产生的服务脚本,这些脚本的优先序要比 /usr/lib/systemd/system/ 高!
/etc/systemd/system/:管理员依据主机系统的需求所建立的执行脚本,其实这个目录有点类似/etc/rc.d/rc5.d/Sxx之类的功能! 执行优先序比/run/systemd/system/高!也就是说,到底系统开机会不会执行某些服务其实是看 /etc/systemd/system/目录下的设置, 所以该目录底下就是一大堆连结档。而实际执行的systemd启动脚本配置文件, 其实都是放置在/usr/lib/systemd/system/ 底下的喔!
因此如果你想要修改某个服务启动的设置,应该要去/usr/lib/systemd/system/ 底下修改才对!
/etc/systemd/system/仅是连结到正确的执行脚本配置文件而已。所以想要看执行脚本设置,应该就得要到/usr/lib/systemd/system/ 底下去查阅才对!
我们在前几小节曾经谈过比较重要的 systemd 启动脚本配置文件在 /usr/lib/systemd/system/, /etc/systemd/system/ 目录下,那还有哪些目录跟系统的 daemon 运作有关呢? 基本上是这样的:
/usr/lib/systemd/system/:
使用 CentOS 官方提供的软件安装后,默认的启动脚本配置文件都放在这里,这里的数据尽量不要修改~ 要修改时,请到 /etc/systemd/system 底下修改较佳!
/run/systemd/system/:
系统执行过程中所产生的服务脚本,这些脚本的优先序要比 /usr/lib/systemd/system/ 高!
/etc/systemd/system/:
管理员依据主机系统的需求所建立的执行脚本,其实这个目录有点像以前 /etc/rc.d/rc5.d/Sxx 之类的功能! 执行优先序又比 /run/systemd/system/ 高喔!
/etc/sysconfig/*:
几乎所有的服务都会将初始化的一些选项设置写入到这个目录下,举例来说,mandb 所要更新的 man page 索引中,需要加入的参数就写入到此目录下的 man-db 当中喔!而网络的设置则写在
/etc/sysconfig/network-scripts/ 这个目录内。所以,这个目录内的文件也是挺重要的;
/var/lib/:
一些会产生数据的服务都会将他的数据写入到 /var/lib/ 目录中。举例来说,数据库管理系统 Mariadb 的数 据库默认就是写入 /var/lib/mysql/ 这个目录下啦!
/run/:
放置了好多 daemon 的暂存档,包括 lock file 以及 PID file 等等。

systemd服务单元unit的类型分类

回到顶部
上面提到systemd将管理的对象称为unit,unit又分为多种服务类型type,每个unit都有对应的配置文件,通过配置文件的扩展名可以看出unit的类型。
可以统计一下/usr/lib/systemd/system/目录下的unit配置文件都有哪些后缀扩展名:
              [root@initroot ~]# ls -l /usr/lib/systemd/system/
            
[root@initroot ~]# ls -l /usr/lib/systemd/system/ | grep -E '(vsftpd|multi|cron)'
-rw-r--r--  1 root root  284 Nov 20  2018 crond.service
-rw-r--r--. 1 root root  567 Jul  6  2018 multipathd.service
-rw-r--r--  1 root root  492 Jul 31  2019 multi-user.target
drwxr-xr-x. 2 root root 4096 Aug  6  2019 multi-user.target.wants
lrwxrwxrwx  1 root root   17 Aug  6  2019 runlevel2.target -> multi-user.target
lrwxrwxrwx  1 root root   17 Aug  6  2019 runlevel3.target -> multi-user.target
lrwxrwxrwx  1 root root   17 Aug  6  2019 runlevel4.target -> multi-user.target
-rw-r--r--. 1 root root  171 Nov 10  2018 vsftpd.service
-rw-r--r--. 1 root root  184 Nov 10  2018 vsftpd@.service
-rw-r--r--. 1 root root   89 Nov 10  2018 vsftpd.target
可以看到vsftpd与crond的unit类型为系统服务service,multi-user的类型为target,target类似init的运行级别。
根据这些扩展名, 大概可以找到几种比较常见的systemd服务unit类型:
unit类型:
1.service:配置文件后缀为.service,用于定义系统服务,这是最常见的unit类型,平时的管理也主要是针对service来管理;
2.socket:配置文件后缀为.socket,用于标识unix域进程间通信使用的socket文件,通常本地服务之间的通信会用到socket文件,例如x window server;
当通过socket文件传递讯息时,信息被传递到监听该socket文件的服务进程daemon, 如果daemon尚未启动,则启动该daemon后再传送数据。有点类似早期的与早期的super daemon xinetd
监听socket文件的服务一般是不会立刻用到的服务,因此在开机时通常会延迟启动。
3.target:配置文件后缀.target,为执行环境类型,是一群unit的集合,用于实现该target环境,如果要执行该target,就需要执行该target下的所有unit,用于模拟实现传统的运行级别概念;
4.snapshot:配置文件后缀.snapshot,用于管理系统快照;
5.device:配置文件后缀.device,用于定义内核识别的设备;
6.mount:配置文件后缀.mount,用于定义文件系统挂载点,例如来自网络的自动挂载、NFS 文件系统挂载等;
7.automount:配置文件后缀.automount,用于定义文件系统的自动挂载点;
8.swap:配置文件后缀.swap,用于标识swap设备;
9.timer:配置文件后缀.timer,用于管理计划任务,类似anacrontab;
10.path:配置文件后缀.path,为侦测特定文件或目录类型,用于根据文件系统上特定对象的变化来启动其他服务。某些服务需要侦测某些特定的目录来提供队列服务, 例如最常见的打印服务,就是通过侦测打印队列目录来启动打印功能! 这时就得要.path的服务类型支持了!;
11.slice:配置文件后缀.slice,用于资源管理;
12.scope:配置文件后缀.scope,用于外部创建的进程;
最常见的就是.service服务类型了。

查看系统上所有的服务

回到顶部
通过systemctl的list-units和list-unit-files选项来查看系统上的所有服务:
            [root@initroot ~]# systemctl [command] [--type=TYPE] [--all]
            
选项和参数:
command选项:
list-units:为systemctl默认选项,依据unit列出目前有启动的unit。
list-unit-files:依据/usr/lib/systemd/system/内的文件,将所有文件列表说明。
--all列出所有的unit,启动和没启动的。
--type=TYPE:即unit type,只列出指定type的unit,主要有service, socket, target等
systemctl不加参数,默认列出系统上启动的所有unit:
[root@initroot ~]# systemctl
UNIT                                                                                     LOAD   ACTIVE SUB       DESCRIPTION                              
proc-sys-fs-binfmt_misc.automount                                                        loaded active waiting   Arbitrary Executable File Formats File Sys
sys-devices-pci0000:00-0000:00:01.1-ata2-host1-target1:0:0-1:0:0:0-block-sr0.device      loaded active plugged   VBOX_CD-ROM                              
sys-devices-pci0000:00-0000:00:03.0-net-enp0s3.device                                    loaded active plugged   82540EM Gigabit Ethernet Controller (PRO/1
sys-devices-pci0000:00-0000:00:05.0-sound-card0.device                                   loaded active plugged   82801AA AC'97 Audio Controller           
sys-devices-pci0000:00-0000:00:0d.0-ata3-host2-target2:0:0-2:0:0:0-block-sda-sda1.device loaded active plugged   VBOX_HARDDISK 1                          
sys-devices-pci0000:00-0000:00:0d.0-ata3-host2-target2:0:0-2:0:0:0-block-sda.device      loaded active plugged   VBOX_HARDDISK                            
sys-devices-platform-serial8250-tty-ttyS0.device                                         loaded active plugged   /sys/devices/platform/serial8250/tty/ttyS0
sys-devices-platform-serial8250-tty-ttyS1.device                                         loaded active plugged   /sys/devices/platform/serial8250/tty/ttyS1
sys-devices-platform-serial8250-tty-ttyS10.device                                        loaded active plugged   /sys/devices/platform/serial8250/tty/ttyS1
...省略...
fstrim.timer                                                                             loaded active waiting   Discard unused blocks once a week        
motd-news.timer                                                                          loaded active waiting   Message of the Day                       
systemd-tmpfiles-clean.timer                                                             loaded active waiting   Daily Cleanup of Temporary Directories   

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

161 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
上面各字段的含义是:
UNIT :unit名称,可以通过后缀扩展名看出每个unix的类别;
LOAD :开机时是否会被加载,systemctl默认显示的是有加载的项目!
ACTIVE :目前的状态,与后续的SUB搭配!就是我们用systemctl status观察时,active的项目!
DESCRIPTION :详细描述
列出所有已经安装的unit:
[root@initroot ~]# systemctl list-unit-files
UNIT FILE                                  STATE          
proc-sys-fs-binfmt_misc.automount          static         
-.mount                                    generated      
dev-hugepages.mount                        static         
dev-mqueue.mount                           static         
proc-sys-fs-binfmt_misc.mount              static         
sys-fs-fuse-connections.mount              static         
sys-kernel-config.mount                    static         
sys-kernel-debug.mount                     static         
acpid.path                                 enabled        
cups.path                                  enabled        
systemd-ask-password-console.path          static         
systemd-ask-password-plymouth.path         static         
systemd-ask-password-wall.path             static         
session-c2.scope                           transient      
accounts-daemon.service                    enabled        
acpid.service                              disabled       
alsa-restore.service                       static  
...省略...
systemd-tmpfiles-clean.timer               static         
ureadahead-stop.timer                      static         

331 unit files listed.
使用systemctl list-unit-files会扫描/usr/lib/systemd/system目录,将系统上所有的服务都列出来,而list-units仅以unit分类作大致的说明。 STATE状态指开机是否会默认加载!主要有enabled、disabled、mask、static等。
可以使用--type指定要查看的unit类型,例如只想知道service类别的daemon,并且不论是否启动,都列出来:
[root@initroot ~]# systemctl list-units --type=service --all
查询系统上以cpu为名的服务:
[root@initroot ~]# systemctl list-units --type=service --all | grep cpu
cpupower.service loaded inactive dead Configure CPU power related settings
确实有个cpupower.service,可以改变CPU电源管理机制的服务!

systemctl分析各unit间的依赖关系

回到顶部
上面我们可以看出unit之间具有依赖关系,systemctl list-dependencies可以看出unit之间的依赖关系。
              [root@initroot ~]# systemctl list-dependencies [unit] [--reverse]
              
--reverse :反向追踪unit的依赖!
例如观察上面cups.service的依赖unit:
              [root@initroot ~]# systemctl list-dependencies cups.service
            
可以查看一下运行级别target所依赖的unit,例如graphical.target会依赖multi-user.target。 列出当前target环境下依赖的所有unit:
[root@initroot ~]# systemctl get-default
multi-user.target
[root@initroot ~]# systemctl list-dependencies
default.target
├─abrt-ccpp.service
├─abrt-oops.service
├─vsftpd.service
├─basic.target
│ ├─alsa-restore.service
│ ├─alsa-state.service
...省略...
│ ├─sockets.target
│ │ ├─avahi-daemon.socket
│ │ ├─dbus.socket
...省略...
│ ├─sysinit.target
│ │ ├─dev-hugepages.mount
│ │ ├─dev-mqueue.mount
...省略...
│ └─timers.target
│
└─systemd-tmpfiles-clean.timer
├─getty.target
│ └─getty@tty1.service
└─remote-fs.target
因为我们前一小节的练习将默认的操作模式变成 multi-user.target 了,因此这边使用 list-dependencies时,所列出的 default.target 其实是 multi-user.target 的内容啦! 根据线条联机的流程,我们也能够知道, multi-user.target 其实还会用到 basic.target + getty.target + remote-fs.target 三大项目, 而 basic.target 又用到了 sockets.target + sysinit.target + timers.target... 等一堆~所以啰,从这边就能够清 楚的查询到每种 target 模式底下还有的相依模式。 那么如果要查出谁会用到 multi-user.target 呢?
就这么作!
[root@initroot ~]# systemctl list-dependencies --reverse
default.target
└─graphical.target
reverse 本来就是反向的意思,所以加上这个选项,代表谁还会用到我的服务的意思~所以看得 出来, multi-user.target 主要是被 graphical.target 所使用喔! 好~那再来,graphical.target 又使用 了多少的服务呢?可以这样看:
[root@initroot ~]# systemctl list-dependencies graphical.target
graphical.target
├─accounts-daemon.service
├─gdm.service
├─network.service
├─rtkit-daemon.service
├─systemd-update-utmp-runlevel.service
└─multi-user.target
├─abrt-ccpp.service
├─abrt-oops.service
.....(底下省略).....
所以可以看得出来,graphical.target 就是在 multi-user.target 底下再加上 accounts-daemon, gdm, network, rtkit-deamon, systemd-update-utmp-runlevel 等服务而已! 这样会看了吗?了解 daemon 之间 的相关性也是很重要的喔!出问题时,可以找到正确的服务相依流程!

systemctl针对service类型的配置文件

回到顶部
在传统的systemv init进程环境下,如果想要建立系统服务,就需要将管理服务的脚本文件放入/etc/init.d/目录下。 在systemd环境下, 就是通过编辑unit的配置文件实现了。

systemctl 配置文件相关目录简介

回到顶部
现在我们知道服务的管理是通过 systemd,而 systemd 的配置文件大部分放置于 /usr/lib/systemd/system/ 目录内。但是 Red Hat 官方文件指出, 该目录的文件主要是原本软件所提供 的设置,建议不要修改!而要修改的位置应该放置于 /etc/systemd/system/ 目录内。
举例来说,如果你想要额外修改 vsftpd.service 的话, 他们建议要放置到哪些地方呢? /usr/lib/systemd/system/vsftpd.service:官方释出的预设配置文件; /etc/systemd/system/vsftpd.service.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 底下的配置文件,那也是 OK 没问题的!并且也能够减少许多配置文件 的增加~自己认为,这样也不错!反正,就完全是个人喜好啰~

systemctl 配置文件的设置项目简介

回到顶部
了解了配置文件的相关目录与文件之后,再来,当然得要了解一下配置文件本身的内容了!让我们先来瞧一瞧 sshd.service 的内容好了! 原本想拿 vsftpd.service 来讲解,不过该文件的内容比较阳春,还是看一下设置项目多一些的 sshd.service 好了!
[root@initroot ~]# cat /usr/lib/systemd/system/sshd.service
[Unit]                                                 # 这个项目与此 unit 的解释、执行服务相依性有关
Description=OpenSSH server daemon
After=network.target sshd-keygen.service
Wants=sshd-keygen.service
[Service]                                              # 这个项目与实际执行的指令参数有关
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
配置文件大概分为三个部份:
[Unit]: unit本身的说明,以及与其他unit的依赖关系;
[Service]或[Socket]或[Timer]或[Mount]或[Path]..:不同的unit type对应不同的设置项目。
例如如果是service的配置文件,这里就是[Service]。[Service]内主要规范服务启动的脚本、环境配置文件名、重新启动服务的方式等。
[Install]:unit会在哪个运行模式target下启动!
设置项目通常是可以重复的,例如可以重复设置两个After,后面的设置会取代前面的!因此,如果你想要将设置值归零,可以使用类似After=的设置,等号后面什么都没有,就将该设置归零了(reset)。
如果设置参数需要有是/否的项目(布尔值, boolean),你可以使用1, yes, true, on代表启动,用 0, no, false, off代表关闭!
空白行、开头为 # 或 ; 的那一行,都代表注释!
每个部份里面还有很多的设置细项,我们使用一个简单的表格来说明每个项目好了!
[Unit]部份设置参数 参数意义说明
Description 当使用systemctl list-units时,输出给管理员看的简易说明!使用systemctl status输出的服务说明,也是取自这里!
这个项目在提供管理员能够进行进一步的文件查询的功能!提供的文件可以是如下的资料:
Documentation
Documentation=http://www....
Documentation=man:sshd(8)
Documentation=file:/etc/ssh/sshd_config
After 说明此unit是在哪个unit启动之后才启动的意思!基本上仅是说明服务启动的顺序,并没有强制要求服务一定要启动后此unit才能启动。 以 sshd.service 的内容为例,该文件提到After后面有network.target以及sshd-keygen.service,但是若这两个unit没有启动而强制启动sshd.service, sshd.service应该还是能够启动的!这与Requires的设置是有差异!
Before与After的意义相反,是在什么服务启动前最好启动这个服务。不过这仅是规范服务启动的顺序,并非强制要求的意思。
Requires 明确定义此unit需要在哪个unit启动后才能够启动!就是设置依赖服务!如果在此项设置的服务没有启动,那么此unit就不会被启动!
Wants 与 Requires 刚好相反,规范的是这个 unit 之后最好还要启动什么服务比较好!不过,并没有明确的规范!主要的目的是希望建立让使用者比较好操作的环境。 因此,Wants后面接的服务即使没有启动,也不会影响到这个unit!
Conflicts 代表冲突的服务!亦即这个项目后面接的服务如果有启动,那么我们这个unit就不能启动!该unit启动,则此项目后的服务就不能启动! 就是冲突性的检查!
接下来了解一下在 [Service] 当中有哪些项目可以使用!
[Service]部份设置参数 参数意义说明 Type 说明unit启动的方式,会影响到ExecStart!这里unit的类型为service,所以这里所说的unit其实就是我们经常提到的守护进程了!
一般来说,有底下几种类型:
simple:默认值,daemon主要由ExecStart接的指令串来启动,启动后常驻于内存中。
forking:由ExecStart启动的程序通过spawns延伸出其他子程序来作为此daemon的主要服务。原生的父程序在启动结束后就会终止运作。传统的unit服务大多属于这种项目, 例如 httpd 这个 WWW 服务,当 httpd 的程序因为运作过久因此即将终结了,则 systemd 会再重新生出另一个子程序持续运作后, 再将父程序删除。据说这样的效能比较好!
oneshot:与simple类似,不过进程在工作完毕后就结束了,不会常驻在内存中。
dbus:与simple类似,但这个daemon必须要在取得一个D-Bus的名称后,才会继续运作!因此设置这个项目时,通常也要设置 BusName=!
idle:与simple类似,意思是,要执行这个daemon必须要所有的工作都顺利执行完毕后才会执行。这类的daemon通常是开机到最后才执行的服务!
比较重要的项目大概是 simple, forking 与 oneshot 了!
毕竟很多服务需要子进程(forking),而有更多的动作只需要在开机的时候执行一次(oneshot),例如文件系统的检查与挂载等。
EnvironmentFile 可以指定启动脚本的环境配置文件!例如sshd.service的配置文件写入到/etc/sysconfig/sshd当中! 也可以使用Environment=后面接多个不同的Shell变量来给予设置! ExecStart就是实际执行此daemon的指令或脚本程序 。 也可以使用ExecStartPre(之前)以及ExecStartPost(之后)两个设置项目来在实际启动服务前,进行额外的指令行为。 指令串仅接受指令 参数 参数...的格式,不能接受 <, >, >>, |, & 等特殊字符,很多的bash语法也不支持! 要使用这些特殊的字符时,最好直接写入到指令脚本里面去!不过,上述的语法也不是完全不能用,亦即,若要支持比较完整的bash语法,那你得要使用Type=oneshot才行! 其他的Type不能支持这些字符。
ExecStop 与systemctl stop的执行有关,关闭此服务时所进行的指令。
ExecReload 与 systemctl reload有关的指令行为
Restart 当设置Restart=1时,则当此daemon服务终止后,会再次的启动此服务。
举例来说,在tty2使用文字界面登入,操作完毕后注销,基本上,这个时候tty2就已经结束服务了。
但是你会看到屏幕又立刻产生一个新的tty2的登入画面等待你的登入!
那就是 Restart 的功能!
除非使用systemctl强制将此服务关闭,否则这个服务会源源不绝的一直重复产生!
RemainAfterExit 当设置为RemainAfterExit=1时,则当这个daemon所属的所有程序都终止之后,此服务会再尝试启动。这对于Type=oneshot的服务很有帮助!
TimeoutSec 若这个服务在启动或者是关闭时,因为某些缘故导致无法顺利正常启动或正常结束的情况下,则我们要等多久才进入强制结束的状态!
KillMode 可以是process, control-group, none其中一种,如果是process则daemon终止时,只会终止主要的程序(ExecStart接的后面那串指令), 如果是control-group时, 则由此daemon所产生的其他control-group的程序,也都会被关闭。
如果是none的话,则没有程序会被关闭喔!
RestartSec与Restart有点相关性,如果这个服务被关闭,然后需要重新启动时,大概要sleep多少时间再重新启动的意思。预设是100ms(毫秒)。
最后,再来看看那么 Install 内还有哪些项目可用?
[Install]部份设置参数 参数意义说明
WantedBy 这个设置后面接的大部分是*.target unit!意思是,这个unit本身是附挂在哪一个target unit底下的! 一般来说,大多的服务性质的unit都是附挂在multi-user.target底下! Also 当目前这个unit本身被enable时,Also后面接的unit也请enable的意思!也就是具有相依性的服务可以写在这里呢!
Alias 进行一个连结的别名的意思!当systemctl enable相关的服务时,则此服务会进行连结档的建立! 以multi-user.target为例,这个家伙是用来作为预设操作环境default.target的规划, 因此当你设置用成default.target时 , 这个/etc/systemd/system/default.target就会连结到/usr/lib/systemd/system/multi-user.target! 大致的项目就有这些,接下来让我们根据上面这些数据来进行一些简易的操作吧!

两个 vsftpd 运作的实例

回到顶部
我们在上一章将 vsftpd 的 port 改成 555 号了。不过,因为某些原因,所以你可能需要使用到两个 端口,分别是正常的 21 以及特殊的 555 ! 这两个 port 都启用的情况下,你可能就得要使用到两 个配置文件以及两个启动脚本设置了!现在假设是这样:
预设的 port 21:使用 /etc/vsftpd/vsftpd.conf 配置文件,以及 /usr/lib/systemd/system/vsftpd.service 设置脚本;
特殊的 port 555:使用 /etc/vsftpd/vsftpd2.conf 配置文件,以及 /etc/systemd/system/vsftpd2.service 设置脚本。
我们可以这样作:
# 1. 先建立好所需要的配置文件
[root@initroot ~]# cd /etc/vsftpd
[root@initroot vsftpd]# cp vsftpd.conf vsftpd2.conf
[root@initroot vsftpd]# vim vsftpd.conf
#listen_port=555
[root@initroot vsftpd]# diff vsftpd.conf vsftpd2.conf
128c128
< #listen_port=555
---
> listen_port=555
# 注意这两个配置文件的差别喔!只有这一行不同而已!
# 2. 开始处理启动脚本设置
[root@initroot vsftpd]# cd /etc/systemd/system
[root@initroot system]# cp /usr/lib/systemd/system/vsftpd.service vsftpd2.service
[root@initroot system]# vim vsftpd2.service
[Unit]
Description=Vsftpd second ftp daemon
After=network.target
[Service]
Type=forking
ExecStart=/usr/sbin/vsftpd /etc/vsftpd/vsftpd2.conf
[Install]
WantedBy=multi-user.target# 重点在改了 vsftpd2.conf 这个配置文件喔!
# 3. 重载 systemd 的脚本配置文件内容
[root@initroot system]# systemctl daemon-reload
[root@initroot system]# systemctl list-unit-files --all | grep vsftpd
vsftpd.service enabled
vsftpd2.service disabled
vsftpd@.service disabled
vsftpd.target disabled
[root@initroot system]# systemctl status vsftpd2.service
vsftpd2.service - Vsftpd second ftp daemon
Loaded: loaded (/etc/systemd/system/vsftpd2.service; disabled)
Active: inactive (dead)
[root@initroot system]# systemctl restart vsftpd.service vsftpd2.service
[root@initroot system]# systemctl enable vsftpd.service vsftpd2.service
[root@initroot system]# systemctl status vsftpd.service vsftpd2.service
vsftpd.service - Vsftpd ftp daemon
Loaded: loaded (/usr/lib/systemd/system/vsftpd.service; enabled)
Active: active (running) since Wed 2015-08-12 22:00:17 CST; 35s ago
Main PID: 12670 (vsftpd)
CGroup: /system.slice/vsftpd.service
└─12670 /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf
Aug 12 22:00:17 study.centos.vbird systemd[1]: Started Vsftpd ftp daemon.
vsftpd2.service - Vsftpd second ftp daemon
Loaded: loaded (/etc/systemd/system/vsftpd2.service; enabled)
Active: active (running) since Wed 2015-08-12 22:00:17 CST; 35s ago
Main PID: 12672 (vsftpd)
CGroup: /system.slice/vsftpd2.service
└─12672 /usr/sbin/vsftpd /etc/vsftpd/vsftpd2.conf
[root@initroot system]# netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1340/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 2387/master
tcp6 0 0 :::555 :::* LISTEN 12672/vsftpd
tcp6 0 0 :::21 :::* LISTEN 12670/vsftpd
tcp6 0 0 :::22 :::* LISTEN 1340/sshd
tcp6 0 0 ::1:25 :::* LISTEN 2387/master
很简单的将你的 systemd 所管理的 vsftpd 做了另一个服务!未来如果有相同的需求,同样的方法作一遍即可!

多重的重复设置方式:以 getty 为例

回到顶部
我们的 CentOS 7 开机完成后,不是说有 6 个终端机可以使用吗?就是那个 tty1~tty6 的啊!那个东西是由 agetty 这个指令达成的。 OK!那么这个终端机的功能又是从哪个项目所提供的呢?其实,那个东东涉及很多层面,主要管理的是 getty.target 这个 target unit , 不过,实际产生 tty1~tty6 的 则是由 getty@.service 所提供的!咦!那个 @ 是啥东西?
先来查阅一下 /usr/lib/systemd/system/getty@.service 的内容好了:
[root@initroot ~]# 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
After=rc-local.service
Before=getty.target
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 之类的字样, 因此,我们如果要启动六个 tty 的时候,基本上应该要有六个启动配 置文件。亦即是可能会用到 getty1.service, getty2.service...getty6.service 才对! 哇!这样控管很麻烦 啊~所以,才会出现这个 @ 的项目啦!咦!这个 @ 到底怎么回事呢?我们先来看看 getty@.service 的上游,亦即是 getty.target 这个东西的内容好了!
[root@initroot ~]# systemctl show getty.target
# 那个 show 的指令可以将 getty.target 的默认设置值也取出来显示!
Names=getty.target
Wants=getty@tty1.service
WantedBy=multi-user.target
Conflicts=shutdown.target
Before=multi-user.target
After=getty@tty1.service getty@tty2.service getty@tty3.service getty@tty4.service
getty@tty6.service getty@tty5.service
.....(后面省略).....
你会发现,咦!怎么会多出六个怪异的 service 呢?我们拿 getty@tty1.service 来说明一下好了!当 我们执行完 getty.target 之后, 他会持续要求 getty@tty1.service 等六个服务继续启动。那我们的 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 个的话,那么可以这样实验看看:
# 1. 修改预设的 logind.conf 内容,将原本 6 个虚拟终端机改成 4 个
[root@initroot ~]# vim /etc/systemd/logind.conf
[Login]NAutoVTs=4
ReserveVT=0
# 原本是 6 个而且还注释,请取消注释,然后改成 4 吧!
# 2. 关闭不小心启动的 tty5, tty6 并重新启动 getty.target 啰!
[root@initroot ~]# systemctl stop getty@tty5.service
[root@initroot ~]# systemctl stop getty@tty6.service
[root@initroot ~]# systemctl restart systemd-logind.service
现在你再到桌面环境下,按下 [ctrl]+[alt]+[F1]~[F6] 就会发现,只剩下四个可用的 tty 啰!后面的 tty5, tty6 已经被放弃了!不再被启动喔! 好!那么我暂时需要启动 tty8 时,又该如何处理呢?需要重 新建立一个脚本吗?不需要啦!可以这样作!
[root@initroot ~]# systemctl start getty@tty8.service
无须额外建立其他的启动服务配置文件喔!
暂时新增 vsftpd 到 2121 端口
不知道你有没有发现,其实在 /usr/lib/systemd/system 底下还有个特别的 vsftpd@.service 喔!来看看 他的内容:
[root@initroot ~]# 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 文件,然后通过该文件来启动新的服务呢? 就来玩玩看!
# 1. 根据 vsftpd@.service 的建议,于 /etc/vsftpd/ 底下先建立新的配置文件
[root@initroot ~]# cd /etc/vsftpd
[root@initroot vsftpd]# cp vsftpd.conf vsftpd3.conf
[root@initroot vsftpd]# vim vsftpd3.conflisten_port=2121
# 2. 暂时启动这个服务,不要永久启动他!
[root@initroot vsftpd]# systemctl start vsftpd@vsftpd3.service
[root@initroot vsftpd]# systemctl status vsftpd@vsftpd3.service
vsftpd@vsftpd3.service - Vsftpd ftp daemon
Loaded: loaded (/usr/lib/systemd/system/vsftpd@.service; disabled)
Active: active (running) since Thu 2015-08-13 01:34:05 CST; 5s ago
[root@initroot vsftpd]# netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp6 0 0 :::2121 :::* LISTEN 16404/vsftpd
tcp6 0 0 :::555 :::* LISTEN 12672/vsftpd
tcp6 0 0 :::21 :::* LISTEN 12670/vsftpd
因为我们启用了 vsftpd@vsftpd3.service ,代表要使用的配置文件在 /etc/vsftpd/vsftpd3.conf 的意思! 所以可以直接通过 vsftpd@.service 而无须重新设置启动脚本! 这样是否比前几个小节的方法还要简 便呢? ^_^。通过这个方式,你就可以使用到新的配置文件啰!只是你得要注意到 @ 这个东西就是 了! ^_^
聪明的读者可能立刻发现一件事,为啥这次 FTP 增加了 2121 端口却不用修改 SELinux 呢?这是因为默认启动小于 1024 号码以下的端口口时, 需要使用到 root 的权限,因此小于 1024 以下 端口的启动较可怕。而这次范例中,我们使用 2121 端口口,他对于系统的影响可能小一些 (其实一样可怕!), 所 以就忽略了 SELinux 的限制了!

自己的服务自己作

回到顶部
我们来模拟自己作一个服务吧!假设我要作一只可以备份自己系统的服务,这只脚本我放在 /backups 底下,内容有点像这样:
[root@initroot ~]# vim /backups/backup.sh
#!/bin/bash
source="/etc /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[root@initroot ~]# chmod a+x /backups/backup.sh
[root@initroot ~]# ll /backups/backup.sh
-rwxr-xr-x. 1 root root 220 Aug 13 01:57 /backups/backup.sh
# 记得要有可执行的权限才可以喔!
接下来,我们要如何设计一只名为 backup.service 的启动脚本设置呢?可以这样做喔!
[root@initroot ~]# 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]
WantedBy=multi-user.target
# 因为 ExecStart 里面有用到 at 这个指令,因此, atd.service 就是一定要的服务!
[root@initroot ~]# systemctl daemon-reload
[root@initroot ~]# systemctl start backup.service
[root@initroot ~]# systemctl status backup.service
backup.service - backup my server
Loaded: loaded (/etc/systemd/system/backup.service; disabled)
Active: inactive (dead)
Aug 13 07:50:31 study.centos.vbird systemd[1]: Starting backup my server...
Aug 13 07:50:31 study.centos.vbird bash[20490]: job 8 at Thu Aug 13 07:50:00 2015
Aug 13 07:50:31 study.centos.vbird systemd[1]: Started backup my server.
# 为什么 Active 是 inactive 呢?这是因为我们的服务仅是一个简单的 script 啊!
# 因此执行完毕就完毕了,不会继续存在内存中喔!
完成上述的动作之后,以后你都可以直接使用 systemctl start backup.service 进行系统的备份了!而且
会直接丢进 atd 的管理中, 你就无须自己手动用 at 去处理这项任务了~好像还不赖喔! ^_^
这样自己做一个服务好像也不难啊! ^_^!自己动手玩玩看吧!

initroot编辑整理,转载请注明www.initroot.com

100次点赞 100次阅读