可以通过systemd
命令查询开机是否完成
systemctl is-system-running
如果启动尚未完成,则返回错误代码。如果想等待启动完成,当然可以重新运行该命令,直到它返回0
。
我认为“一定有更好的方法”来做到这一点。有没有一种不依赖轮询的方法?
我想这样做的原因是我目前有一个脚本,可以将固件下载到设备,然后重新启动,并希望监视它以查看它是否可以正常启动。目前,我通过systemctl is-system-running
SSH 发出命令来执行此操作,直到它返回,0
或者在启动应该完成的时间内没有返回。我当然希望这件事尽快结束。
答案1
可以等待这个条件而不在循环中轮询这个命令,但不幸的是它并不那么简单......
systemd 将发布一个启动完成信号一旦启动完成,就可以在 D-Bus 上进行监视,因此可以对其进行监视并获得通知。
这里有一个简单的dbus-wait
工具可以监视 D-Bus 上的信号。
我设法使用以下命令等到启动完成:
dbus-wait org.freedesktop.systemd1.Manager StartupFinished
这种方法的问题在于存在竞争条件。如果首先我检查系统是否正在运行(使用systemctl is-system-running
)并看到它仍在“启动”,然后决定等待信号,那么到时候可能dbus-wait
会连接到总线并开始等待信号,那么 systemd 只是完成启动并已在总线中发布此信号,这将dbus-wait
等待一个不会发生的事件并最终超时......
另一方面,应该可以以一种不受竞争条件影响的方式来实现这一点,首先注册事件的监视,然后检查属性,如果它仍未设置为“正在运行”,则运行事件循环等待信号。
我实现了上述方法并将其建议给上游systemd。我的建议是允许运行systemctl is-system-running --wait
为此目的运行(但这可能最终会使用不同的语法(可能是单独的命令)进入 systemd。)可以在以下位置找到新 systemd 功能的建议:公关#9796在 systemd 项目上。 (一旦它被接受并合并,我将更新这个答案。)
更新:公关#9796刚刚合并到 systemd 中,因此从 systemd v240 开始,可以使用以下命令等待启动完成:
systemctl is-system-running --wait
答案2
等待单位文件
这是一个可以满足您需求的原型。首先是一个 systemd 单元文件waity.service
:
$ cat /etc/systemd/system/waity.service
[Unit]
Description=Waity Service
After=systend-user-sessions.service
[Service]
Type=simple
ExecStart=/opt/bin/waity.sh
等待脚本
它运行一个脚本来询问 systemd 以查看它是否完成启动:
$ cat /opt/bin/waity.sh
#!/bin/bash
while $(sleep 10); do
echo "waiting for systemd to finish booting..."
if systemctl is-system-running | grep -qE "running|degraded"; then
break
fi
done
echo "systemd finished booting..."
echo "...do something else..."
运行示例
现在启用该服务:
$ systemctl enable --now waity.service
现在,当我们启动系统时,该服务将处于 10 秒的循环中,直到它看到 的is-system-running
操作systemctl
返回 arunning
或degraded
状态。其中任何一个都表明系统已完成启动。
该服务的状态:
$ systemctl status waity.service
● waity.service - Waity Service
Loaded: loaded (/etc/systemd/system/waity.service; static; vendor preset: disabled)
Active: inactive (dead)
Aug 03 22:06:01 centos7 waity.sh[4519]: Got unexpected auxiliary data with level=1 and type=2
Aug 03 22:06:01 centos7 waity.sh[4519]: Got unexpected auxiliary data with level=1 and type=2
Aug 03 22:06:01 centos7 waity.sh[4519]: systemd finished booting...
Aug 03 22:06:01 centos7 waity.sh[4519]: ...do something else...
Aug 03 22:06:01 centos7 systemd[1]: Child 4519 belongs to waity.service
Aug 03 22:06:01 centos7 systemd[1]: waity.service: main process exited, code=exited, status=0/SUCCESS
Aug 03 22:06:01 centos7 systemd[1]: waity.service changed running -> dead
Aug 03 22:06:01 centos7 systemd[1]: waity.service: cgroup is empty
Aug 03 22:06:01 centos7 systemd[1]: Collecting waity.service
Aug 03 22:07:17 centos7 systemd[1]: Collecting waity.service
我们可以在上面的消息中看到我们已检测到启动完成:
Aug 03 22:06:01 centos7 waity.sh[4519]: systemd finished booting...
Aug 03 22:06:01 centos7 waity.sh[4519]: ...do something else...
到那时我们就可以做...do something else...
.一旦这一切完成,该服务将进入完成/停止状态。