第十七章、系统服务
1.1)、daemon与service
系统为了某些功能必须要提供一些服务 (不论是系统本身还是网络方面),这个服务就称为 service 。 但是 service 的提供总是需要程序的运行吧!否则如何执行呢?所以达成这个 service 的程序我们就称呼他为 daemon 啰!
注:你不必去区分什么是 daemon 与 service !事实上,你可以将这两者视为相同!因为达成某个服务是需要一支 daemon 在背景中运行, 没有这支 daemon 就不会有 service !所以不需要分的太清楚啦。
系统核心第一支调用的程序是 init , 然后 init 去唤起所有的系统所需要的服务,不论是本机服务还是网络服务。
从 CentOS 7.x 以后,Red Hat 系列的 distribution 放弃沿用多年的 System V 开机启动服务的流程,就是前一小节提到的 init 启动脚本的方法, 改用 systemd 这个启动服务管理机制。
通过systemctl管理服务
通过mask来强迫服务注销
# 1. 先看看 cups 的服务是开还是关? [root@study ~]# systemctl status cups.service cups.service - CUPS Printing Service Loaded: loaded (/usr/lib/systemd/system/cups.service; enabled) Active: inactive (dead) since Tue 2015-08-11 19:19:20 CST; 3h 29min ago # 有趣得很!竟然是 enable 但是却是 inactive 耶!相当特别! # 2. 那就直接关闭,同时确认没有启动喔! [root@study ~]# systemctl stop cups.service [root@study ~]# systemctl disable cups.service rm '/etc/systemd/system/multi-user.target.wants/cups.path' rm '/etc/systemd/system/sockets.target.wants/cups.socket' rm '/etc/systemd/system/printer.target.wants/cups.service' # 也是非常特别!竟然一口气取消掉三个链接文件!也就是说,这三个文件可能是有相依性的问题喔! [root@study ~]# netstat -tlunp | grep cups # 现在应该不会出现任何数据!因为根本没有 cups 的任务在执行当中~所以不会有 port 产生 # 3. 尝试启动 cups.socket 监听用户端的需求喔! [root@study ~]# systemctl start cups.socket [root@study ~]# systemctl status cups.service cups.socket cups.path cups.service - CUPS Printing Service Loaded: loaded (/usr/lib/systemd/system/cups.service; disabled) Active: inactive (dead) since Tue 2015-08-11 22:57:50 CST; 3min 41s ago cups.socket - CUPS Printing Service Sockets Loaded: loaded (/usr/lib/systemd/system/cups.socket; disabled) Active: active (listening) since Tue 2015-08-11 22:56:14 CST; 5min ago cups.path - CUPS Printer Service Spool Loaded: loaded (/usr/lib/systemd/system/cups.path; disabled) Active: inactive (dead) # 确定仅有 cups.socket 在启动,其他的并没有启动的状态! # 4. 尝试使用 lp 这个指令来打印看看? [root@study ~]# echo "testing" | lp lp: Error - no default destination available. # 实际上就是没有打印机!所以有错误也没关系! [root@study ~]# systemctl status cups.service cups.service - CUPS Printing Service Loaded: loaded (/usr/lib/systemd/system/cups.service; disabled) Active: active (running) since Tue 2015-08-11 23:03:18 CST; 34s ago [root@study ~]# netstat -tlunp | grep cups tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 25881/cupsd tcp6 0 0 ::1:631 :::* LISTEN 25881/cupsd # 见鬼!竟然 cups 自动被启动了!明明我们都没有驱动他啊!怎么回事啊? # 因为很多服务彼此之间是有相依性的。 # 比较正规的作法是,要关闭 cups.service 时,连同其他两个会唤醒 service 的 cups.socket 与 # cups.path 通通关闭,那就没事了!
那么,如何追踪某一个 unit 的相依性呢?
举例来说好了,我们怎么知道 graphical.target 会用到 multi-user.target 呢?那 graphical.target 下面还有哪些东西呢?
[root@study ~]# 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 .....(下面省略).....
网络服务:基本上,会产生一个网络监听端口 (port) 的程序,你就可以称他是个网络服务。
- 自己的服务自己作
假设要作一只可以备份自己系统的服务,这只脚本我放在 /backups 下面:
[root@study ~]# 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@study ~]# chmod a+x /backups/backup.sh [root@study ~]# ll /backups/backup.sh -rwxr-xr-x. 1 root root 220 Aug 13 01:57 /backups/backup.sh # 记得要有可执行的权限才可以喔!
接下来,我们要设计一只名为 backup.service 的启动脚本:
[root@study ~]# 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@study ~]# systemctl daemon-reload [root@study ~]# systemctl start backup.service [root@study ~]# 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 啊! # 因此执行完毕就完毕了,不会继续存在内存中喔!
然后,定时启动:
现在假设这样:
开机后 2 小时开始执行一次这个 backup.service
自从第一次执行后,未来我每两天要执行一次 backup.service
[root@study ~]# vim /etc/systemd/system/backup.timer [Unit] Description=backup my server timer [Timer] OnBootSec=2hrs OnUnitActiveSec=2days [Install] WantedBy=multi-user.target # 只要这样设置就够了!储存离开吧! [root@study ~]# systemctl daemon-reload [root@study ~]# systemctl enable backup.timer [root@study ~]# systemctl restart backup.timer [root@study ~]# systemctl list-unit-files | grep backup backup.service disabled # 这个不需要启动!只要 enable backup.timer 即可! backup.timer enabled [root@study ~]# systemctl show timers.target ConditionTimestamp=Thu 2015-08-13 14:31:11 CST # timer 这个 unit 启动的时间! [root@study ~]# systemctl show backup.service ExecMainExitTimestamp=Thu 2015-08-13 14:50:19 CST # backup.service 上次执行的时间 [root@study ~]# systemctl show backup.timer NextElapseUSecMonotonic=2d 19min 11.540653s # 下一次执行距离 timers.target 的时间
如上表所示,我上次执行 backup.service 的时间是在 2015-08-13 14:50 ,由于设置两个小时执行一次,因此下次应该是 2015-08-15 14:50 执行才对! 由于 timer 是由 timers.target 这个 unit 所管理的,而这个 timers.target 的启动时间是在 2015-08-13 14:31 , 要注意,最终backup.timer 所纪录的下次执行时间,其实是与 timers.target 所纪录的时间差!因此是“ 2015-08-15 14:50 - 2015-08-13 14:31 ”才对! 所以时间差就是 2d 19min 啰!
【重点回顾】
① 早期的服务管理使用 systemV 的机制,通过 /etc/init.d/*, service, chkconfig, setup 等指令来管理服务的启动/关闭/默认启动;
② 从 CentOS 7.x 开始,采用 systemd 的机制,此机制最大功能为平行处理,并采单一指令管理 (systemctl),开机速度加快!
③ systemd 将各服务定义为 unit,而 unit 又分类为 service, socket, target, path, timer 等不同的类别,方便管理与维护;
④ 启动/关闭/重新启动的方式为: systemctl [start|stop|restart] unit.service;
⑤ 设置默认启动/默认不启动的方式为: systemctl [enable|disable] unit.service;
⑥ 查询系统所有启动的服务用 systemctl list-units --type=service 而查询所有的服务 (含不启动) 使用 systemctl list-unit-files --type=service;
⑦ systemd 取消了以前的 runlevel 概念 (虽然还是有相容的 target),转而使用不同的 target 操作环境。常见操作环境为 multi-user.targer与 graphical.target。 不重新开机而转不同的操作环境使用 systemctl isolate unit.target,而设置默认环境则使用 systemctl set-default unit.target;
⑧ systemctl 系统默认的配置文件主要放在 /usr/lib/systemd/system,管理员若要修改或自行设计时,则建议放在 /etc/systemd/system/ 目录下。
⑨ 管理员应使用 man systemd.unit, man systemd.service, man systemd.timer 查询 /etc/systemd/system/ 下面配置文件的语法, 并使用systemctl daemon-reload 载入后,才能自行撰写服务与管理服务喔!
⑩ 除了 atd 与 crond 之外,可以 通过 systemd.timer 亦即 timers.target 的功能,来使用 systemd 的时间管理功能。
⑪ 一些不需要的服务可以关闭喔!
Over......