我知道以下线程据说是一个回答它。但答案不是一般意义上的答案。它说明了某一特定情况下的问题,但不是一般情况下的问题。
我的问题是:有没有办法调试排序周期通用的方式?例如:是否有一个命令可以描述循环以及将一个单元连接到另一个单元的原因?
例如,我有以下内容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,但事实并非如此,至少不明显。是否有一个命令可以演示此链接的来源?一般来说,是否有一个命令可以找到循环并显示循环中每个链接的起源?
答案1
您可以使用命令可视化循环systemd-analyze verify
,systemd-analyze dot
并且图形可视化 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
链接:
答案2
是否有一个命令可以演示此链接的来源?
您可以做的最接近的是systemctl show -p Requires,Wants,Requisite,BindsTo,PartOf,Before,After cvol.service
,它将显示给定单元的结果(有效)依赖项列表。
是否有一个命令可以找到循环并显示循环中每个链接的起源?
据我所知,没有这样的命令。实际上,systemd 没有提供任何帮助调试排序周期的功能(叹气)。
据journalctl称,cvol.service想要basic.service,但事实并非如此,至少不明显。
首先,需求依赖关系(Wants=
、Requires=
等BindsTo=
)独立于排序依赖关系(Before=
和After=
)。你在这里看到的是一个订购Wants=
依赖循环,即与etc无关。
其次,某些类型的单元之间创建了许多“默认依赖关系”。他们由以下人员控制DefaultDependencies=
该部分中的指令[Unit]
(即默认启用)。
特别是,除非显式禁用此指令,否则任何.service
-type 单元都会获得隐式Requires=basic.target
和After=basic.target
依赖项,这正是您所看到的。这记录在系统服务(5)。
答案3
步骤1:对default.target运行验证命令
systemd-analyze verify default.target
步骤 2:观察消息中提到的服务或目标“systemd 通过删除作业打破订购周期”并显示其完整的依赖项列表
systemctl show -p Requires,Wants,Requisite,BindsTo,PartOf,Before,After <service or target name mentioned in the "breaking cycle" message>
步骤 3:查看服务或目标文件中通常定义的“after”和“before”组
/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 被定义为出站,并导致 systemd 无限循环。
这治愈很简单——换个词“后”到“前”如有必要,反之亦然。