系统:带有 EFI 启动的 Ubuntu 20.04。
解释一下我为什么需要这个
我配置了两个swap
分区:
- 第二个 HDD 上有一个主交换区。用于休眠。(休眠功能最好在 HDD 上使用,以延长 SSD 的使用寿命。)
- SSD 上的第二个交换分区与系统一起。这是当我使用 SSD 作为单个磁盘时的情况 - 当第二个 HDD 被移除和丢失时。在这种情况下,我只希望系统正常工作 - 即使没有休眠功能(或使用 SSD 上的交换分区)。
我做了什么:
- 在硬盘上创建交换分区。
- 将其 UUID 设置为 resume for
Grub
。
/etc/default/grub
:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash resume=UUID=25d5d4af-736a-4232-a4bb-492499bc1038"
- 将两个交换分区设置为
fstab
优先于 HDD 上的交换分区以及nofail
和x-systemd.device-timeout=3s
选项。此选项适用于缺少 HDD 的情况。如果没有此选项并且缺少 HDD,系统会在启动过程中挂起 90 秒。
/etc/fstab
交换分区的配置:
#swap on HDD
UUID=25d5d4af-736a-4232-a4bb-492499bc1038 none swap nofail,pri=20,x-systemd.device-timeout=3s 0 0
#swap on SDD
UUID=e78a171a-3c52-4cd1-b86a-17709f4b49d9 none swap pri=10 0 0
我遇到了什么问题:
当 SSD 和 HDD 一起连接到笔记本电脑时,一切都很好。当 HDD 在系统启动过程中丢失时,Grub
会尝试在 HDD 上查找带有交换分区,并因此挂起约 33 秒。
系统启动后,在日志中出现以下关于等待丢失的硬盘(我故意删除的)和交换分区超时的消息:
/var/log/boot.log:[ESC[0;1;31m TIME ESC[0m] Timed out waiting for device ESC[0;1;39m/dev/disk/by-uuid/46e39f74-e1b3-4705-9bac-84ee2593b4d
4ESC[0m.
/var/log/syslog:Feb 23 14:23:26 Device-2 kernel: [ 0.032426] Kernel command line: BOOT_IMAGE=/boot/vmlinuz-5.13.0-28-generic root=UUID=a59635ec-2cef-4396-bdf3-be7e4b23fc73 ro quiet splash resume=UUID=25d5d4af-736a-4232-a4bb-492499bc1038 vt.handoff=7
/var/log/syslog:Feb 23 14:56:14 Device-2 systemd[1]: dev-disk-by\x2duuid-25d5d4af\x2d736a\x2d4232\x2da4bb\x2d492499bc1038.device: Job dev-disk-by\x2duuid-25d5d4af\x2d736a\x2d4232\x2da4bb\x2d492499bc1038.device/start timed out.
我想要的是:
设置等待丢失硬盘的超时时间不超过 5 秒。现在系统默认设置为 30-33 秒。
我尝试了以下:
- 在配置中找到超时属性
Grub
。/etc/default/grub
可以指定两个相关选项: GRUB_HIDDEN_TIMEOUT
GRUB_RECORDFAIL_TIMEOUT
但它们不适用于这种情况。有关此选项的信息可在此处找到:
我尝试分析Grub
in的代码/etc/grub.d/
,发现这样的超时可能在系统启动配置中指定 - in 。我尝试在配置systemd
中找到相应的超时选项:systemd
sudo grep -iR timeout /etc/systemd/
/etc/systemd/system/rescue.target.wants/grub-initrd-fallback.service:TimeoutSec=0
/etc/systemd/system/network-online.target.wants/NetworkManager-wait-online.service:ExecStart=/usr/bin/nm-online -s -q --timeout=30
/etc/systemd/system/emergency.target.wants/grub-initrd-fallback.service:TimeoutSec=0
/etc/systemd/system/multi-user.target.wants/ua-reboot-cmds.service:TimeoutSec=0
/etc/systemd/system/multi-user.target.wants/unattended-upgrades.service:TimeoutStopSec=1800
/etc/systemd/system/multi-user.target.wants/grub-initrd-fallback.service:TimeoutSec=0
/etc/systemd/system/multi-user.target.wants/snapd.recovery-chooser-trigger.service:# blocks the service startup until a trigger is detected or a timeout is hit
/etc/systemd/system/sleep.target.wants/grub-initrd-fallback.service:TimeoutSec=0
/etc/systemd/system.conf:#DefaultTimeoutStartSec=90s
/etc/systemd/system.conf:#DefaultTimeoutStopSec=90s
/etc/systemd/system.conf:#DefaultTimeoutAbortSec=
/etc/systemd/user.conf:#DefaultTimeoutStartSec=90s
/etc/systemd/user.conf:#DefaultTimeoutStopSec=90s
/etc/systemd/user.conf:#DefaultTimeoutAbortSec=
/etc/systemd/logind.conf:#HoldoffTimeoutSec=30s
尝试将选项的值从 30 秒更改为 5 秒:
/etc/systemd/system/network-online.target.wants/NetworkManager-wait-online.service:ExecStart=/usr/bin/nm-online -s -q --timeout=5
/etc/systemd/logind.conf:#HoldoffTimeoutSec=5s
但这并未产生预期的结果。
我还尝试对交换分区进行相同的设置labels
,并使用此标签(而不是 UUID)指定恢复交换分区/dev/disk/by-label/...
。但在这种情况下,无法确定将使用两者中的哪个交换分区来从休眠状态加载系统。
我发现了类似的问题:
如何设置 systemd 启动作业“dev-md125.device”的超时(mdadm)
但其中没有systemd
关于如何配置 HDD 超时的详细信息。
这里有示例如何TimeoutStartSec
设置httpd.service
是否可以在系统启动期间指定 HDD 安装的超时时间?
谢谢。
答案1
就我而言,相同量的延迟(30 秒)是由于 initramfs 脚本中的愚蠢逻辑造成的:
local slumber=30
case $DPKG_ARCH in
powerpc|ppc64|ppc64el)
slumber=180
;;
*)
slumber=30
;;
esac
if [ "${ROOTDELAY:-0}" -gt $slumber ]; then
slumber=$ROOTDELAY
fi
上面忽略了 rootdelay,它小于“slumber”(这个名字和代码一样神奇)。
要修复此问题你应该:
- 添加内核启动参数
rootdelay=3
(编辑/etc/default/grub
)并运行update-grub
; - 使用以下命令修补你的 initramfs 脚本:
--- /usr/share/initramfs-tools/scripts/local 2023-09-25 22:47:50.000000000 +0300
+++ /usr/share/initramfs-tools/scripts/local 2024-02-06 03:35:29.442516895 +0300
@@ -64,9 +64,7 @@
slumber=30
;;
esac
- if [ "${ROOTDELAY:-0}" -gt $slumber ]; then
- slumber=$ROOTDELAY
- fi
+ slumber=${ROOTDELAY:-$slumber}
case "$dev_id" in
UUID=*|LABEL=*|PARTUUID=*|/dev/*)
- 更新 initrd 映像:
update-initramfs -k 6.7.3-060703-generic -c
或者你可以保存update-initrd
到你的/boot
:
#!/bin/bash
kv=${1#initrd.img-}
kv=${kv#vmlinuz-}
img="initrd.img-$kv"
update-initramfs -k $kv -c
lsinitramfs $img > /boot/$img.txt
- 如果您使用的是 Debian,并且不想在
initramfs-tools-core
更新时覆盖上述补丁,请执行以下操作:
cd /usr/share/initramfs-tools/scripts
dpkg-divert --rename --divert $_/local.orig $_/local
所有上述命令都必须在 root 权限下执行(显然,这样我就不会愚蠢地用sudo
命令弄乱它们)。