Centos 7 更新後不能進入登陸介面的問題排查
週末隨手 yum update 了一下, 結果就悲劇了。重啟後, plymouth 結束後的螢幕上只留下灰灰的背景和游標。由於這次更新包含核心更新,我嘗試在 grub 介面上選擇更新之前的核心版本啟動,結果仍然不起作用。難道只能重灌系統了?有些不甘心,選擇 centos 做桌面就是看中其穩定性(當然不足之處就是軟體版本比較舊),何況電腦上裝了雙系統,還有 window 10, 萬不得已不想走這條路。於是搜尋加折騰弄了大半天,萬幸問題解決了。排查過程頗具有典型意義,因此做個記錄。
首先,用 centos 的安裝盤做引導載入檔案系統,以下命令等同於 system V init 下修改 init level:
systemctl set-default multi-user.target
該命令效果等價於:
rm /etc/systemd/system/default.target
ln -s /usr/lib/systemd/system/multi-user.target /etc/systemd/system/default.target
重啟後正常登陸系統 bash shell。看來問題不大隻是圖形介面有問題。這時輸入命令:
systemctl show --no-pager -p "Wants" graphical.target
可以獲得 level5 啟動依賴的 daemon, 並不是很多,在我的電腦上返回如下:
Wants=systemd-readahead-replay.service systemd-update-utmp-runlevel.service rtkit-daemon.service network.service systemd-readahead-collect.service jexec.service gdm.service accounts-daemon.service
逐個啟動以上 daemon 排查,有時候問題就可以定位到某個 daemon 上。但是我的所有 daemon 都可以啟動,切換到圖形介面仍然沒有登陸介面(可以使用 alt + ctrl + F1, alt + ctrl + F2 在圖形介面與 terminal 之間切換)。這時就要檢視日誌了,在使用 systemd 的系統上可以使用 journalctl 命令,常用命令如下:
journalctl -k # 顯示 kernel 資訊,這個就等於 dmesg 了
journalctl -u NetworkManager.service # 顯示該 unit 的相關資訊
journalctl _PID=1 # 顯示 pid 等於 1 的程序相關資訊
journald 包含了系統從 boot 到現在涵蓋 kernel 和 unit 的所有日誌資訊,可以說是集 dmesg 和 syslog 之大成。其中的 error 會被紅色高亮顯示,不過有些 error 並不影響系統使用,比如自帶的開源驅動在 A 卡下總有這麼兩條錯誤。最終問題定位到 gnome-shell, gnome-shell 的 main.js 竟然丟擲了異常導致其退出,而且似乎是語法上的錯誤, gnome 的開發者應該不會犯如此低階的錯誤。眾所周知近年來 js 語法更新得很快,會不會是 gnome-shell 的版本與 js runtime 的版本不匹配呢?gnome 使用的 js runtime 對應 gjs 包,使用命令:
yum history list
yum history package-list gjs
yum history package-list gnome-shell
發現 gjs 在最近的一次更新中確實更新了,但 gnome-shell 沒有!!!這是怎麼回事呢?這時博主才想起更新的時候有依賴包衝突,當時根據提示跳過了部分包:
yum update --skip-broken
這樣問題最終被定位:由於沒有完整更新造成程式執行錯誤。找到問題就好辦了,只要解決依賴包衝突然後完整更新就可以了。再敲一次 yum 更新命令顯示衝突包是 epel 庫中的 webkitGtk,base 庫中自己就有 webkitGtk4 所以放心大膽刪了。然後 yum update 重啟,系統總算又回來了。
排查過程中在 level3 與 level5 之間切換了好幾次,查到可以在 grub 介面中切換。當 grub 選擇作業系統介面出現後,按 e 出現編輯介面,移動到 linux16 開始的一行在最後新增 3,按 ctrl + x 啟動。這樣也不用每次修改 default.target 了,比較方便。