该系列目录 --> 【BASH】回顾与知识点梳理(目录)
在 Unix-Like 的系统中,你会常常听到 daemon 这个字眼!那么什么是传说中的 daemon 呢?这些 daemon 放在什么地方?他的功能是什么?该如何启动这些 daemon ?又如何有效的将这些 daemon 管理妥当?此外,要如何视察这些daemon 开了多少个 ports ?又这些 ports 要如何关闭?还有还有,晓得你系统的这些 port 各代表的是什么服务吗? 这些都是最基础需要注意的呢!尤其是在架设网站之前,这里的观念就显的更重要了。
从 CentOS 7.x 这一版之后,传统的 init 已经被舍弃,取而代之的是 systemd 这个家伙~这家伙跟之前的 init 有什么差异? 优缺点为何?如何管理不同种类的服务类型?以及如何取代原本的『执行等级』等等,很重要的改变喔!
我们曾经谈过『服务』这东西! 当时的说明是『常驻在记体体中的程序,且可以提供一些系统或网络功能,那就是服务
』。而服务一般的英文说法是『service
』。
简单的说,系统为了某些功能必须要提供一些服务 (不论是系统本身还是网络方面),这个服务就称为 service
。 但是 service 的提供总是需要程序的运作吧!否则如何执行呢?所以达成这个 service 的程序我们就称呼他为 daemon
啰! 举例来说,达成循环型例行性工作排程服务 (service) 的程序为 crond 这个 daemon 啦!这样说比较容易理解了吧!
daemon 既然是一只程序执行后的程序,那么 daemon 所处的那个原本的程序通常是如何命名的呢 (daemon 程序的命名方式)。 每一个服务的开发者,当初在开发他们的服务时,都有特别的故事啦!不过,无论如何,这些服务的名称被建立之后,被挂上 Linux 使用时,通常在服务的名称之后会加上一个 d ,例如例行性命令的建立的 at, 与 cron 这两个服务, 他的程序文件名会被取为 atd 与 crond,这个 d 代表的就是daemon 的意思。
那个很纯种的 Unix 版本~ 在那种年代底下,我们启动系统服务的管理方式被称为 SysV 的 init 脚本程序的处理方式!亦即系统核心第一支呼叫的程序是 init , 然后 init 去唤起所有的系统所需要的服务,不论是本地服务还是网络服务就是了。
基本上 init 的管理机制有几个特色如下:
服务的启动、关闭与观察等方式:
所有的服务启动脚本通通放置于 /etc/init.d/ 底下,基本上都是使用 bash shell script 所写成的脚本程序,需要启动、关闭、重新启动、观察状态时, 可以透过如下的方式来处理:
服务启动的分类:
init 服务的分类中,依据服务是独立启动或被一只总管程序管理而分为两大类:
服务的相依性问题:
服务是可能会有相依性的~例如,你要启动网络服务,但是系统没有网络, 那怎么可能可以唤醒网络服务呢?如果你需要联机到外部取得认证服务器的联机,但该联机需要另一个 A 服务的需求,问题是,A 服务没有启动, 因此,你的认证服务就不可能会成功启动的!这就是所谓的服务相依性问题。init 在管理员自己手动处理这些服务时,是没有办法协助相依服务的唤醒的!
执行等级的分类:
上面说到 init 是开机后核心主动呼叫的, 然后 init 可以根据用户自定义的执行等级 (runlevel) 来唤醒不同的服务,以进入不同的操作界面。基本上 Linux 提供 7 个执行等级,分别是 0, 1, 2…6 , 比较重要的是
而各个执行等级的启动脚本是透过/etc/rc.d/rc[0-6]/SXXdaemon
连结到 /etc/init.d/daemon , 连结档名 (SXXdaemon) 的功能为: S 为启动该服务,XX 是数字,为启动的顺序。由于有 SXX 的设定,因此在开机时可以『依序执行
』所有需要的服务,同时也能解决相依服务的问题。这点与管理员自己手动处理不太一样就是了。
制定执行等级默认要启动的服务:
若要建立如上提到的 SXXdaemon 的话,不需要管理员手动建立连结档, 透过如下的指令可以来处理默认启动、预设不启动、观察预设启动否的行为:
执行等级的切换行为:
当你要从纯文本界面 (runlevel 3) 切换到图形界面 (runlevel 5), 不需要手动启动、关闭该执行等级的相关服务,只要『 init 5 』即可切换,init 这小子会主动去分析 /etc/rc.d/rc[35].d/ 这两个目录内的脚本, 然后启动转换 runlevel 中需要的服务~就完成整体的 runlevel 切换。
基本上 init 主要的功能都写在上头了,重要的指令包括 daemon 本身自己的脚本(/etc/init.d/daemon) 、xinetd 这个特殊的总管程序 (super daemon)、设定预设开机启动的 chkconfig,以及会影响到执行等级的 init N 等。虽然 CentOS 7 已经不使用 init 来管理服务了,不过因为考虑到某些脚本没有办法直接塞入 systemd 的处理,因此这些脚本还是被保留下来, 所以,我们在这里还是稍微介绍了一下。
从 CentOS 7.x 以后,Red Hat 系列的 distribution 放弃沿用多年的 System V 开机启动服务的流程,就是前一小节提到的 init 启动脚本的方法, 改用 systemd 这个启动服务管理机制~那么 systemd 有什么好处呢?
一项一项任务依序启动
』的模式,因此不相依的服务也是得要一个一个的等待。但目前我们的硬件主机系统与操作系统几乎都支持多核心架构了, 没道理未相依的服务不能同时启动啊!systemd 就是可以让所有的服务同时启动,因此你会发现到,系统启动的速度变快了!虽然如此,不过 systemd 也是有些地方无法完全取代 init 的!包括:
不过,光是同步启动服务脚本这个功能就可以节省你很多开机的时间~同时 systemd 还有很多特殊的服务类型 (type) 可以提供更多有趣的功能!确实值得学一学~ 而且 CentOS 7 已经用了 systemd 了!想不学也不行啊~哈哈哈!好~既然要学,首先就得要针对 systemd 管理的 unit 来了解一下。
基本上, systemd 将过去所谓的 daemon 执行脚本通通称为一个服务单位 (unit),而每种服务单位依据功能来区分时,就分类为不同的类型 (type)。 基本的类型有包括系统服务、数据监听与交换的插槽档服务 (socket)、储存系统状态的快照类型、提供不同类似执行等级分类的操作环境 (target) 等等。 哇!这么多类型,那设定时会不会很麻烦呢?其实还好,因为配置文件都放置在底下的目录中:
也就是说,到底系统开机会不会执行某些服务其实是看 /etc/systemd/system/ 底下的设定,所以该目录底下就是一大堆连结档。而实际执行的 systemd 启动脚本配置文件, 其实都是放置在/usr/lib/systemd/system/ 底下的喔!因此如果你想要修改某个服务启动的设定,应该要去/usr/lib/systemd/system/ 底下修改才对! /etc/systemd/system/ 仅是连结到正确的执行脚本配置文件而已。所以想要看执行脚本设定,应该就得要到 /usr/lib/systemd/system/ 底下去查阅才对!
那 /usr/lib/systemd/system/ 以下的数据如何区分上述所谓的不同的类型 (type) 呢?很简单!看扩展名!举例来说,我们来瞧瞧上一章谈到的 vsftpd 这个范例的启动脚本设定, 还有 crond 与纯文本模式的 multi-user 设定:
[root@study ~]# ll /usr/lib/systemd/system/ | grep -E '(vsftpd|multi|cron)'
-rw-r--r--. 1 root root 284 7 月 30 2014 crond.service #
-rw-r--r--. 1 root root 567 3 月 6 06:51 multipathd.service
-rw-r--r--. 1 root root 524 3 月 6 13:48 multi-user.target #
drwxr-xr-x. 2 root root 4096 5 月 4 17:52 multi-user.target.wants
lrwxrwxrwx. 1 root root 17 5 月 4 17:52 runlevel2.target -> multi-user.target
lrwxrwxrwx. 1 root root 17 5 月 4 17:52 runlevel3.target -> multi-user.target
lrwxrwxrwx. 1 root root 17 5 月 4 17:52 runlevel4.target -> multi-user.target
-rw-r--r--. 1 root root 171 6 月 10 2014 vsftpd.service #
-rw-r--r--. 1 root root 184 6 月 10 2014 [email protected]
-rw-r--r--. 1 root root 89 6 月 10 2014 vsftpd.target
# 比较重要的是上头提供的那三行特殊字体的部份!
所以我们可以知道 vsftpd 与 crond 其实算是系统服务 (service),而 multi-user 要算是执行环境相关的类型 (target type)。根据这些扩展名的类型, 我们大概可以找到几种比较常见的 systemd 的服务类型如下:
扩展名 | 主要服务功能 |
---|---|
.service | 一般服务类型 (service unit):主要是系统服务 ,包括服务器本身所需要的本地服务以及网络服务都是!比较经常被使用到的服务大多是这种类型! 所以,这也是最常见的类型了! |
.socket | 内部程序数据交换的插槽服务 (socket unit):主要是 IPC (Inter-process communication) 的传输讯息插槽文件 (socket file) 功能 。 这种类型的服务通常在监控讯息传递的插槽文件,当有透过此插槽文件传递讯息来说要链接服务时,就依据当时的状态将该用户的要求传送到对应的 daemon, 若 daemon 尚未启动,则启动该daemon 后再传送用户的要求。使用 socket 类型的服务一般是比较不会被用到的服务,因此在开机时通常会稍微延迟启动的时间 (因为比较没有这么常用嘛!)。一般用于本地服务比较多,例如我们的图形界面很多的软件都是透过 socket 来进行本机程序数据交换的行为。 (这与早期的xinetd 这个 super daemon 有部份的相似喔!) |
.target | 执行环境类型 (target unit):其实是一群 unit 的集合 ,例如上面表格中谈到的 multi-user.target 其实就是一堆服务的集合~也就是说, 选择执行 multi-user.target 就是执行一堆其他 .service 或/及 .socket 之类的服务就是了! |
.mount .automount |
文件系统挂载相关的服务 (automount unit / mount unit) :例如来自网络的自动挂载、NFS 文件系统挂载等与文件系统相关性较高的程序管理。 |
.path | 侦测特定文件或目录类型 (path unit):某些服务需要侦测某些特定的目录来提供队列服务 ,例如最常见的打印服务,就是透过侦测打印队列目录来启动打印功能! 这时就得要 .path 的服务类型支持了! |
.timer | 循环执行的服务 (timer unit):这个东西有点类似 anacrontab 喔 !不过是由 systemd 主动提供的,比 anacrontab 更加有弹性! |
其中又以 .service 的系统服务类型最常见了!因为我们一堆网络服务都是透过这种类型来设计的啊!接下来,让我们来谈谈如何管理这些服务的启动与关闭。
基本上, systemd 这个启动服务的机制,主要是透过一只名为 systemctl 的指令来处理的!跟以前systemV 需要 service / chkconfig / setup / init 等指令来协助不同, systemd 就是仅有 systemctl 这个指令来处理而已呦!所以全部的行为都得要使用 systemctl 的意思啦!有没有很难?其实习惯了之后,鸟哥是觉得 systemctl 还挺好用的!^_^
一般来说,服务的启动有两个阶段,一个是『开机的时候设定要不要启动这个服务
』, 以及『你现在要不要启动这个服务
』,这两者之间
有很大的差异喔!举个例子来说,假如我们现在要『立刻取消 atd 这个服务』时,正规的方法 (不要用 kill) 要怎么处理?
[root@study ~]# systemctl [command] [unit]
command 主要有:
start :立刻启动后面接的 unit
stop :立刻关闭后面接的 unit
restart :立刻关闭后启动后面接的 unit,亦即执行 stop 再 start 的意思
reload :不关闭后面接的 unit 的情况下,重载配置文件,让设定生效
enable :设定下次开机时,后面接的 unit 会被启动
disable :设定下次开机时,后面接的 unit 不会被启动
status :目前后面接的这个 unit 的状态,会列出有没有正在执行、开机预设执行否、登录等信息等!
is-active :目前有没有正在运作中
is-enable :开机时有没有预设要启用这个 unit
# 范例一:看看目前 atd 这个服务的状态为何?
[root@study ~]# systemctl status atd.service
atd.service - Job spooling tools
Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled) #2
Active: active (running) since Mon 2015-08-10 19:17:09 CST; 5h 42min ago #3
Main PID: 1350 (atd)
CGroup: /system.slice/atd.service
└─1350 /usr/sbin/atd -f
Aug 10 19:17:09 study.centos.vbird systemd[1]: Started Job spooling tools.
# 重点在第二、三行喔~
# Loaded:这行在说明,开机的时候这个 unit 会不会启动,enabled 为开机启动,disabled 开机不会启动
# Active:现在这个 unit 的状态是正在执行 (running) 或没有执行 (dead)
# 后面几行则是说明这个 unit 程序的 PID 状态以及最后一行显示这个服务的登录文件信息!
# 登录文件信息格式为:『时间』 『讯息发送主机』 『哪一个服务的讯息』 『实际讯息内容』
# 所以上面的显示讯息是:这个 atd 预设开机就启动,而且现在正在运作的意思!
好!再回到 systemctl status atd.service 的第三行,不是有个 Active 的 daemon 现在状态吗?除了running 跟 dead 之外, 有没有其他的状态呢?有的~基本上有几个常见的状态:
active (running)
:正有一只或多只程序正在系统中执行的意思,举例来说,正在执行中的 vsftpd 就是这种模式。active (exited)
:仅执行一次就正常结束的服务,目前并没有任何程序在系统中执行。 举例来说,开机或者是挂载时才会进行一次的 quotaon 功能,就是这种模式! quotaon 不须一直执行~只须执行一次之后,就交给文件系统去自行处理啰!通常用 bash shell 写的小型服务,大多是属于这种类型 (无须常驻内存)。active (waiting)
:正在执行当中,不过还再等待其他的事件才能继续处理。举例来说,打印的队列相关服务就是这种状态! 虽然正在启动中,不过,也需要真的有队列进来 (打印作业) 这样他才会继续唤醒打印机服务来进行下一步打印的功能。inactive
:这个服务目前没有运作的意思。既然 daemon 目前的状态就有这么多种了,那么 daemon 的预设状态有没有可能除了 enable/disable 之外,还有其他的情况呢?当然有!
相依属性的服务
)[root@node-135 vsftpd]# systemctl disable chronyd
Removed symlink /etc/systemd/system/multi-user.target.wants/chronyd.service.
[root@node-135 vsftpd]# systemctl stop chronyd
看得很清楚~其实就是从 /etc/systemd/system 底下删除一条连结文件而已~# 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 是一种打印服务,这个打印服务会启用 port 631 来提供网络打印机的打印功能。 但是其实我们无须一直启动 631 埠口吧?因此,多了一个名为 cups.socket 的服务,这个服务可以在『用户有需要打印时,才会主动唤醒cups.service 』的意思! 因此,如果你仅是 disable/stop cups.service 而忘记了其他两个服务的话,那么当有用户向其他两个 cups.path, cups.socket 提出要求时, cups.service 就会被唤醒!所以,你关掉也没用!
比较正规的作法是,要关闭 cups.service 时,连同其他两个会唤醒 service 的 cups.socket 与cups.path 通通关闭,那就没事了! 比较不正规的作法是,那就强迫 cups.service 注销吧!透过 mask 的方式来将这个服务注销看看!
# 1. 保持刚刚的状态,关闭 cups.service,启动 cups.socket,然后注销 cups.servcie
[root@study ~]# systemctl stop cups.service
[root@study ~]# systemctl mask cups.service
ln -s '/dev/null' '/etc/systemd/system/cups.service'
# 喔耶~其实这个 mask 注销的动作,只是让启动的脚本变成空的装置而已!
[root@study ~]# systemctl status cups.service
cups.service
Loaded: masked (/dev/null)
Active: inactive (dead) since Tue 2015-08-11 23:14:16 CST; 52s ago
[root@study ~]# systemctl start cups.service
Failed to issue method call: Unit cups.service is masked. # 再也无法唤醒!
上面的范例你可以仔细推敲一下~原来整个启动的脚本配置文件被连结到 /dev/null 这个空装置~因此,无论如何你是再也无法启动这个 cups.service 了! 透过这个 mask 功能,你就可以不必管其他相依服务可能会启动到这个想要关闭的服务了!虽然是非正规,不过很有效! ^_^
那如何取消注销呢?当然就是 unmask 即可啊
[root@study ~]# systemctl unmask cups.service
rm '/etc/systemd/system/cups.service'
[root@study ~]# systemctl status cups.service
cups.service - CUPS Printing Service
Loaded: loaded (/usr/lib/systemd/system/cups.service; disabled)
Active: inactive (dead) since Tue 2015-08-11 23:14:16 CST; 4min 35s ago
# 好佳在有恢复正常!
系统上面有多少的服务存在呢?这个时候就得要透过 list-units 及 list-unit-files 来观察了! 细部的用法如下:
[root@study ~]# systemctl [command] [--type=TYPE] [--all]
command:
list-units :依据 unit 列出目前有启动的 unit。若加上 --all 才会列出没启动的。
list-unit-files :依据 /usr/lib/systemd/system/ 内的文件,将所有文件列表说明。
--type=TYPE:就是之前提到的 unit type,主要有 service, socket, target 等
# 范例一:列出系统上面有启动的 unit
[root@study ~]# systemctl
UNIT LOAD ACTIVE SUB DESCRIPTION
proc-sys-fs-binfmt_mis... loaded active waiting Arbitrary Executable File Formats File System
sys-devices-pc...:0:1:... loaded active plugged QEMU_HARDDISK
sys-devices-pc...0:1-0... loaded active plugged QEMU_HARDDISK
sys-devices-pc...0:0-1... loaded active plugged QEMU_DVD-ROM
.....(中间省略).....
vsftpd.service loaded active running Vsftpd ftp daemon
.....(中间省略).....
cups.socket loaded failed failed CUPS Printing Service Sockets
.....(中间省略).....
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.
141 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 的类别 (看扩展名)
# LOAD :开机时是否会被加载,默认 systemctl 显示的是有加载的项目而已喔!
# ACTIVE :目前的状态,须与后续的 SUB 搭配!就是我们用 systemctl status 观察时,active 的项目!
# DESCRIPTION :详细描述啰
# cups 比较有趣,因为刚刚被我们玩过,所以 ACTIVE 竟然是 failed 的喔!被玩死了! ^_^
# 另外,systemctl 都不加参数,其实预设就是 list-units 的意思!
# 范例二:列出所有已经安装的 unit 有哪些?
[root@study ~]# systemctl list-unit-files
UNIT FILE STATE
proc-sys-fs-binfmt_misc.automount static
dev-hugepages.mount static
dev-mqueue.mount static
proc-fs-nfsd.mount static
.....(中间省略).....
systemd-tmpfiles-clean.timer static
336 unit files listed.
使用 systemctl list-unit-files
会将系统上所有的服务通通列出来~而不像 list-units 仅以 unit 分类作大致的说明。 至于 STATE 状态就是前两个小节谈到的开机是否会加载的那个状态项目啰!主要有enabled / disabled / mask / static 等等。
假设我不想要知道这么多的 unit 项目,我只想要知道 service 这种类别的 daemon 而已,而且不论是否已经启动,通通要列出来! 那该如何是好?
[root@study ~]# systemctl list-units --type=service --all
# 只剩下 *.service 的项目才会出现喔!
# 范例一:查询系统上是否有以 cpu 为名的服务?
[root@study ~]# systemctl list-units --type=service --all | grep cpu
cpupower.service loaded inactive dead Configure CPU power related settings
# 确实有喔!可以改变 CPU 电源管理机制的服务哩!
透过上个小节我们知道系统上所有的 systemd 的 unit 观察的方式,那么可否列出跟操作界面比较有关的 target 项目呢? 很简单啊!就这样搞一下:
[root@node-135 vsftpd]# systemctl list-units --type=target --all
UNIT LOAD ACTIVE SUB DESCRIPTION
basic.target loaded active active Basic System
cryptsetup.target loaded active active Local Encrypted Volumes
emergency.target loaded inactive dead Emergency Mode
final.target loaded inactive dead Final Step
getty-pre.target loaded inactive dead Login Prompts (Pre)
getty.target loaded active active Login Prompts
graphical.target loaded inactive dead Graphical Interface
initrd-fs.target loaded inactive dead Initrd File Systems
initrd-root-fs.target loaded inactive dead Initrd Root File System
initrd-switch-root.target loaded inactive dead Switch Root
initrd.target loaded inactive dead Initrd Default Target
local-fs-pre.target loaded active active Local File Systems (Pre)
local-fs.target loaded active active Local File Systems
multi-user.target loaded active active Multi-User System
network-online.target loaded active active Network is Online
network-pre.target loaded inactive dead Network (Pre)
network.target loaded active active Network
nss-user-lookup.target loaded inactive dead User and Group Name Lookups
paths.target loaded active active Paths
remote-fs-pre.target loaded inactive dead Remote File Systems (Pre)
remote-fs.target loaded active active Remote File Systems
rescue.target loaded inactive dead Rescue Mode
shutdown.target loaded inactive dead Shutdown
slices.target loaded active active Slices
sockets.target loaded active active Sockets
sound.target loaded active active Sound Card
swap.target loaded active active Swap
sysinit.target loaded active active System Initialization
● syslog.target not-found inactive dead syslog.target
time-sync.target loaded inactive dead System Time Synchronized
timers.target loaded active active Timers
umount.target loaded inactive dead Unmount All Filesystems
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.
32 loaded units listed.
To show all installed unit files use 'systemctl list-unit-files'.
喔!在我们的 CentOS 7.9 的预设情况下,就有 32 个 target unit 耶!而跟操作界面相关性比较高的target 主要有底下几个:
正常的模式是 multi-user.target 以及 graphical.target 两个,救援方面的模式主要是 rescue.target 以及更严重的 emergency.target。 如果要修改可提供登入的 tty 数量,则修改 getty.target 项目。基本上,我们最常使用的当然就是 multi-user 以及 graphical 啰! 那么我如何知道目前的模式是哪一种?又得要如何修改呢?底下来玩一玩吧!
[root@study ~]# systemctl [command] [unit.target]
选项与参数:
command:
get-default :取得目前的 target
set-default :设定后面接的 target 成为默认的操作模式
isolate :切换到后面接的模式
# 范例一:我们的测试机器默认是图形界面,先观察是否真为图形模式,再将默认模式转为文字界面
[root@study ~]# systemctl get-default
graphical.target # 果然是图形界面喔!
[root@study ~]# systemctl set-default multi-user.target
[root@study ~]# systemctl get-default
multi-user.target
# 范例二:在不重新启动的情况下,将目前的操作环境改为纯文本模式,关掉图形界面
[root@study ~]# systemctl isolate multi-user.target
# 范例三:若需要重新取得图形界面呢?
[root@study ~]# systemctl isolate graphical.target
在正常的切换情况下,使用上述 isolate 的方式即可。不过为了方便起见, systemd 也提供了数个简单的指令给我们切换操作模式之用喔! 大致上如下所示:
[root@study ~]# systemctl poweroff 系统关机
[root@study ~]# systemctl reboot 重新启动
[root@study ~]# systemctl suspend 进入暂停模式
[root@study ~]# systemctl hibernate 进入休眠模式
[root@study ~]# systemctl rescue 强制进入救援模式
[root@study ~]# systemctl emergency 强制进入紧急救援模式
关机、重新启动、救援与紧急模式这没啥问题,那么什么是暂停与休眠模式呢?
我们在本章一开始谈到 systemd 的时候就有谈到相依性的问题克服,那么,如何追踪某一个 unit 的相依性呢? 举例来说好了,我们怎么知道 graphical.target 会用到 multi-user.target 呢?那graphical.target 底下还有哪些东西呢? 底下我们就来谈一谈:
[root@study ~]# systemctl list-dependencies [unit] [--reverse]
选项与参数:
--reverse :反向追踪谁使用这个 unit 的意思!
# 范例一:列出目前的 target 环境下,用到什么特别的 unit
[root@study ~]# systemctl get-default
multi-user.target
[root@study ~]# 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
│ └─[email protected]
└─remote-fs.target
根据线条联机的流程,我们也能够知道, multi-user.target 其实还会用到 basic.target + getty.target + remote-fs.target 三大项目, 而
basic.target 又用到了 sockets.target + sysinit.target + timers.target… 等一堆~所以啰,从这边就能够清楚的查询到每种 target 模式底下还有的相依模式。 那么如果要查出谁会用到 multi-user.target 呢?就这么作!
[root@study ~]# systemctl list-dependencies --reverse
default.target
└─graphical.target
reverse 本来就是反向的意思,所以加上这个选项,代表『谁还会用到我的服务
』的意思~所以看得出来, multi-user.target 主要是被 graphical.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
.....(底下省略).....
所以可以看得出来,graphical.target 就是在 multi-user.target 底下再加上 accounts-daemon, gdm, network, rtkit-deamon, systemd-update-utmp-runlevel 等服务而已! 这样会看了吗?了解 daemon 之间的相关性也是很重要的喔!出问题时,可以找到正确的服务相依流程!
我们在前几小节曾经谈过比较重要的 systemd 启动脚本配置文件在 /usr/lib/systemd/system/, /etc/systemd/system/ 目录下,那还有哪些目录跟系统的 daemon 运作有关呢? 基本上是这样的:
我们知道 systemd 里头有很多的本机会用到的 socket 服务,里头可能会产生很多的 socket file ~那你怎么知道这些 socket file 放置在哪里呢? 很简单!还是透过 systemctl 来管理!
[root@node-135 vsftpd]# systemctl list-sockets
LISTEN UNIT ACTIVATES
/dev/log systemd-journald.socket systemd-journald.service
/run/dbus/system_bus_socket dbus.socket dbus.service
/run/dmeventd-client dm-event.socket dm-event.service
/run/dmeventd-server dm-event.socket dm-event.service
/run/lvm/lvmetad.socket lvm2-lvmetad.socket lvm2-lvmetad.service
/run/lvm/lvmpolld.socket lvm2-lvmpolld.socket lvm2-lvmpolld.service
/run/systemd/initctl/fifo systemd-initctl.socket systemd-initctl.service
/run/systemd/journal/socket systemd-journald.socket systemd-journald.service
/run/systemd/journal/stdout systemd-journald.socket systemd-journald.service
/run/systemd/shutdownd systemd-shutdownd.socket systemd-shutdownd.service
/run/udev/control systemd-udevd-control.socket systemd-udevd.service
kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
12 sockets listed.
Pass --all to see loaded but inactive sockets, too.
这样很清楚的就能够知道正在监听本地服务需求的 socket file 所在的文件名位置啰!
系统所有的功能都是某些程序所提供的,而程序则是透过触发程序而产生的。同样的,系统提供的网络服务当然也是这样的! 只是由于网络牵涉到 TCP/IP 的概念,所以显的比较复杂一些就是了。
当客户端联机过来我们的主机时, 我们主机是如何分辨不同的服务要求呢?那就是透过埠号 (端口号,port number) 啦!系统上面有没有什么设定可以让服务与埠号对应在一起呢?那就是 /etc/services 啦!
[root@study ~]# cat /etc/services
....(前面省略)....
ftp 21/tcp
ftp 21/udp fsp fspd
ssh 22/tcp # The Secure Shell (SSH) Protocol
ssh 22/udp # The Secure Shell (SSH) Protocol
....(中间省略)....
http 80/tcp www www-http # WorldWideWeb HTTP
http 80/udp www www-http # HyperText Transfer Protocol
....(底下省略)....
# 这个文件的内容是以底下的方式来编排的:
# <该服务的说明>
请特别注意!虽然有的时候你可以藉由修改 /etc/services 来更改一个服务的埠号,不过并不建议如此做, 因为很有可能会造成一些协议的错误情况!这里特此说明一番呦!(除非你要架设一个地下网站,否则的话,使用 /etc/services 原先的设定就好啦!)
除了本地服务之外,其实你一定要观察的,反而是网络服务喔!虽然网络服务默认有 SELinux 管理,不过,在鸟哥的立场上, 我还是建议非必要的网络服务就关闭他!那么什么是网络服务呢?基本上,会产生一个网络监听端口口 (port) 的程序,你就可以称他是个网络服务了! 那么如何观察网络端口口?就这样追踪啊!
[root@study ~]# netstat -tlunp
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 29113/vsftpd
tcp6 0 0 :::22 :::* LISTEN 1340/sshd
tcp6 0 0 ::1:25 :::* LISTEN 2387/master
udp 0 0 0.0.0.0:5353 0.0.0.0:* 750/avahi-daemon: r
udp 0 0 0.0.0.0:36540 0.0.0.0:* 750/avahi-daemon: r
如上表所示,我们的系统上至少开了 22, 25, 555, 5353, 36540 这几个埠口~而其中 5353, 36540 是由avahi-daemon 这个东西所启动的!接下来我们使用 systemctl 去观察一下,到底有没有 avahi-daemon 为开头的服务呢?
[root@study ~]# systemctl list-units --all | grep avahi-daemon
avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack
avahi-daemon.socket loaded active running Avahi mDNS/DNS-SD Stack Activation Socket
透过追查,知道这个 avahi-daemon 的目的是在局域网络进行类似网芳的搜寻,因此这个服务可以协助你在区网内随时了解即插即用的装置! 包括笔记本电脑等,只要连上你的区网,你就能够知道谁进来了。问题是,你可能不要这个协议啊!所以,那就关闭他吧!
[root@study ~]# systemctl stop avahi-daemon.service
[root@study ~]# systemctl stop avahi-daemon.socket
[root@study ~]# systemctl disable avahi-daemon.service avahi-daemon.socket
[root@study ~]# netstat -tlunp
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 29113/vsftpd
tcp6 0 0 :::22 :::* LISTEN 1340/sshd
tcp6 0 0 ::1:25 :::* LISTEN 2387/master
一般来说,你的本地服务器至少需要 25 号埠口,而 22 号埠口则最好加上防火墙来管理远程联机登入比较妥当~因此,上面的埠口中, 除了 555 是我们上一章因为测试而产生的之外,这样的系统能够被爬墙的机会已经少很多了! ^_^!OK!现在如果你的系统里面有一堆网络端口口在监听, 而你根本不知道那是干麻用的,鸟哥建议你,现在就透过上面的方式,关闭他吧!
该系列目录 --> 【BASH】回顾与知识点梳理(目录)