简洁版本
开机时确切地重复相同的系统,有时启动信息以
[ ...] systemd[1]: Set hostname to <liab>.
[ ...] systemd[1]: Mounted /.
[ ...] systemd[1]: Mounted /host.
[ ...] systemd[1]: Cannot add dependency job for unit display-manager.service, ignoring: Unit display-manager.service failed to load: No such file or directory.
而其他时候他们开始
[ ...] systemd[1]: Set hostname to <liab>.
[ ...] systemd[1]: Unit host.mount is bound to inactive unit dev-sda1.device. Stopping, too.
[ ...] systemd[1]: Cannot add dependency job for unit display-manager.service, ignoring: Unit display-manager.service failed to load: No such file or directory.
并且与前一种情况相比,稍后缺少几个服务启动消息。我该如何找到原因?
长版本
由于我正在构建信息亭设置,因此这里的设置非常非标准。
创建根文件系统
我没有运行完整的 Ubuntu 安装程序,而是从开始debootstrap --variant=minbase … vivid
,添加一些软件包并在 chroot 中自定义内容。然后使用该 chroot 创建 squashfs,作为我的设置的根文件系统。
从 initramfs 挂载
该只读 squashfs 包含在某些主机文件系统上的文件中,可能是 vfat 或 ext4 或其他。它由 initramfs 挂载。为了实现这一点,我有一个文件,其中/etc/initramfs-tools/conf.d/
设置LOOP
为根文件系统中 squashfs 的路径,还设置了LOOPFSTYPE=squashfs
。squashfs 包含一个名为 的空目录/host
,这会导致主机文件系统/usr/share/initramfs-tools/scripts/local
转到mount -o move
该目录。因此,当 initramfs 将控制权移交给 systemd 时,我将拥有/
并/host
挂载并准备使用。
文件系统
我的/etc/fstab
读物
# <fs> <mountpoint> <type> <opts> <dump/pass>
/dev/loop0 / squashfs nodev,noauto,ro 0 0
/host/boot /boot auto bind,ro 0 0
none /run tmpfs noexec,nodev,nosuid 0 0
none /tmp tmpfs noexec,nodev,nosuid 0 0
none /var/tmp tmpfs noexec,nodev,nosuid 0 0
none /var/log tmpfs noexec,nodev,nosuid,size=5% 0 0
none /home/liab tmpfs nodev,nosuid,uid=liab,gid=liab,mode=0770 0 0
所以我有一个条目,/
但它被标记了,noauto
因为 initramfs 已经处理了这个问题,对吧?尽管如此,那里列出的选项显然会在某个时候应用,这是我偶然发现的nosuid
。我没有条目,因为/host
我不知道要使用哪个设备。initramfs 可以从引导加载程序配置中找出该设备,但我不想将任何文件系统 ID 或类似的东西包含在 squashfs 中,因为相同的 squashfs 应该可以从不同的主机文件系统中使用。
启动
目前,我只在 qemu 中启动此设置。我使用它的-snapshot
选项,使用我的用户帐户无法修改的文件系统。因此,我确信底层文件系统映像没有任何变化,因此任何行为差异都一定是某种非确定性的结果,很可能是某种竞争条件。我的 qemu 调用目前读起来有点像这样:
qemu-system-x86_64 \
-serial stdio \
-kernel …/boot/vmlinuz-3.19.0-15-generic \
-append 'console=ttyS0 root=/dev/sda1' \
-initrd …/initrd.img-3.19.0-15-generic \
-snapshot -hda …/hdimg
因此,我将看到一个最终会显示 GUI 的屏幕,但我还会将启动消息打印到启动 qemu 的终端上,客户内核会将其视为串行控制台。正是这些控制台消息让我担心。
显然,initramfs 很好地完成了它的工作,然后将控制权移交给 systemd。Systemd 依次显示问候语、设置主机名,然后显然遵循两个可能路径之一。
第一条路径导致出现/
和 的挂载消息/host
。从消息 开始[ OK ] Reached target Swap.
,许多启动步骤将由[ OK ]
以绿色打印的 OK 开头的消息行指示。稍后,可能是为了响应Starting Journal Service
,dmesg
类似时间戳的消息会消失,大概是重定向到某个日志守护程序,只剩[ OK ]
下那些消息。
第二条路径没有在早期提到重新安装。相反,它写入/
。那里的对应于内核参数;将其更改为某个文件系统 ID 会相应地更改错误消息。在此启动过程中从未出现任何彩色线条。相应的行似乎完全消失了,即使带时间戳的行记录了许多相同步骤的开始和完成。这些步骤的顺序不同。这意味着一旦日志服务启动,我就再也看不到任何消息了。/host
Unit host.mount is bound to inactive unit dev-sda1.device. Stopping, too.
dev-sda1.device
root=/dev/sda1
到目前为止,我还不能说出这些不同的启动方式会给正在运行的系统带来什么其他实际差异。但我不喜欢我无法理解的非确定性行为。
调试
为了调试这种情况,我添加了systemd.log_target=console systemd.log_level=debug
内核命令行。这样做的一个不良影响是,在 udev 事件处理期间,initramfs 执行会打印一百万行。日志的相关部分似乎如下。如果我得到绿色的OK
赞,它会显示
Using notification socket /run/systemd/notify
Successfully created private D-Bus server.
dev-loop0.device changed dead -> tentative
dev-sda1.device changed dead -> tentative
Trying to enqueue job host.mount/start/fail
Installed new job host.mount/start as 1
Installed new job -.slice/start as 4
Installed new job system.slice/start as 3
Installed new job dev-sda1.device/start as 5
Installed new job -.mount/start as 2
Enqueued job host.mount/start as 1
host.mount changed dead -> mounted
Job host.mount/start finished, result=done
-.mount changed dead -> mounted
Job -.mount/start finished, result=done
Activating default unit: default.target
Failed to load configuration for all.target: No such file or directory
Failed to load configuration for bluetooth.service: No such file or directory
Failed to load configuration for hal.service: No such file or directory
Failed to load configuration for kbd.service: No such file or directory
Failed to load configuration for console-screen.service: No such file or directory
Failed to load configuration for plymouth-quit-wait.service: No such file or directory
Failed to load configuration for plymouth-quit.service: No such file or directory
Failed to load configuration for display-manager.service: No such file or directory
Trying to enqueue job graphical.target/start/isolate
Cannot add dependency job for unit display-manager.service, ignoring: Unit display-manager.service failed to load: No such file or directory.
Job dev-sda1.device/start finished, result=canceled
Installed new job syslog.socket/start as 90
如果我没有看到这些行,它会显示
Using notification socket /run/systemd/notify
Successfully created private D-Bus server.
host.mount changed dead -> mounted
Unit host.mount is bound to inactive unit dev-sda1.device. Stopping, too.
Trying to enqueue job host.mount/stop/fail
Installed new job host.mount/stop as 1
Enqueued job host.mount/stop as 1
-.mount changed dead -> mounted
dev-loop0.device changed dead -> tentative
dev-sda1.device changed dead -> tentative
Activating default unit: default.target
Failed to load configuration for bluetooth.service: No such file or directory
Failed to load configuration for hal.service: No such file or directory
Failed to load configuration for kbd.service: No such file or directory
Failed to load configuration for console-screen.service: No such file or directory
Failed to load configuration for all.target: No such file or directory
Failed to load configuration for plymouth-quit-wait.service: No such file or directory
Failed to load configuration for plymouth-quit.service: No such file or directory
Failed to load configuration for display-manager.service: No such file or directory
Trying to enqueue job graphical.target/start/isolate
Cannot add dependency job for unit display-manager.service, ignoring: Unit display-manager.service failed to load: No such file or directory.
Job host.mount/stop finished, result=canceled
Startup finished in 13.247s (kernel) + 2.322s (userspace) = 15.569s.
Installed new job systemd-modules-load.service/start as 48
不确定这是否有用。