一、CentOS 7的systemd向后兼容
systemd被设计成尽可能向后兼容SysV init和Upstart,下面是一些特别要注意的和之前主要版本的RHEL不再兼容的部分。
1)systemd对运行级别支持有限
为了保存兼容,systemd提供一定数量的target单元,可以直接和运行级别对应,也可以被早期的分布式的运行级别命令支持。不是所有的target都可以被映射到运行级别,在这种情况下,使用runlevel命令有可能会返回一个为N的不知道的运行级别,所以推荐尽量避免在RHEL7中使用runlevel命令。
2)systemd不支持像init脚本那样的个性化命令
除了一些标准命令参数例如:start、stop、status,SysV init脚本可以根据需要支持想要的任何参数,通过参数提供附加的功能,因为SysV init的服务器脚本实际上就是shell脚本,命令参数实际上就是shell子函数。举个例子,RHEL6的iptables服务脚本可以执行panic命令行参数,这个参数可以让系统立即进入紧急模式,丢弃所有的进入和发出的数据包。但是类似这样的命令行参数在systemd中是不支持的,systemd只支持在配置文件中指定命令行参数。
3)systemd不支持和没有从systemd启动的服务通讯
当systemd启动服务的时候,他保存进程的主ID以便于追踪,systemctl工具使用进程PID查询和管理服务。相反的,如果用户从命令行启动特定的服务,systemctl命令是没有办法判断这个服务的状态是启动还是运行的。
4)systemd可以只停止运行的服务
在RHEL6及之前的版本,当关闭系统的程序启动之后,RHEL6的系统会执行/etc/rc0.d/下所有服务脚本的关闭操作,不管服务是处于运行或者根本没有运行的状态。而systemd可以做到只关闭在运行的服务,这样可以大大节省关机的时间。
5)不能从标准输出设备读到系统服务信息
systemd启动服务的时候,将标准输出信息定向到/dev/null,以免打扰用户。
6)systemd不继承任何上下文环境
systemd不继承任何上下文环境,如用户或者会话的HOME或者PATH的环境变量。每个服务得到的是干净的上下文环境。
7)SysV init脚本依赖性
当systemd启动SysV init脚本,systemd在运行的时候,从LinuxStandardBase(LSB)Linux标准库头文件读取服务的依赖信息并继承。
8)超时机制
为了防止系统被卡住,所有的服务有5分钟的超时机制。
二、systemd单元(unit)的概念
在RHEL7之前,服务管理是分布式的被SysV init或UpStart通过/etc/rc.d/init.d下的脚本管理。这些脚本是经典的Bash脚本,允许管理员控制服务的状态。在RHEL7中,这些脚本被服务单元文件替换。
系统初始化需要做的事情非常多。需要启动后台服务,比如启动 SSHD 服务;需要做配置工作,比如挂载文件系统。这个过程中的每一步都被 systemd 抽象为一个配置单元,即 unit。Systemd可以管理所有系统资源。不同的资源统称为 Unit(单位)。可以认为一个服务是一个配置单元;一个挂载点是一个配置单元;一个交换分区的配置是一个配置单元;等等。systemd 将配置单元归纳为以下一些不同的类型。然而,systemd 正在快速发展,新功能不断增加。所以配置单元类型可能在不久的将来继续增加。systemd中有许多单元类型,服务单元文件的扩展名是.service,同脚本的功能相似。例如有查看、启动、停止、重启、启用或者禁止服务的参数。
Systemd unit(单元)介绍
.service
代表一个后台服务进程,比如 mysqld。这是最常用的一类。
.target
此类配置单元为其他配置单元进行逻辑分组。它们本身实际上并不做什么,只是引用其他配置单元而已。这样便可以对配置单元做一个统一的控制。这样就可以实现大家都已经非常熟悉的运行级别概念。比如想让系统进入图形化模式,需要运行许多服务和配置命令,这些操作都由一个个的配置单元表示,将所有这些配置单元组合为一个目标(target),就表示需要将这些配置单元全部执行一遍以便进入目标所代表的系统运行状态。 (例如:multi-user.target 相当于在传统使用 SysV 的系统中运行级别 5)
.socket
此类配置单元封装系统和互联网中的一个 套接字 。当下,systemd 支持流式、数据报和连续包的 AF_INET、AF_INET6、AF_UNIX socket 。每一个套接字配置单元都有一个相应的服务配置单元 。相应的服务在第一个“连接“进入套接字时就会启动(例如:nscd.socket 在有新连接后便启动 nscd.service)。
.device
此类配置单元封装一个存在于 Linux 设备树中的设备。每一个使用 udev 规则标记的设备都将会在 systemd 中作为一个设备配置单元出现。
.mount
此类配置单元封装文件系统结构层次中的一个挂载点。Systemd 将对这个挂载点进行监控和管理。比如可以在启动时自动将其挂载;可以在某些条件下自动卸载。Systemd 会将/etc/fstab 中的条目都转换为挂载点,并在开机时处理。
.automount
此类配置单元封装系统结构层次中的一个自挂载点。每一个自挂载配置单元对应一个挂载配置单元 ,当该自动挂载点被访问时,systemd 执行挂载点中定义的挂载行为。
.swap
和挂载配置单元类似,交换配置单元用来管理交换分区。用户可以用交换配置单元来定义系统中的交换分区,可以让这些交换分区在启动时被激活。
.timer
定时器配置单元用来定时触发用户定义的操作,这类配置单元取代了 atd、crond 等传统的定时服务。
.snapshot
与 target 配置单元相似,快照是一组配置单元。它保存了系统当前的运行状态。
每个配置单元都有一个对应的配置文件,系统管理员的任务就是编写和维护这些不同的配置文件,比如一个 MySQL 服务对应一个 mysql.service 文件。这种配置文件的语法非常简单,用户不需要再编写和维护复杂的系统 5 脚本了。
systemd单元文件放置位置
1 2 3 4 5 6 7 8 |
# 默认单元文件安装目录 /usr/lib/systemd/system/system # 单元运行时创建,这个目录优先于按照目录 /run/systemd/system # 系统管理员创建和管理的单元目录,优先级最高 /etc/systemd/system |
有了对systemd的基本认识后,下面就开始来介绍相关的操作命令。但是注意一点,systemd并不是一个命令,而是一组命令,涉及到系统管理的方方面面。
三、Unit管理命令(systemctl)
1)查看当前系统的所有Unit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 列出正在运行的Unit systemctl list-units # 列出所有Unit,包括没有找到配置文件的或者启动失败的 systemctl list-units --all # 列出所有没有运行的Unit systemctl list-units --all --state=inactive # 列出所有加载失败的Unit systemctl list-units --failed # 列出所有正在运行的、类型为service的Unit systemctl list-units --type=service |
四、unit.service管理命令(systemctl)
1)unit.service管理
使用systemcl命令可以控制服务,service命令和chkconfig命令依然可以使用,但是主要是出于兼容的原因,应该尽量避免使用。使用systemctl命令的时候,服务名字的扩展名可以写全,例如:
1 |
systemctl stop bluuetooth.service |
也可以忽略,例如:
1 |
systemctl stop bluetooth |
对于用户来说,最常用的是下面这些命令,用于启动和停止Unit(主要是service)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# 启动一个服务 systemctl start name.service # 关闭一个服务 systemctl stop name.service # 重启一个服务 systemctl restart name.service # 重载一个服务 systemctl reload name.service # 仅当服务运行的时候,重启服务 systemctl try-restart name.service # 杀死一个服务的所有子进程 systemctl kill name.service # 重载所有修改过的配置文件 systemctl daemon-reload # 允许服务开机启动 systemctl enable name.service # 禁止服务开机启动 systemclt disable name.service # 命令列出一个Unit的所有依赖 systemctl list-dependencies nginx.service # 显示某个Unit的所有底层参数 systemctl show httpd.service # 显示某个Unit的指定属性的值 systemctl show -p CPUShares httpd.service # 设置某个Unit的指定属性 systemctl set-property httpd.service CPUShares=500 |
2) 查看unit.service状态
1 2 3 4 5 6 7 8 |
# 显示系统状态 systemctl status # 显示单个Unit的状态 sysystemctl status bluetooth.service # 显示远程主机的某个Unit的状态 systemctl -H root@rhel7.example.com status httpd.service |
systemd提供管理远程系统
不光是可以管理本地系统,systemd还可以控制远程系统,管理远程系统主要是通过SSH协议,只有确认可以连接远程系统的SSH,在systemctl命令后面添加-H或者–host参数,加上远程系统的ip或者主机名就可以。
服务输出信息关键词解释:
1 2 3 4 5 6 |
Loaded #服务已经被加载,显示单元文件绝对路径,标志单元文件可用; Active #服务已经被运行,并且有启动时间信息; Main PID #与进程名字一致的PID,主进程PID; Status #服务的附件信息; Process #相关进程的附件信息; CGroup #进程的CGroup信息。; |
除了status命令,systemctl还提供了三个查询状态的简单方法,主要供脚本内部的判断语句使用。
1 2 3 4 5 6 7 8 |
# 显示某个Unit是否正在运行 systemctl is-active application.service # 显示某个Unit是否处于启动失败状态 systemctl is-failed application.service # 显示某个Unit服务是否建立了启动链接 systemctl is-enabled application.service |
五、unit.target管理命令(systemctl)
启动计算机的时候,需要启动大量的Unit。如果每一次启动,都要一一写明本次启动需要哪些 Unit,显然非常不方便。Systemd 的解决方案就是 Target。简单说,Target 就是一个 Unit 组,包含许多相关的 Unit 。启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit。从这个意义上说,Target 这个概念类似于”状态点”,启动某个 Target 就好比启动到某种状态。
传统的init启动模式里面,有 RunLevel 的概念,跟 Target 的作用很类似。不同的是,RunLevel 是互斥的,不可能多个 RunLevel 同时启动,但是多个 Target 可以同时启动。
target与runlevel对应关系?
在RHEL7之前的版本,使用运行级别代表特定的操作模式。运行级别被定义为七个级别,用数字0到6表示,每个级别可以启动特定的一些服务。RHEL7使用target替换运行基本。
systemd target使用target单元文件描述,target单位文件扩展名是.target,target单元文件的唯一目标是将其他systemd单元文件通过一连串的依赖关系组织在一起。举个例子,graphical.target单元,用于启动一个图形会话,systemd会启动像GNOME显示管理(gdm.service)、帐号服务(axxounts-daemon)这样的服务,并且会激活multi-user.target单元。相似的multi-user.target单元,会启动必不可少的NetworkManager.service、dbus.service服务,并激活basic.target单元。
RHEL7预定义了一些target和之前的运行级别或多或少有些不同。为了兼容,systemd也提供一些target映射为SysV init的运行级别,具体的对应信息如下:
target与runlevel的区别如下:
1)默认的RunLevel(在/etc/inittab文件设置)现在被默认的 Target 取代,位置是/etc/systemd/system/default.target,通常符号链接到graphical.target(图形界面)或者multi-user.target(多用户命令行)。
2)启动脚本的位置,以前是/etc/init.d目录,符号链接到不同的 RunLevel 目录 (比如/etc/rc3.d、/etc/rc5.d等),现在则存放在/lib/systemd/system和/etc/systemd/system目录。
3)配置文件的位置,以前init进程的配置文件是/etc/inittab,各种服务的配置文件存放在/etc/sysconfig目录。现在的配置文件主要存放在/lib/systemd目录,在/etc/systemd目录里面的修改可以覆盖原始设置。
怎样知道一个target需要哪些进程服务?
例如,可能想搞明白target单元“multi-user.target”究竟启用了哪些服务,使用以下命令:
1 2 3 |
[root@localhost ~]# systemctl show -p "Wants" multi-user.target Wants=tuned.service brandbot.path ksm.service systemd-ask-password-wall.path hypervkvpd.service NetworkManager.service systemd-user-sess |
除了Wants,还可以查看各种形式的依赖和被依赖信息:WantedBy、Requires、RequiredBy、Conflicts、ConflictedBy、Before、After。
unit.arget的管理命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 查看当前系统的所有Target systemctl list-unit-files --type=target # 查看一个Target包含的所有Unit systemctl list-dependencies multi-user.target # 查看启动时的默认Target systemctl get-default # 设置启动时的默认Target systemctl set-default multi-user.target # 切换target systemctl isolate multi-user.target |
切换Target时,默认不关闭前一个Target启动的进程,systemctl isolate命令改变这种行为,关闭前一个 Target 里面所有不属于后一个 Target 的进程。
systemd的救援模式和紧急模式
使用systemctl rescue进入救援模式,如果连救援模式都进入不了,可以进入紧急模式:
1 |
[root@localhost ~]# systtmctl emergency |
紧急模式进入做小的系统环境,以便于修复系统。紧急模式根目录以只读方式挂载,不激活网络,只启动很少的服务,进入紧急模式需要root密码。
六、电源管理命令(systemctl)
1 2 3 4 5 |
systemctl reboot #重启机器 systemctl poweroff #关机 systemctl suspend #待机 systemctl hibernate #休眠 systemctl hybrid-sleep #混合休眠模式(同时休眠到硬盘并待机) |
关机不是每个登录用户在任何情况下都可以执行的,一般只有管理员才可以关机。正常情况下系统不应该允许 SSH 远程登录的用户执行关机命令。否则其他用户正在工作,一个用户把系统关了就不好了。为了解决这个问题,传统的 Linux 系统使用 ConsoleKit 跟踪用户登录情况,并决定是否赋予其关机的权限。现在 ConsoleKit 已经被 systemd 的 logind 所替代。
logind 不是 pid-1 的 init 进程。它的作用和 UpStart 的 session init 类似,但功能要丰富很多,它能够管理几乎所有用户会话(session)相关的事情。logind 不仅是 ConsoleKit 的替代,它可以:
l 维护,跟踪会话和用户登录情况。如上所述,为了决定关机命令是否可行,系统需要了解当前用户登录情况,如果用户从 SSH 登录,不允许其执行关机命令;如果普通用户从本地登录,且该用户是系统中的唯一会话,则允许其执行关机命令;这些判断都需要 logind 维护所有的用户会话和登录情况。
l Logind 也负责统计用户会话是否长时间没有操作,可以执行休眠/关机等相应操作。
l 为用户会话的所有进程创建 CGroup。这不仅方便统计所有用户会话的相关进程,也可以实现会话级别的系统资源控制。
l 负责电源管理的组合键处理,比如用户按下电源键,将系统切换至睡眠状态。
l 多席位(multi-seat) 管理。如今的电脑,即便一台笔记本电脑,也完全可以提供多人同时使用的计算能力。多席位就是一台电脑主机管理多个外设,比如两个屏幕和两个鼠标/键盘。席位一使用屏幕 1 和键盘 1;席位二使用屏幕 2 和键盘 2,但他们都共享一台主机。用户会话可以自由在多个席位之间切换。或者当插入新的键盘,屏幕等物理外设时,自动启动 gdm 用户登录界面等。所有这些都是多席位管理的内容。ConsoleKit 始终没有实现这个功能,systemd 的 logind 能够支持多席位。
七、系统引导性能分析命令(systemd-analyze)
Systemd提供了工具用于识别和定位引导相关的问题或性能影响。systemd-analyze是一个内建的命令,可以用来检测引导过程。你可以找出在启动过程中出错的单元,然后跟踪并改正引导组件的问题。在下面列出一些常用的systemd-analyze命令。
1)查看详细的每个服务消耗的启动时间
1 2 |
[root@localhost ~]# systemd-analyze time Startup finished in 1.155s (kernel) + 4.991s (initrd) + 33.621s (userspace) = 39.767s |
2) 查看严重消耗时间的服务树状表
1 2 3 4 5 6 7 8 9 10 |
[root@localhost ~]# systemd-analyze critical-chain The time after the unit is active or started is printed after the "@" character. The time the unit takes to start is printed after the "+" character. └─multi-user.target @33.558s └─postfix.service @28.577s +4.200s └─network.target @28.530s └─network.service @26.534s +1.978s └─NetworkManager.service @25.098s +732ms └─firewalld.service @16.479s +8.596s └─basic.target @14.686s |
命令打印严重消耗时间的服务树状表,按照启动消耗的时间进行排序,时间消耗越多,越排到前面。@之后是服务激活或者启动的时间,+号之后是服务启动消耗的时间。个人理解@是从系统引导到服务启动起来的时间,是一个相对时间消耗,+是服务启动消耗的时间,是一个绝对时间消耗。
3)初始化开始到当前服务所花的时间排序
1 2 3 4 5 6 7 8 9 10 |
[root@localhost ~]# systemd-analyze blame 13.094s dev-mapper-centos\x2droot.device 8.596s firewalld.service 4.914s ModemManager.servic 4.754s systemd-udev-settle.service 4.658s kdump.service 4.200s postfix.service 3.642s tuned.service 3.570s libvirtd.service ……. |
会列出所有正在运行的单元,按从初始化开始到当前所花的时间排序,通过这种方式你就知道哪些服务在引导过程中要花较长时间来启动。
检查所有系统单元中是否有语法错误
1 |
[root@localhost ~]# systemd-analyze verify |
4)打印分析图及其他命令
1 |
[root@localhost ~]# systemd-analyze plot > boot.svg |
可以用来把整个引导过程写入一个SVG格式文件里。整个引导过程非常长不方便阅读,所以通过这个命令我们可以把输出写入一个文件,之后再查看和分析。下面这个命令就是做这个。
5)用分隔符产生当前服务
1 |
[root@localhost ~]# systemd-analyze dot |
6)以友好方式显示当前服务状态
1 |
[root@localhost ~]# systemd-analyze dump |
以上描述的这些管理功能仅仅是 systemd 的部分功能,除此之外,systemd 还负责系统其他的管理配置,比如配置网络,Locale 管理,管理系统内核模块加载等。
八、日志管理命令(journalctl)
Systemd 统一管理所有 Unit 的启动日志。带来的好处就是,可以只用journalctl一个命令,查看所有日志(内核日志和应用日志)。日志的配置文件是/etc/systemd/journald.conf。
journalctl功能强大,用法非常多。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# 查看所有日志(默认情况下 ,只保存本次启动的日志) journalctl # 查看内核日志(不显示应用日志) journalctl -k # 查看系统本次启动的日志 journalctl -b journalctl -b -0 # 查看上一次启动的日志(需更改设置) journalctl -b -1 # 查看指定时间的日志 journalctl --since="2012-10-30 18:17:16" journalctl --since "20 min ago" journalctl --since yesterday journalctl --since "2015-01-10" --until "2015-01-11 03:00" journalctl --since 09:00 --until "1 hour ago" # 显示尾部的最新10行日志 journalctl -n # 显示尾部指定行数的日志 journalctl -n 20 # 实时滚动显示最新日志 journalctl -f # 查看指定服务的日志 journalctl /usr/lib/systemd/systemd # 查看指定进程的日志 journalctl _PID=1 # 查看某个路径的脚本的日志 journalctl /usr/bin/bash # 查看指定用户的日志 journalctl _UID=33 --since today # 查看某个 Unit 的日志 journalctl -u nginx.service journalctl -u nginx.service --since today # 实时滚动显示某个 Unit 的最新日志 journalctl -u nginx.service -f # 合并显示多个 Unit 的日志 journalctl -u nginx.service -u php-fpm.service --since today # 查看指定优先级(及其以上级别)的日志,共有8级 # 0: emerg # 1: alert # 2: crit # 3: err # 4: warning # 5: notice # 6: info # 7: debug journalctl -p err -b # 日志默认分页输出,--no-pager 改为正常的标准输出 journalctl --no-pager # 以JSON格式(单行)输出 journalctl -b -u nginx.service -o json # 以JSON格式(多行)输出,可读性更好 journalctl -b -u nginx.serviceqq -o json-pretty # 显示日志占据的硬盘空间 journalctl --disk-usage # 指定日志文件占据的最大空间 journalctl --vacuum-size=1G # 指定日志文件保存多久 journalctl --vacuum-time=1years |
九、其他命令
1)localectl
localectl命令用于查看本地化设置。
1 2 3 4 5 6 |
# 查看本地化设置 localectl # 设置本地化参数 localectl set-locale LANG=en_GB.utf8 localectl set-keymap en_GB |
2)timedatectl
timedatectl命令用于查看当前时区设置。
1 2 3 4 5 6 7 8 9 10 |
# 查看当前时区设置 timedatectl # 显示所有可用的时区 timedatectl list-timezones # 设置当前时区 timedatectl set-timezone America/New_York timedatectl set-time YYYY-MM-DD timedatectl set-time HH:MM:SS |
3)loginctl
loginctl命令用于查看当前登录的用户。
1 2 3 4 5 6 7 8 |
# 列出当前session loginctl list-sessions # 列出当前登录用户 loginctl list-users # 列出显示指定用户的信息 loginctl show-user ruanyf |
4)hostnamectl
hostnamectl命令用于查看当前主机的信息。
1 2 3 4 5 |
# 显示当前主机的信息 hostnamectl # 设置主机名 hostnamectl set-hostname rhel7 |
完结。。。