
我的 Ubuntu 17.04 啟動失敗,我想調試它。
啟動隨機失敗,我相信這是由於競爭條件造成的。
我可以要求systemd
不要並行化任何任務,這樣我就可以看看這是否會導致引導失敗?
答案1
解決方法:手動運行服務
我曾經有一個啟動時崩潰。就我而言,崩潰是在達到basic.target
目標之後但之前multi-user.target
,所以我想找出哪個服務啟動multi-user.target
導致了崩潰。
首先,我安排啟動以basic.target
新增 root shell。您可以永久執行此操作(假設您成功啟動!)
systemctl set-default basic.target
systemctl enable debug-shell
該debug-shell
服務在 tty 9 上運行 root shell。
systemd.unit=basic.target systemd.debug-shell
透過在內核命令列中新增參數可以獲得相同的效果。例如,在 Grub 中,將命令列編輯為類似的內容
linux /vmlinuz-4.13.0-38-generic root=/dev/mapper/crypt-root ro systemd.unit=basic.target systemd.debug-shell
在這個 shell 中,我執行了以下腳本來一一啟動服務。請注意,這在很大程度上未經測試(我運行了一次,它在有問題的服務上按預期崩潰了)。
#!/bin/sh
wants=$(systemctl show -p Wants multi-user.target | sed 's/^Wants=//' | tr ' ' '\n' | sort)
log=/var/tmp/multi-user-steps-$(date +%Y%m%d-%H%M%S)
log () {
echo "$* ..." | tee -a "$log"
sync
"$@"
ret=$?
echo "$* -> $ret" | tee -a "$log"
sync
return $ret
}
# systemd services
for service in $wants; do
log systemctl start $service
sleep 2
done
# upstart services
for conf in /etc/init/*.conf; do
service=${conf##*/}; service=${service%.conf}
log service ${service} start
sleep 2
done
# sysvinit services
for service in /etc/rc3.d/S*; do
log ${service} start
sleep 2
done
新增額外的依賴項
下面的腳本聲明了對 systemd 單元的「之前」依賴關係,這些單元是給定目標的直接依賴關係,以強制它們按特定順序運行。您可能想在multi-user.target
或上運行它basic.target
。
注意這個腳本一般不起作用因為它沒有考慮現有的依賴關係:它可能會導致依賴循環。正確的腳本應該收集現有的依賴關係並進行拓撲排序。我已經解決了我的問題,所以我不想再繼續解決它了;我將其發布,以防有人想要對其進行調整以適應他們的需求。
另請注意,這不會影響 Upstart 和 SysVinit 服務。
/etc
在運行之前先備份! (我強烈建議使用等等管理員.)
#!/bin/sh
set -e
if [ $# -eq 0 ] || [ "$1" = "--help" ]; then
cat <<EOF
Usage: $0 TARGET
Linearize the dependencies of a systemd target so it starts deterministically.
This scripts adds systemd unit files called linearize-for*.conf containing
extra Before= dependencies for each dependency of TARGET.
EOF
fi
service_dir=/etc/systemd/system
target=$1
wants=$(systemctl show -p Wants "$target" | sed 's/[^= ]*=//' |
tr ' ' '\n' | sort)
previous=
for want in $wants; do
[ -d "$service_dir/$want.d" ] || mkdir "$service_dir/$want.d"
cat <<EOF >"$service_dir/$want.d/linearize-for-${target%.*}.conf"
[Unit]
Before=$previous
EOF
previous=$want
done