systemd 的工具与技巧提示

来源:互联网 发布:用java开发微信企业号 编辑:程序博客网 时间:2024/06/16 03:23

(一)

我们在《在 Linux Deepin 上安装和使用 systemd》一篇中已经讨论过 systemd 在 Linux Deepin 上的安装与简单使用,这篇文章将对其使用方法进行更为详细的探讨,介绍 systemd 提供的工具与常见技巧。

systemd 的工具

如今,Fedora、OpenSUSE、Mandriva 及一些其他发行版使用 systemd 初始化工具(init tool)来启动系统。systemd 包含了自己的配置和诊断工具,在使用它处理系统启动问题时用到的技巧不同于 sysvinit。
systemd 初始化工具虽面世仅有两年,却已成为一些发行版中默认使用的初始化工具;一些其他的发行版把它包含进来,作为 upstart 和 sysvinit 的替代品。由于它与 upstart 和 sysvinit 的兼容特性,我们在使用这两个初始化工具的发行版里面熟悉的命令与技巧也适用于 systemd。但是,为了能够真正利用好这个新的初始化系统的功能,系统管理员也需要了解 systemd 的工具与参数。
给 systemd 传达命令的主要工具是 systemctl,它是一个命令行程序。该工具在改变配置文件或重新启动后台程序时需要 root 权限,但即使是非 root 用户也能下达一些诊断的命令。如果你在启动该命令时不加任何参数,你会看到一个系统启动时执行任务的“单位(unit)”列表,包括挂载及检测磁盘、启动后台服务及配置硬件。
对于未配置过系统服务的 Linux Deepin 12.06,在安装完 systemd 之后,systemctl 会列出约 140 个正在运行着的单位(active unit),可分为十类(如图)。

服务(service)单位是最重要的一类单位之一,因为它们管理着后台服务,而在使用 sysvinit 的发行版里面则一般使用初始化脚本来启动这些服务。挂载(mount)与自动挂载(automount)单位用来挂载文件系统。套接字(socket)单位用来创建套接字,并在访问套接字后,立即利用依赖关系间接地启动另一单位。你可以使用参数让 systemctl 只列出某个类型的单位,如所有的服务单位:

1
systemctl--type=service

systemd 自动将其输出结果递交给 less 显示;你不仅可以使用箭头键来上下滚动,也可以向右滚动,因为有时更多的信息会偶尔“藏”到那里。
列表中的第一栏是单位的名字,第二栏则表示该单位的定义是否已由 systemd 正确加载。第三栏则告诉我们该单位是否正在运行。如果你使用了 -a 参数,那么该程序将仅显示非正在运行的单位,即已安装但并未在启动时使用的单位,同时也包含引导系统未能正常加载的单位文件(原因很可能为该单位文件出现错误)。
第四栏则给出了当前状态:“exited”表示该进程已经无任何错误地完成,这种情况适用于一诸如进程在启动后并不在后台继续运行的情况,例如,在系统启动时由于考虑到兼容性因素执行在 sysvinit 里面常用的 /etc/rc.d/rc.local 文件的服务单位。“Running”表示正在后台运行的服务,如 cron、dbus、sshd 和 udev。
第五栏是对该单位的描述。标有“LSB”或“SYSV”的单位已由 systemd 自动创建以管理传统启动脚本。
不能启动或启动后崩溃的服务在第四栏中用红色标为“failed”(如果终端可以显示彩色)。你可以如下命令来察看该服务是何时崩溃的以及在服务程序结束后提供了什么错误代码:

1
systemctl statusntpd.service

对于一个新安装的 Linux Deepin 12.06,systemctl 会列出约50个服务型单位,包含文本终端的登陆进程(agetty)。因为 systemd 不同于 sysvinit, 它会像管理普通的后台服务一样以服务单位的形式对这些进程进行管理。

单位文件与目标(target)

单位的处理

创建单位用的系统配置文件位于 /lib/systemd/system/,但 /etc/systemd/system 目录下的同名文件会优先于前者。
单位文件的定义通常比传统的 sysvinit 脚本要短得多。例如,用于通过 NTP 来同步网络时间的服务只有短短几行:

1
2
3
4
5
6
7
8
[Unit]
Description=NetworkTime Service
[Service]
ExecStart=/usr/bin/ntpd-n -u ntp:ntp-g
[Install]
WantedBy=multi-user.target

所有的单位文件都包含由[Unit]开头的一节,其中包含一般设置与简短介绍。[Service]一节含有针对该服务要进行的任务的指定设置——对于 NTP 来说,仅需要启动该服务的命令行。如果需要用一个指定的命令来终止程序,你可以用 ExecStop= 来进行设置。这一步对于 NTP 守护进程是不需要的,因为根据 Unix 传统,它可以用一个简单的“SIGTERM”信号来结束。如果没有指定其他命令,这个命令会告诉 systemd 结束任务。
[Install]一节包含了 systemd 在(反)安装时要解释的说明;这里的 NTP 一例中,其内容意为在“多用户”目标激活时应当同步时间。

目标

“目标”单位的概念与 sysvinit 的运行级别相似;实际上,为考虑兼容性,systemd 甚至能够识别与目标对应的运行级别名称。所以,你可以在引导装载程序中的 kernel 一行中加入 single 这个参数;systemd 就会激活 rescue.target,提供一个相当于单用户模式的最小化界面。
在 systemd 中,多用户模式(即不使用图形化登陆界面就完全启动系统的模式)由 multi-user.target 表示,可以通过下面这个链接来将其设为默认启动目标:

1
ln -sf /lib/systemd/system/multi-user.target/etc/systemd/system/default.target

如果此后你确实需要默认启动图形化登陆界面,可用同样的方式来将 graphical.target 设为默认目标。这等同于传统初始化工具的运行级别 5。你也可以在引导装载程序中为 kernel 指定想要启动的目标单位:

1
systemd.unit=multi-user.target

如果想要在操作过程中激活一个不同的目标单位,你可以使用 systemctl 的 isolate 命令(需要 root 权限):

1
systemctl isolaterescue.target

切换为 rescue 目标对于管理任务来说很有用,systemd 这时会停止所有的用户登陆与后台服务,只有系统服务在运行,如监视逻辑卷的服务(lvm2-monitor)。有时,甚至这些服务也需要停止并重新安装,这时你可以使用 emergency.target 来进入紧急模式(emergency mode),这时只有命令提示符的进程以及内核线程在运行。


(二)

我们在《systemd 的工具与技巧提示(一)》一篇中介绍了 systemd 的工具 systemctl 及单位与目标的概念与相关操作。这一篇中我们将继续介绍 systemd 对于依赖的处理及与 systemd 直接或间接相关的故障排除方法。

依赖

需求

systemctl show 命令提供了一些关于正在运行的单位和它们正在执行的任务的内部信息,以及关于 systemd 依赖于哪些单位来启用多用户模式的信息。

1
systemctl show-p Wants multi-user.target

其他的目标也可能显示在输出中,如 multi-user.target 依赖于 basic.target。而后者又依赖于 sysinit.target,sysinit.target 依赖于 local-fs.target。这三个目标用于管理系统的基本配置,包括挂载文件系统和启动 udev。为指定对于基本目标(basic target)的依赖,单位配置文件 multi-user.target 包含了如下语句:

1
2
Requires=basic.target
After=basic.target

在使用 Requires 的同时指定 After 一行,systemd 就会知道它必须不仅启用该目标,而且需等待该目标完全启动后再继续进行其他任务。
Wants 是 Requires 的稍弱形式的替代语句,systemd 也会启用这些单位,但即使这些单位不能启动也会继续启动系统。这一类依赖也可以通过链接到单位文件来指定,单位文件位于含有该单位的路径、名称和一个 .wants的目录下。你可以使用 ls 或 systemctl 的 show 命令:

1
2
ls /*/systemd/system/multi-user.target.wants/
systemctlshow -pWants multi-user.target

关闭服务

如果你想要通过挂起 NTPD 服务单位来让系统在启动时不通过 NTP 来同步系统时间,你可以使用下面的方式:

1
systemctl disablentpd.service

在这里,systemctl 仅仅是移除了到 Wants 目录下面的服务单位的链接;同理,可用 systemctl enable 命令来创建一个链接以激活一项服务。也可以不使用 systemctl 而以手动创建(移除)链接的方式激活(挂起)单位。
如果一项服务是由传统的初始化脚本而不是单位来启动的,systemctl 则将这个激活要求递交给 update-rc.d 程序。如在 Linux Deepin 中安装 Apache 和使用 systemctl 激活它时就是这种情况。反过来, update-rc.d 也可将任务授权给 systemctl 来完成,但这只是个别情况,请读者最好不用或谨慎使用。
服务的激活与挂起在该服务下一次启动或系统关闭后生效;下面的命令用来立即启动一项服务:

1
systemctl startntpd.service

对于使用 sysvinit 的发行版,与之对应的命令是 service ntpd start。在 systemctl 命令之后使用 stop 参数来代替 start 则为停止一项服务。使用systemctl status 命令可以传达该单位的信息,如当前状态及与该单位的对应的配置文件。该程序也告诉我们该服务现在是否正在运行,如果正在运行的话,会显示运行了多长时间,以及有哪些进程属于它,并明晰地显示出主进程。

通过由 systemctl 创建的控制组可以很容易地找出是哪项服务启动了哪些进程。system-cgls 可显示由 systemd 创建的 cgroup 层次(hierarchy)。也可用ps命令显示组从属关系(group affiliation)

1
ps xaw-eo pid,args,cgroup

问题解决

停在启动行界面

如果在启动时出现可能与 systemd 直接或间接相关的问题,请用以下参数启动 kernel:

1
systemd.log_target=kmsgsystemd.log_level=debug

systemd 会识别这些参数并在终端提供全面的故障排除信息。同时,该信息也会保存在由 dmesg 创建的内核通知缓冲存储区(kernel notification buffer)以备过后分析。
命令行程序 poweroff、halt 及 reboot 是 systemd 的一部分,但也可以使用 systemctl 的命令关闭或重新启动系统。也可以这样重启系统:

1
systemctl kexec

在所有服务被终止后,systemd 告诉正在运行的内核直接启动一个预先配置好的 Linux 内核,这会让系统快速重新启动,因为它会直接跳过BIOS和引导装载程序,如果没有一个配置好的 kexec 内核,systemd 则会执行正常的重新启动过程。

深入探究

对于标准的管理任务来说,你通常只会接触到服务单位和目标单位;对于更深层的 systemd 功能,或是要在系统启动时做到像使用 sysvinit 和 upstart 的发行版使用脚本管理系统那样管理好系统启动,其他的单位就也显得很重要了。这些任务包括挂载 /etc/fstab 中指定的文件系统,激活交换分区及不定时清理临时文件目录。
对于其中的挂载任务,systemd 有一个自动挂载功能,可以为 /etc/fstab 中配置的挂载点创建虚拟挂载点(phseudo mount point)。虚拟挂载点直到存取时才真正挂载。在 /etc/fstab 中加入 comment=systemd.automount 一行可把任一挂载点变为自动挂载点。这样可以加快启动过程。这对于读取网络共享很有用,因为 WLAN 连接直到用户使用 NetworkManager 时才被建立。

寻找答案

systemctl 可以用来在不知道一服务的 PID 时告诉 systemd 去发出信号。比如,下面的命令会让 rsyslogd 进入调试模式(debug mode),当你再次输入这个命令时,该服务会停止:

1
systemctl kill--signal=USR1rsyslogd.service

如果你不指定发送哪一个信号,systemctl 会发送一个标准终止信号,会终止属于一服务的所有进程。
systemd-analyze 命令会告诉你系统启动所用时间及其中有多少时间是用在内核、initramfs及由 systemd 控制的用户级配置上。
如果你想更深入地查看后一因素,可使用 systemd-analyze blame 来获知各个单位的启动时间。如需知道关于启动过程的更为详细的信息,该程序可创建一个用图表展示单位启动的 SVG 文件:

1
systemd-analyzeplot >plot.svg


有时,这可以用来寻找过分拖长启动时间的单位。《Systemd for Administrators》系列博客的第七部分有一些关于如何正确阐释这些结果的提示。这一系列(目前有1、2部分)也包含了关于使用 systemd 的许多其他建议与注释。

  • Verifying Bootup
  • Which Service Owns Which Processes?
  • How Do I Convert A SysV Init Script Into A systemd Service File?
  • Killing Services
  • The Three Levels of “Off”
  • Changing Roots
  • The Blame Game
  • The New Configuration Files
  • On /etc/sysconfig and /etc/default
  • Instantiated Services
  • Converting inetd Services
  • Securing Your Services

Lennart Poettering的博客主页有关于该初始化系统的相关背景的许多其他的文章。另外,Pottering 在他的文章第三篇《Systemd Status Update》中列出了在过去1年半的时间里 systemd 的改动。