调试systemd中订购周期的通用方法


23

我知道下面的线程,并且应该是答案。除了答案,不是一般意义上的答案。它说明了在一种特定情况下但不是一般情况下的问题。

我的问题是:有没有一种通用的调试订购周期的方法?例如:是否有一个描述循环的命令以及将一个单元链接到另一个单元的命令?

例如,我有以下内容journalctl -b(请忽略日期,我的系统没有RTC与之同步时间):

Jan 01 00:00:07 host0 systemd[1]: Found ordering cycle on sysinit.target/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on local-fs.target/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on cvol.service/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on basic.target/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on sockets.target/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on dbus.socket/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on sysinit.target/start
Jan 01 00:00:07 host0 systemd[1]: Breaking ordering cycle by deleting job local-fs.target/start
Jan 01 00:00:07 host0 systemd[1]: Job local-fs.target/start deleted to break ordering cycle starting with sysinit.target/start

其中cvol.service(已引入并破坏周期的那个)是:

[Unit]
Description=Mount Crypto Volume
After=boot.mount
Before=local-fs.target

[Service]
Type=oneshot
RemainAfterExit=no
ExecStart=/usr/bin/cryptsetup open /dev/*** cvol --key-file /boot/***

[Install]
WantedBy=home.mount
WantedBy=root.mount
WantedBy=usr-local.mount

根据journalctl所述,cvol.service想要basic.service,除了它不是,至少不是很明显。是否有一个命令可以演示此链接的来源?通常,是否有一条命令可以找到周期并显示周期中每个链接的起源?

Answers:


20

是否有一个命令可以演示此链接的来源?

您能做的最接近的是 systemctl show -p Requires,Wants,Requisite,BindsTo,PartOf,Before,After cvol.service,它将显示给定单元的结果(有效)依赖项列表。

是否有一个命令可以找到周期并显示周期中每个链接的起源?

据我所知,没有这样的命令。实际上systemd没有提供任何帮助来调试订购周期(叹气)。

根据journalctl所述,cvol.service想要basic.service,除了它不是,至少不是很明显。

首先,要求依赖(Wants=Requires=BindsTo=等等)是独立的顺序依赖(的Before=After=)。您在这里看到的是一个排序依赖性周期,即与Wants=等等无关。

其次,在某些类型的单元之间创建了许多“默认依赖项”。它们由DefaultDependencies=[Unit]节中的指令控制(默认情况下启用)。

特别是,除非明确禁用此伪指令,否则任何.service-type单元都会隐式包含Requires=basic.targetAfter=basic.target相关性,这正是您所看到的。这记录在systemd.service(5)中


您引用的命令效果很好,并且确实显示了对basic.target的依赖。很遗憾,缺少systemctl的工具集,但是哦,这是一个新项目
galets 2015年

2
@galets:从我的经验来看,这种短缺的例子很少。也许有一天,我会避免增加周期报告程序的冗长性,在日志中添加一些有用的信息。同时,实际上,您可以systemd-analyze verify UNIT用来检查设备的正确性。在后台,此命令将创建一个虚拟systemd实例,并尝试加载给定的UNIT作为初始事务(好像是default.target)。这不会显示任何新信息(与日志相比),但是至少您不必在启用该设备的情况下重新启动即可查看它是否发生故障。
intelfx 2015年

系统要求增强(RFE):增加循环报告程序的详细信息
adrelanos

20

您可以用可视化的命令周期systemd-analyze verifysystemd-analyze dotGraphViz的 dot工具:

systemd-analyze verify default.target |&
perl -lne 'print $1 if m{Found.*?on\s+([^/]+)}' |
xargs --no-run-if-empty systemd-analyze dot |
dot -Tsvg >cycle.svg

您应该会看到以下内容:

在此处输入图片说明

在这里,您可以看到周期: c.service->b.service->a.service->c.service

Color legend: 
    black     = Requires
    dark blue = Requisite
    dark grey = Wants
    red       = Conflicts
    green     = After

链接:


systemd-analyze verify在debian 8安装中不存在。
sjas

@sjas,systemd-analyze verify 可用v216。尝试一下systemd-verify。是否存在?
Evgeny Vereshchagin


1
systemd-analyze verify default.target本身在显示循环方面做得不错……
Gert van den Berg

0

步骤1:为default.target运行验证命令

systemd-analyze verify default.target

步骤2:观察消息“通过删除作业中断系统订购周期”消息中提到的服务或目标,并显示其完整的依存关系列表

systemctl show -p Requires,Wants,Requisite,BindsTo,PartOf,Before,After <service or target name mentioned in the "breaking cycle" message>

步骤3:查看通常在以下位置定义的服务或目标文件中的“之后”和“之前”组

/lib/systemd/system

并找到众所周知的服务或目标,这些服务或目标是顺序的,但按出站顺序排列。

例:

dbus.service

通常是市场“之后”

multi-user.target

但是“之前”

sockets.target

通过调用可以很容易地观察到这种依赖性

systemctl list-dependencies default.target

但是如果文件

/lib/systemd/system/dbus.service

包含以下行:

Before=multi-user.target

要么

After=sockets.target

或同时出现这两种情况,则意味着dbus.service被定义为出站,这将导致系统循环。

解决方法很简单- 必要时将单词“ After”更改为“ Before”,反之亦然。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.