一、systemd的由来
Linux一直以来采用init进程但是init有两个缺点:
1、启动时间长。Init进程是串行启动,只有前一个进程启动完,才会启动下一个进程。(这也是CentOS5的主要特征)
2、启动脚本复杂。Init进程只是执行启动脚本,不管其他事情。脚本需要自己处理各种情况,这使得脚本变得很长而且复杂。
Init:
Centos 5 Sys init 是启动速度最慢的,串行启动过程,无论进程相互之间有无依赖关系。
Centos6 Upstart init 相对启动速度快一点有所改进。有依赖的进程之间依次启动而其他与之没有依赖关系的则并行同步启动。
Centos7 Systemd 与以上都不同。所有进程无论有无依赖关系则都是并行启动(当然很多时候进程没有真正启动而是只有一个信号或者说是标记而已,在真正利用的时候才会真正启动。)
二、systemd
Systemd为了解决上文的问题而诞生。它的目标是,为系统的启动和管理提供一套完整的解决方案。根据linux惯例,字母d是守护进程(daemon) 的缩写。Systemd名字的含义就是 守护整个系统。
Centos 7里systemd代替了init,成为了系统的第一个进程。PID为1.其他所有的进程都是它的子进程。Systemd 的优点是功能强大,使用方便,缺点是体系庞大,非常复杂。事实上,现在还有很多人反对使用 Systemd,理由就是它过于复杂,与操作系统的其他部分强耦合,违反"keep simple, keep stupid"的Unix 哲学。
Systemd 架构图
三、服务管理
1、systemctl
Systemctl是systemd的主要命令,用于管理系统。
Centos 7 :service unit
注意:能兼容早期的服务脚本
命令格式
#systemctl COMMAND name.service
重启系统
# systemctl reboot
关闭系统,切断电源
# systemctl poweroff
CPU停止工作
# systemctl halt
暂停系统
# systemctl suspend
让系统进入冬眠状态
# systemctl hibernate
让系统进入交互式休眠状态
# systemctl hybrid-sleep
启动进入救援状态(单用户状态)
# systemctl rescue
启动服务
#service name start ==> systemctl start name.service
停止服务
#service name stop ==> systemctl stop name.service
重启服务
#service name restart ==> systemctl restart name.service
查看服务状态
#service name status ==> systemctl status name.service
条件式重启:已启动才重启,否则不做操作
#service name condrestart ==> systemctl tryrestart name.service
重载或重启服务:先加载,再启动
#systemctl reload-or-restart name.service
重载或条件式重启服务:
#systemctl reload-or-try-restart name.service
禁止自动和手动启动:
#systemctl mask name.service
取消禁止:
#systemctl unmask name.service
2、服务查看:
查看所有服务的开机自启状态:
chkconfig --list ==> systemctl list-unit-files --type service
用来列出该服务在哪些运行级别下启用和禁用
chkconfig sshd –list ==>ls /etc/systemd/system/*.wants/sshd.service
查看服务是否开机自启:
systemctl is-enabled name.service
其它命令:
查看服务的依赖关系:
systemctl list-dependencies name.service
杀掉进程:
systemctl kill 进程名
显示某个 Unit 的所有底层参数
# systemctl show httpd.service
显示某个 Unit 的指定属性的值
# systemctl show -p CPUShares httpd.service
设置某个 Unit 的指定属性
# sudo systemctl set-property httpd.service CPUShares=500
3、服务状态:
显示状态
systemctl list-unit-files --type service –all
loaded:Unit 配置文件已处理
active(running)一次或多次持续处理的运行
active(exited)成功完成一次性的配置
active(waiting)运行中,等待一个事件
inactive不运行
enabled开机启动
disabled开机不启动
static开机不启动,但可被另一个启用的服务激活
4、hostnamectl
hostnamectl命令用于查看当前主机的信息。
显示当前主机的信息
# hostnamectl
设置主机名。
# hostnamectl set-hostname rhel7
5、localectl
localectl命令用于查看本地化设置。
查看本地化设置
# localectl
# 设置本地化参数。
# localectl set-locale LANG=en_GB.utf8
# localectl set-keymap en_GB
6、 timedatectl
123456789 timedatectl
timedatectl命令用于查看当前时区设置。
查看当前时区设置
显示所有可用的时区
# timedatectl list-timezones
# 设置当前时区
$# timedatectl set-timezone America/New_York
# timedatectl set-time YYYY-MM-DD
# timedatectl set-time HH:MM:SS
7、loginctl
loginctl命令用于查看当前登录的用户。
# 列出当前session
# loginctl list-sessions
# 列出当前登录用户
# loginctl list-users
# 列出显示指定用户的信息
# loginctl show-user (ruanyf) 用户
四、unit
Systemd可以管理系统中所有资源。不同的资源统称为unit(单位)。Unit表示不同类型的systemd对象,通过配置文件进程标识和配置;文件中主要包含了系统服务、监听socket、保存的系统快照以及其它与init相关的信息。
1、Unit类型
Unit一共分为12种。
Sysstemctl –t help 查看unit类型
Service unit:文件扩展名为.Service,用于定义系统服务
Target unit : 文件名扩展为.target,用于模拟实现“运行级别”
Device unit :.device ,用于定义文件内核识别设备
Mount unit: .mount 定义文件系统挂载点。
Socket unit: .socket, 用于标识进程间通信用的socket文件,也可在系统启动时,延迟启动服务,实现按需启动
Snapshot unit: .snapshot, 管理系统快照
Swap unit: .swap, 用于标识swap设备
Automount unit: .automount,文件系统的自动挂载点
Path unit: .path,用于定义文件系统中的一个文件或目录使用,常用于当文件系统变化时,延迟激活服务,如:spool目录
Scope unit :不是由systemd启动的外部进程
Slice unit :进程组
Timer unit :定时器
2、systemctl list-units命令可以查看当前系统的所有 Unit 。
列出正在运行的 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
3、unit状态
systemctl status命令用于查看系统状态和单个 Unit 的状态。
显示系统状态
#systemctl status
显示单个 Unit 的状态
# sysystemctl status bluetooth.service
显示远程主机的某个 Unit 的状态
# systemctl -H root@rhel7.example.com status httpd.service
除了status命令,systemctl还提供了三个查询状态的简单方法,主要供脚本内部的判断语句使用。
显示某个 Unit 是否正在运行
# systemctl is-active application.service
显示某个 Unit 是否处于启动失败状态
# systemctl is-failed application.service
显示某个 Unit 服务是否建立了启动链接
# systemctl is-enabled application.service
4、依赖关系
Unit 之间存在依赖关系:A 依赖于 B,就意味着 Systemd 在启动 A 的时候,同时会去启动 B。
#systemctl list-dependencies命令列出一个 Unit 的所有依赖。
# systemctl list-dependencies nginx.service
上面命令的输出结果之中,有些依赖是 Target 类型(详见下文),默认不会展开显示。如果要展开 Target,就需要使用--all参数。
# systemctl list-dependencies --all nginx.service
五、unit配置文件
1、概述
每一个 Unit 都有一个配置文件,告诉 Systemd 怎么启动这个 Unit 。
Systemd 默认从目录/etc/systemd/system/读取配置文件。但是,里面存放的大部分文件都是符号链接,指向目录/usr/lib/systemd/system/,真正的配置文件存放在那个目录。
systemctl enable httpd.service命令用于在上面两个目录之间,建立符号链接关系。(Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.)等同于 ln -s /usr/lib/systemd/system/httpd.service /etc/systemd/system/multi-user.target.wants/httpd.service。当然systemdctl diable httpd.service 则相当于删除这个软连接。
/usr/lib/system/system:每个服务最主要的启动脚本设置,类似于之前的/etc/init.d/
/run/system/system:系统执行过程中所产生的服务脚本,与上面目录优先运行。
/etc/systemd/system:管理员建立的执行脚本,类似于/etc/rc.d/rcN.d/Sxx的功能,比上面目录优先运行。
2、配置文件状态
systemctl list-unit-files命令用于列出所有配置文件。
列出所有配置文件
#systemctl list-unit-files
列出指定类型的配置文件
#systemctl list-unit-files --type=service
systemctl list-unit-files该命令会输出一个列表,从中可以看到每个配置文件的状态。
Unit config filestatus
lvm2-lvmetad.service disabled
lvm2-lvmetad.socket enabled
lvm2-lvmpolld.service disabled
lvm2-lvmpolld.socket enabled
这个列表显示每个配置文件的状态,一共有四种。
enabled:已建立启动链接
disabled:没建立启动链接
static:该配置文件没有[Install]部分(无法执行),只能作为其他配置文件的依赖
masked:该配置文件被禁止建立启动链接
注意,从配置文件的状态无法看出,该 Unit 是否正在运行。这必须执行前面提到的systemctl status命令。
# systemctl status httpd.service
3、配置文件格式
1)unit配置文件格式
[Unit]
Description=backup /etc
Requires=atd.service
[Service]
Type=simple
ExecStart=/bin/bash -c "echo /testdir/bak.sh|at now"
[Install]
WantedBy=multi-user.target
[unit] :定义与Unit类型无关的通用选项;用于提供unit的描述信息、 unit行为及依赖关系等
[Service]:与特定类型相关的专用选项;此处为Service类型
[Install]:定义由“ systemctl enable”以及"systemctl disable“命令在实现服务启用或禁用时用到的一些选项
2、Unit段的常用选项:Description:简短描述
Description:描述信息
After:定义unit的启动次序,表示当前unit应该晚于哪些
unit启动,其功能与Before相反
Requires:依赖到的其它units,强依赖,被依赖的units无法激活时,当前unit也无法激活
Wants:依赖到的其它units,弱依赖
Conflicts:定义units间的冲突关系
BindsTo:与Requires类似,它指定的 Unit 如果退出,会导致当前 Unit 停止运行
Before:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之后启动
Conflicts:这里指定的 Unit 不能与当前 Unit 同时运行
Condition...:当前 Unit 运行必须满足的条件,否则不会运行
Assert...:当前 Unit 运行必须满足的条件,否则会报启动失败
3、service常用的选项
Type:定义影响ExecStart及相关参数的功能的unit进程启动类型
simple:默认值,这个daemon主要由ExecStart接的指令串来启动,启动后常驻于内存中
forking:由ExecStart启动的程序透过spawns延伸出其他子程序来作为此daemon的主要服务。原生父程序在启动结束后就会终止。
oneshot:与simple类似,不过这个程序在工作完毕后就结束了,不会常驻在内存中
dbus:与simple类似,但这个daemon必须要在取得一个D-Bus的名称后,才会继续运作.因此通常也要同时设定BusNname= 才行
notify:在启动完成后会发送一个通知消息。还需要配合NotifyAccess 来让 Systemd 接收消息
idle:与simple类似,要执行这个daemon必须要所有的工作都顺利执行完毕后才会执行。这类的daemon通
常是开机到最后才执行即可的服务。
EnvironmentFile:环境配置文件
ExecStart:指明启动unit要运行命令或脚本的绝对路径
ExecStartPre: ExecStart前运行
ExecStartPost: ExecStart后运行
ExecRsload: 重启当前服务时执行的命令
ExecStopPost:停止当前服务之后执行的命令
ExecStartSec:自动重启当前服务间隔的秒数
ExecStop:指明停止unit要运行的命令或脚本
Restart:当设定Restart=1 时,则当次daemon服务意外终止后,会再次自动启动此服务。
TimeoutSec:定义 Systemd 停止当前服务之前等待的秒数。
Environment:指定环境变量。
4、install 常用选项
Install段的常用选项:
Alias:别名,可使用systemctl command Alias.service
RequiredBy:被哪些units所依赖,强依赖
WantedBy:被哪些units所依赖,弱依赖
Also:安装本服务的时候还要安装别的相关服务
注意:对于新创建的unit文件,或者修改了的unit文件,要通知systemd重载此配置文件,而后可以选择重启。
# systemctl daemon-reload
# systemctl daemon-reload
#systemctl restart httpd.service
更加详细的unit配置文件格式 请参考官方文档
https://www.freedesktop.org/software/systemd/man/systemd.unit.html
六、Target
启动计算机的时候,需要启动大量的 Unit。如果每一次启动,都要一一写明本次启动需要哪些 Unit,显然非常不方便。Systemd 的解决方案就是 Target。
简单说,Target 就是一个 Unit 组,包含许多相关的 Unit 。启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit。从这个意义上说,Target 这个概念类似于"状态点",启动某个 Target 就好比启动到某种状态。
传统的init启动模式里面,有 RunLevel 的概念,跟 Target 的作用很类似。不同的是,RunLevel 是互斥的,不可能多个 RunLevel 同时启动,但是多个 Target 可以同时启动。
1、Target命令
查看当前系统的所有 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 时,默认不关闭前一个 Target 启动的进程, systemctl isolate 命令改变这种行为,
关闭前一个 Target 里面所有不属于后一个 Target 的进程 systemctl isolate multi-user.target
2、Target与传统 RunLevel 的对应关系如下。
Traditional runlevel New target name Symbolically linked to...
Runlevel 0 | runlevel0.target -> poweroff.target
Runlevel 1 | runlevel1.target -> rescue.target
Runlevel 2 | runlevel2.target -> multi-user.target
Runlevel 3 | runlevel3.target -> multi-user.target
Runlevel 4 | runlevel4.target -> multi-user.target
Runlevel 5 | runlevel5.target -> graphical.target
Runlevel 6 | runlevel6.target -> reboot.target
3、它与init进程的主要差别如下。
(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目录里面的修改可以覆盖原始设置。
七、日志管理
Systemd 统一管理所有 Unit 的启动日志。带来的好处就是,可以只用journalctl一个命令,查看所有日志(内核日志和应用日志)。日志的配置文件是/etc/systemd/journald.conf。
1、journalctl功能强大,用法非常多。
查看所有日志(默认情况下 ,只保存本次启动的日志)
# 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
2、查看指定优先级(及其以上级别)的日志,共有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