systemd v.s init
OpenSUSE 42.1 用systemd替代了init, 成为pid==1的进程。
为保证兼容性,系统中还存在/etc/init.d、/sbin/init;需要说明的是/sbin/init为/usr/lib/systemd/systemd的一个符号链接。
与/etc/init.d相对应,/etc/systemd的目录下是各个服务的配置文件。
对应关系
传统的init启动模式里面,有 RunLevel 的概念,跟 Target 的作用很类似
| SysV 启动级别 | Systemd target | 说明 |
|---|---|---|
| 0 | runlevel0.target, poweroff.target | 中断系统(halt) |
| 1, s, single | runlevel1.target, rescue.target | 单用户模式 |
| 2, 4 | runlevel2.target, runlevel4.target, multi-user.target | 用户自定义启动级别,通常识别为级别3 |
| 3 | runlevel3.target, multi-user.target | 多用户,无图形界面。用户可以通过终端或网络登录 |
| 5 | runlevel5.target, graphical.target | 多用户,图形界面。继承级别3的服务,并启动图形界面服务 |
| 6 | runlevel6.target, reboot.target | 重启 |
| emergency | emergency.target | 急救模式(Emergency shell) |
主要区别
- 1). runLevel在/etc/inittab中定义; systemd中为默认Target
/etc/systemd/system/default.target - 2). init启动脚本位于/etc/init.d, 链接到不同的 RunLevel 目录(/etc/rc3.d、/etc/rc5.d等); systemd中位于
/lib/systemd/system和/etc/systemd/system - 3). init进程的配置文件是/etc/inittab,各种服务的配置文件存放在/etc/sysconfig目录; systemd配置文件主要存放在/lib/systemd目录,在/etc/systemd目录里面的修改可以覆盖原始设置
- 4) RunLevel 是互斥的,不可能多个 RunLevel 同时启动,但是多个 Target 可以同时启动。
CheatSheet (from linoxide)

systemd架构图

systemd命令
systemd提供了一组命令,涉及到系统管理的各个方面。
systemd-analyze命令
systemd-analyze [OPTIONS...] {COMMAND} ...
Profile systemd, show unit dependencies, check unit files.
Commands:
time Print time spent in the kernel
blame Print list of running units ordered by time to init
critical-chain Print a tree of the time critical chain of units
plot Output SVG graphic showing service initialization
dot Output dependency graph in dot(1) format
set-log-level LEVEL Set logging threshold for manager
set-log-target TARGET Set logging target for manager
dump Output state serialization of service manager
verify FILE... Check unit files for correctness
journalctl命令
Systemd 统一管理所有 Unit 的启动日志。带来的好处就是,可以只用journalctl一个命令,查看所有日志(内核日志和应用日志)。
日志的配置文件是/etc/systemd/journald.conf
查看所有日志(默认情况下 ,只保存本次启动的日志)
sudo journalctl
查看内核日志(不显示应用日志)
sudo journalctl -k
查看系统本次启动的日志
sudo journalctl -bsudo journalctl -b -0
查看上一次启动的日志(需更改设置)
sudo journalctl -b -1
查看指定时间的日志
sudo journalctl --since="2012-10-30 18:17:16"sudo journalctl --since "20 min ago"sudo journalctl --since yesterdaysudo journalctl --since "2015-01-10" --until "2015-01-11 03:00"sudo journalctl --since 09:00 --until "1 hour ago"
显示尾部的最新10行日志
sudo journalctl -n
显示尾部指定行数的日志
sudo journalctl -n 20
实时滚动显示最新日志
sudo journalctl -f
查看指定服务的日志
sudo journalctl /usr/lib/systemd/systemd
查看指定进程的日志
sudo journalctl _PID=1
查看某个路径的脚本的日志
sudo journalctl /usr/bin/bash
查看指定用户的日志
sudo journalctl _UID=33 --since today
查看某个 Unit 的日志
sudo journalctl -u nginx.servicesudo journalctl -u nginx.service --since today
根据syslog的优先级获取日志
sudo journalctl -p err
cgroup相关
- 获取服务之前的cgroup关系
systemd-cgls - 获得运行中服务cgroup的资源统计
systemd-cgtop - 获得某个服务的CPU.Shares
systemctl show -p CPUShares httpd.service - 配置某个服务的CPU.Shares
systemctl set-property httpd.service CPUShares=512
服务管理
systemctl enable ntpdsystemctl disable ntpdsystemctl start ntpdsystemctl stop ntpdsystemctl restart ntpdsystemctl reload ntpdsystemctl is-enabled ntpdsystemctl is-active ntpdsystemctl status ntpd
系统启动
sudo systemctl rebootsudo systemctl poweroffsudo systemctl halt#CPU停止工作sudo systemctl suspendsudo systemctl hibernatesudo systemctl hybrid-sleep#交互式休眠sudo systemctl rescue
关于reboot
/sbin/reboot是到/bin/systemctl的符号链接。 systemctl中有关于argv[0]的判断, 如果是reboot的话则重启。对于shutdown等同理。
hostnamectl
查看或设置当前主机的信息。
localectl
查看或设置本地化设置。
timedatectl
查看或设置时间日期项。
loginctl
Send control commands to or query the login manager
Unit
Systemd将资源统称为Unit。
Unit 一共分成12种。
- Service unit:系统服务
- Target unit:多个 Unit 构成的一个组
- Device Unit:硬件设备
- Mount Unit:文件系统的挂载点
- Automount Unit:自动挂载点
- Path Unit:文件或路径
- Scope Unit:不是由 Systemd 启动的外部进程
- Slice Unit:进程组
- Snapshot Unit:Systemd 快照,可以切回某个快照
- Socket Unit:进程间通信的 socket
- Swap Unit:swap 文件
- Timer Unit:定时器
systemctl list-units命令可以查看当前系统的所有 Unit
systemctl list-unitssystemctl list-units --allsystemctl list-units --all --state=inactivesystemctl list-units --failedsystemctl list-units --type=service
Unit状态
systemctl status命令用于查看系统状态和单个 Unit 的状态
systemctl statussystemctl status nigix.servicesystemctl is-active application.servicesystemctl is-failed application.servicesystemctl is-enabled application.service
Unit管理
- 立即启动一个服务
sudo systemctl start apache.service - 立即停止一个服务
sudo systemctl stop apache.service - 重启一个服务
sudo systemctl restart apache.service - 杀死一个服务的所有子进程
sudo systemctl kill apache.service - 重新加载一个服务的配置文件
sudo systemctl reload apache.service - 重载所有修改过的配置文件
sudo systemctl daemon-reload - 显示某个 Unit 的所有底层参数
systemctl show httpd.service
Unit 依赖关系
Unit之间可以存在依赖关系。
systemctl list-dependencies nginx.servicesystemctl list-dependencies --all nginx.serviceTarget会展开
Unit 的配置文件
每一个 Unit 都有一个配置文件,告诉 Systemd 怎么启动这个 Unit. 配置文件位于/etc/systemd/system/,
多是符号链接(到/lib/systemd/system中的文件).
sudo systemctl enable nginx相当于
sudo ln -s /lib/systemd/system/nginx.service /etc/systemd/system/multi-user.target.wants/nginx.service
文件状态
systemctl list-unit-files命令用于列出所有配置文件
systemctl list-unit-files --type=service列出指定类型的配置文件
配置文件的状态STATE, 一共有四种:
enabled: 已建立启动链接disabled: 没建立启动链接static: 该配置文件没有[Install]部分(无法执行),只能作为其他配置文件的依赖masked: 该配置文件被禁止建立启动链接
从配置文件的状态无法看出Unit是否正在运行. 使用systemctl status
一旦修改配置文件, 就要让systemd重新加载配置文件, 然后重新启动; 否则修改不会生效
sudo systemctl daemon-reloadsudo systemctl restart nginx.service
配置文件的格式
systemctl cat 命令可以用来查看配置文件: 例如 systemctl cat ssh显示ssh.service
# /lib/systemd/system/ssh.service
[Unit]
Description=OpenBSD Secure Shell server
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run
[Service]
EnvironmentFile=-/etc/default/ssh
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
[Install]
WantedBy=multi-user.target
Alias=sshd.service
配置文件分成几个区块. 每个区块的第一行是用方括号表示的区别名(比如[Unit])
注意 配置文件的区块名和字段名都是大小写敏感的
每个区块包含若干条键值对. 键值对的等号两侧不能有空格
[Unit]:启动顺序与依赖关系
用来定义Unit的元数据,以及配置与其它Unit的关系. 它的主要字段:
- Description:简短描述
- Documentation:文档地址
- Requires:当前 Unit 依赖的其他 Unit,如果它们没有运行,当前 Unit 会启动失败
- Wants:与当前 Unit 配合的其他 Unit,如果它们没有运行,当前 Unit 不会启动失败
- BindsTo:与Requires类似,它指定的 Unit 如果退出,会导致当前 Unit 停止运行
- Before:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之后启动
- After:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之前启动
- Conflicts:这里指定的 Unit 不能与当前 Unit 同时运行
- Condition...:当前 Unit 运行必须满足的条件,否则不会运行
Assert...:当前 Unit 运行必须满足的条件,否则会报启动失败
[Service]定义如何启动当前服务
用来 Service 的配置, 只有 Service 类型的 Unit 才有这个区块. 它的主要字段:
- Type:定义启动时的进程行为。它有以下几种值。
- Type=simple:默认值,执行ExecStart指定的命令,启动主进程
- Type=forking:ExecStart字段将以fork()方式启动,此时父进程将会退出,子进程将成为主进程
- Type=oneshot:类似于simple,但只执行一次,Systemd 会等它执行完,才启动其他服务
- Type=dbus:当前服务通过D-Bus启动
- Type=notify:类似于simple,启动结束后会发出通知信号,然后 Systemd 再启动其他服务
- Type=idle:若有其他任务执行完毕,当前服务才会运行
- ExecStart:启动当前服务的命令
- ExecStartPre:启动当前服务之前执行的命令
- ExecStartPost:启动当前服务之后执行的命令
- ExecReload:重启当前服务时执行的命令
- ExecStop:停止当前服务时执行的命令
- ExecStopPost:停止当其服务之后执行的命令
所有的启动设置之前,都可以加上一个连词号-,表示"抑制错误",即发生错误的时候,不影响其他命令的执行。 - RestartSec:自动重启当前服务间隔的秒数
- Restart:定义何种情况 Systemd 会自动重启当前服务,可能的值包括always(总是重启)、on-success、on-failure、on-abnormal、on-abort、on-watchdog
- TimeoutSec:定义 Systemd 停止当前服务之前等待的秒数
- Environment:指定环境变量
EnvironmentFile:指定当前服务的环境参数文件。该文件内部的key=value键值对,可以用$key的形式,在当前配置文件中获取。KillMode:定义 Systemd 如何停止 sshd 服务。KillMode字段可以设置的值如下。control-group(默认值):当前控制组里面的所有子进程,都会被杀掉process:只杀主进程mixed:主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号none:没有进程会被杀掉,只是执行服务的 stop 命令。Restart:定义了退出后,Systemd的重启方式。 上面的例子中,Restart设为on-failure,表示任何意外的失败,就将重启sshd。如果 sshd 正常停止(比如执行systemctl stop命令),它就不会重启。 可以设置的值如下。no(默认值):退出后不会重启on-success:只有正常退出时(退出状态码为0),才会重启on-failure:非正常退出时(退出状态码非0),包括被信号终止和超时,才会重启on-abnormal:只有被信号终止和超时,才会重启on-abort:只有在收到没有捕捉到的信号终止时,才会重启on-watchdog:超时退出,才会重启always:不管是什么退出原因,总是重启 对于守护进程,推荐设为on-failure。对于那些允许发生错误退出的服务,可以设为on-abnormal。
[Install]定义如何安装这个配置文件,即怎样做到开机启动。
定义如何启动,以及是否开机启动。它的主要字段:
WantedBy:一个或多个 Target,systemctl enable时,其符号链接会放入/etc/systemd/system/Target名.wants
RequiredBy:一个或多个 Target,systemctl enable时,符号链接会放入/etc/systemd/system/Target名.required
Alias:当前 Unit 可用于启动的别名
Also:当前 Unitenable 时,会被同时enable的Unit
Target
Target 是一组Unit。启动某个 Target 的时候Systemd 就会启动里面所有的 Unit.
查看当前系统的所有 Target
systemctl list-unit-files --type=target
查看一个 Target 包含的所有 Unit
systemctl list-dependencies multi-user.target
查看启动时的默认 Target
systemctl get-default
设置启动时的默认 Target
sudo systemctl set-default multi-user.target
切换 Target 时,默认不关闭前一个 Target 启动的进程,
关闭前一个 Target 里面所有不属于后一个 Target 的进程
sudo systemctl isolate multi-user.target
Target 的配置文件
systemctl cat multi-user.target
# /lib/systemd/system/multi-user.target
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Multi-User System
Documentation=man:systemd.special(7)
Requires=basic.target
Conflicts=rescue.service rescue.target
After=basic.target rescue.service rescue.target
AllowIsolate=yes
Requires字段:要求basic.target一起运行。Conflicts字段:冲突字段。如果rescue.service或rescue.target正在运行,multi-user.target就不能运行,反之亦然。After:表示multi-user.target在basic.target 、 rescue.service、 rescue.target之后启动,如果它们有启动的话。AllowIsolate:允许使用systemctl isolate命令切换到multi-user.target。
如何使用 systemd 中的定时器
systemd timers可以实现定时执行任务.(vs cron jobs)
准备
man systemd.serviceman systemd.timerman systemd.target
任务
每个1小时运行脚本 /home/linux/jobscheduler
步骤
- 创建service文件
/etc/systemd/system/js.service[Unit] Description=JobScheduler [Service] Type=simple ExecStart=/home/linux/jobscheduler 创建timer文件
/etc/systemd/system/js.timer[Unit] Description=Runs JobScheduler every hour [Timer] OnBootSec=10min OnUnitActiveSec=1h Unit=js.service [Install] WantedBy=multi-user.target授权运行timer
systemctl enable js.timer systemctl start js.timer
可以创建一个target,来组织一个timer调度多个service