常規故障排除

出自 Arch Linux 中文维基

本文介紹了一些常規的故障排除方法。有關特定應用程序的問題,請參閱該特定程序的 wiki 頁面。

常用手段[編輯 | 編輯原始碼]

這篇文章的某些內容需要擴充。

原因: 考慮到本頁面的標題,應該要提及一些基本的「無腦的」解決方案,比如進行冷啟動、更新到最新版本等…… (在 Talk:常規故障排除 中討論)

出現的錯誤消息請務必閱讀,這一點很重要。有時可能很難獲得正確的錯誤消息(比如出錯的是圖形應用程序)。

  1. 在終端中運行應用程序,這樣可以查看輸出。
    1. 如果仍然沒有足夠的信息進行調試,請增加輸出的詳細度(通常加上參數 --verbose/-v/-V--debug/-d)。
    2. 如果沒有這樣的參數,可能是要在應用程序的配置文件中指定調試模式。
    3. 應用程序可能會有日誌文件,日誌文件通常位於 /var/log$HOME/.cache$HOME/.local
    4. 如果沒有辦法增加輸出的詳細度,那麼運行 strace 和類似的命令總是可行的。
  2. 檢查 日誌。錯誤也可能在日誌中留下痕跡,特別是當這個程序依賴於其他程序時。
    1. dmesg 從內核環形緩衝區讀取日誌。當磁盤由於某種原因無法訪問時這很有用,但這也可能導致日誌不完整,因為內核環形緩衝區的大小是有限的。如果可以的話儘量使用 journalctl
    2. journalctldmesg 有着更多的過濾選項,且默認使用人類可讀的時間戳。
  3. 建議檢查相關應用的問題跟蹤列表,看看這是不是已知問題,以及是否存在解決方案。
    1. 應用通常是有問題跟蹤列表的,具體取決於上游的選擇,有時應用還有論壇,甚至有 IRC 頻道。
    2. Arch Linux bugtracker 主要用於打包 bug。

額外支援[編輯 | 編輯原始碼]

如果需要額外支援,你可以在 the forumsIRC 上提問。

當要求貼出 完整 的 輸出 / 日誌 時,不能僅僅貼出你認為的重要部分。信息來源應該包括:

  • 所有涉及到的命令的完整輸出,不要只選擇你認為相關的東西。
  • systemd 的 日誌
    • 要獲得更廣泛的輸出,請使用 systemd.log_level=debug 引導參數,但這會產生大量的輸出,因此僅在確實需要時才啟用它。
    • 不要使用 -x 參數,因為這會使輸出混亂,讓它難以閱讀。
    • 除非需要上次啟動的日誌,否則請使用 -b 參數。不指定這個參數可能會導致日誌很大,甚至超過在線剪貼板的允許大小。
  • 相關的配置文件
  • 相關的驅動程序
  • 相關軟件包的版本
  • 內核日誌:journalctl -kdmesg(都需要 root 權限)。
  • Xorg:所用的 顯示管理器 的設置也決定了 Xorg 的日誌位置。
    • Xorg.log 可能在以下位置之一:系統日誌、/var/log/$HOME/.local/share/xorg/
    • 一些顯示管理器,如 LightDM,可能會在它自己的日誌目錄裡面也放一份 Xorg.log
  • Pacman:如果最近一次更新導致了問題,可以查看 /var/log/pacman.log
    • 使用 pacman--debug 參數也很有效。

最好將上述收集到的信息放到一個 在線剪貼板 裡。

在線剪貼板將返回一個鏈接,你可以把它貼到論壇或 IRC。

此外,在提問前最好複習一下 如何正確報告問題

系統啟動問題[編輯 | 編輯原始碼]

這篇文章的某些內容需要擴充。

原因: 根據 Arch:Talk:Installation guide#Buggy graphics driver,或許應該加上在硬件上嘗試 nomodeset 的內容? (在 Talk:常規故障排除 中討論)

診斷系統啟動問題時,了解問題出在啟動的哪一階段很重要。

  1. 固件(UEFI 或 BIOS)
    1. 往往只有非常基礎的調試工具。
    2. 確保 安全啟動 已關閉。
  2. 引導加載器
    1. 此處最容易引發故障的因素是修改了內核參數。
  3. initramfs
    1. 通常能提供一個 emergency shell。
    2. 在 shell 中可以用 dmesg 或 journal,取決於構建時選擇的鈎子。
  4. 實際系統
    1. 根據故障的嚴重程度,可能只需要調用 調試控制台 就行了。

如果某一階段的調試工具無法修復損壞的組件,請嘗試使用 包含最新 Arch Linux ISO 的U盤

控制台的輸出信息[編輯 | 編輯原始碼]

在啟動過程完成以後,屏幕會被清空並顯示登錄提示符,這使得用戶無法看到初始化過程中的輸出和其中的錯誤信息。這一默認特性可以使用接下來幾節中的方法進行修改。

請注意,無論選擇下面哪個方法,在啟動後通過 journalctl -kdmesg 都可以顯示內核消息,用於檢查錯誤。要顯示本次啟動的所有日誌,請使用 journalctl -b

輸出流控制[編輯 | 編輯原始碼]

以下是適用於大多數終端模擬器的基本操作,包括虛擬終端 (VC):

  • Ctrl+s 暫停輸出。
  • Ctrl+q 繼續輸出。

這樣不僅會暫停輸出,而且會暫停嘗試打印到終端的程序,即暫停輸出時會阻塞 write() 調用。 如果你的 init 進程出現凍結,請確保系統控制台沒有暫停。

要查看已經顯示過的錯誤信息,參見 Getty#將引導消息保留在 tty1 上

打印更多內核消息[編輯 | 編輯原始碼]

在啟動時大部分內核消息是隱藏的,添加不同的內核參數即可打印出更多消息,最簡單的有這些參數:

  • debug,有如下效果:
    • 內核會提高它的控制台 日誌級別,這樣內核日誌緩衝區中的所有消息都將打印到控制台。[1]
    • systemd 會提高它的日誌級別,這會記錄下調試信息,這些信息在其他地方是不會生成的。[2]
  • ignore_loglevel,對於內核來說它和 debugloglevel=8 (debug 對應的級別是 7)有相同的效果,但在啟動後期日誌級別不會提高。

在特定情況下可以添加的參數還有這些:

  • earlyprintk=vga,keep 打印啟動過程中最早期的內核消息,用在還沒顯示輸出就崩潰的情況下。在 UEFI 系統上需要把 vga 改成 efi
  • log_buf_len=16M 將分配一個更大的 (16 MiB) 內核日誌緩衝區,確保調試輸出不會被覆蓋。

生成更多內核調試信息[編輯 | 編輯原始碼]

#打印更多內核消息 描述了如何將內核日誌緩衝區中的內容打印到控制台,但內核日誌緩衝區也不是所有消息都有(除了 systemd 的 debug 輸出)。本節討論如何獲取比內核日誌更詳細的信息。

動態調試[編輯 | 編輯原始碼]

由函數 pr_debug 或類似函數 dev_dbg(), drm_dbg()bt_dev_dbg() 生成的消息不在內核日誌裡,除非:

  • 修改內核源代碼,在需要的地方定義 DEBUG
  • 利用內核的 動態調試 功能來啟用調試消息。

本節討論動態調試的用法,當你已經查看了所有內核日誌,甚至是 information 級別的日誌,但還是想從特定位置獲取更多調試信息,那麼動態調試很有用。

首先,你用的內核必須是用 CONFIG_DYNAMIC_DEBUG 內核配置選項編譯出來的,linux 包的內核已經滿足了要求,如果用這個內核就無需執行任何操作。

然後需要確定所需調試信息在哪,有幾種選擇:

  • 如果問題與特定模塊有關,就找到內核模塊的名稱。比如要排除 Intel 圖形處理器 的故障,就需要關注 i915 DRM 內核模塊.
  • 找到內核中相關功能對應的目錄,這需要查看(或在線導航)內核源代碼以了解其結構。例如,要查看所有 DRM 內核模塊的調試消息,可以使用路徑 drivers/gpu/drm

要使用該消息「源」,就必須發起一次動態調試查詢,指明要啟用哪些調試消息,格式如下:

match_type match_parameter flags

其中:

  • match_type 是匹配類型,與上述 2 種選擇相對應,可取值為 modulefile
  • match_parameter 是要監控的模塊或文件路徑,後一種情況允許使用星號作為通配符。
  • flags 表示如何處理匹配結果,可以取 +p 來開始打印其消息,或者 -p 來撤消打印。

一些查詢示例:

  • module i915 +p 打印來自 i915 內核模塊的調試信息。
  • file drivers/gpu/drm/* +p 打印來自 DRM 驅動的調試信息。
  • file * +p 打印調試信息。

最後,要實際執行上述查詢,可以這樣:

  • 在運行時執行查詢,運行命令:
# echo "查询" > /sys/kernel/debug/dynamic_debug/control
上述命令假設 debugfs 掛載到了 /sys/kernel/debug/,你可以用 mount 來確認。 [3]
  • 在系統啟動時執行查詢,添加 dyndbg="query" 內核參數

以上是對動態調試功能非常簡略的概述,更多詳細信息請參閱 文檔

特定子系統的調試[編輯 | 編輯原始碼]

在特定的子系統中,還有許多單獨的參數可用於調試,例如 bootmem_debugsched_debug。此外 initcall_debug 用來檢查啟動卡死很有用(找到那些沒有返回的調用)。特定的信息請查詢 內核參數文檔

netconsole[編輯 | 編輯原始碼]

netconsole 是一個內核模塊,它將所有內核日誌消息(即 dmesg)通過網絡發送到另一台計算機,不涉及到用戶空間(如 syslogd)。 "netconsole" 這個名稱不是很準確,因為它並不是真正的控制台,更像是遠程日誌記錄服務。

它可以內置使用或作為模塊使用。內置使用的 netconsole 在網卡之後就被初始化,並馬上啟動特定的接口。作為模塊使用,主要用於捕獲無顯示器的計算機的內核崩潰輸出,或者另一種情況就是用戶空間有故障。

故障恢復控制台[編輯 | 編輯原始碼]

在啟動過程中的某個階段獲取一個交互式 shell 可以幫助你準確找出問題出在哪裡,以及為何失敗。有幾個內核參數可以做到這一點,但它們都啟動了一個正常的shell,可以隨時 exit 讓內核恢復正在執行的操作:

  • rescue 在根文件系統剛剛被掛載為讀寫模式的時候啟動一個 shell
  • emergency 可以在更早的時候啟動 shell,早於大部分文件系統掛載之前
  • init=/bin/sh(作為最後的選擇)把 init 程序改成 root shell。因為 rescueemergency 都依賴於 systemd,而這可以在 systemd 壞掉的時候工作

還有一個選擇,那就是 systemd 的 debug-shell,它在 tty9 上新增了一個 root shell,可以按 Ctrl+Alt+F9 來使用。這個功能可以通過在 內核參數 中添加 systemd.debug-shell,或者是 啟用 debug-shell.service 來打開。

警告: 使用完後要記得禁用該服務,避免在每次啟動時都打開 root shell 而帶來安全風險。

調試內核模塊[編輯 | 編輯原始碼]

參閱 內核模塊#獲取信息

調試硬件問題[編輯 | 編輯原始碼]

  • 按照 udev#Debug output 的說明可以顯示額外硬件調試信息。
  • 確保你的系統已經安裝了 微碼 更新。
  • 要測試內存請參閱 MemTest86+
  • 要排查系統是否超溫請使用 lm_sensors
  • 要檢查存儲器的健康狀況,請參閱 S.M.A.R.T.

調試系統卡死問題[編輯 | 編輯原始碼]

不幸的是,系統卡死通常很難調試,並且有些需要很長時間才能復現。有些類型的卡死調試起來相對容易一點:

  • 聲音還在播放?這種情況可能只是顯示卡死了,顯卡驅動可能有問題。
  • 系統還有響應嗎?如果切換到其他 TTY 不行的話就試試 SSH
  • 硬盤活動指示燈(如果有的話)是否在指示有大量數據在讀寫?大量的內存交換也會暫時卡死系統。關於大量寫入硬盤時卡死的情況請參閱 這個 StackExchange 回答

如果上述都不行,嘗試一次 完整 的關機。按 一次 電源鍵或許可以使系統有反應,並顯示「關機畫面」,關機畫面包含了所有正在停止的單元。或者使用神奇的 SysRq 鍵也可以進行完整關機。完整關機很重要,因為 日誌 可能提示了系統卡死的原因。在非正常關閉時日誌可能不會寫入磁盤。系統毫無反應的情況更難調試,因為日誌無法及時寫入磁盤。

如果卡死以後沒法將任何內容寫入磁盤,可以嘗試遠程日誌。以下是一個粗略的遠程日誌方案,需要從另一個設備發起,可用於基本調試:

$ ssh freezing_host journalctl -f

許多致命卡死(整個系統無響應只能強制關機)可能與固件、驅動程序或硬件存在缺陷有關。嘗試不同的內核(請參閱 內核#調試回退),甚至換個 Linux 發行版或操作系統,還有更新固件並運行硬件診斷可能有助於發現問題。

提示:建議嘗試更新設備的固件,因為這些更新可能會修復奇怪的問題。

如果卡死以後無法收集用來調試的日誌或信息,請嘗試在 live 環境中重現卡死。如果需要圖形環境來重現,或者如果在 archiso 上成功重現了卡死,請更換不同發行版的 live 環境,最好不是基於 Arch Linux 的發行版,以排除卡死與版本或內核補丁相關的可能性。如果在 live 環境中仍然卡死,則很可能與硬件有關。如果不再發生卡死,那就需要了解兩個系統的差異。配置、版本和內核參數的不同,以及其他類似的更改可能已經解決了卡死問題。

但是,大寫鎖定指示燈閃爍可能表示 內核崩潰。當發生內核崩潰時,因為某些設置,TTY 可能不會顯示,導致內核崩潰被誤以為是另一種卡死。

處理軟件倒退問題[編輯 | 編輯原始碼]

警告: 這樣做往往會導致 部分升級,在特殊情況下這是不可避免的。請謹慎操作並準備好 恢復系統的方法,以防部分升級導致無法啟動。

如果是更新導致的問題,且 降級 特定包可以解決問題,則可能是 軟件倒退。 如果在正常的完整系統升級後發生這種情況,請檢查 pacman.log 來確定哪個軟件包可能導致了該問題。處理軟件倒退最重要的是檢查新版本是否已解決問題,這樣可以節省大量時間。為此,首先確保應用程序已完全更新(確保程序與 官方倉庫 中的版本相同)。如果已經最新或者更新不能解決問題,請嘗試使用實際的最新版本,通常是 -git 版本,它可能已經打包在 AUR 中。如果這樣能解決問題,並且已修復的版本還不在官方倉庫中,請等待新版本打包,然後切換回官方倉庫的版本。

如果問題仍然存在,請調試程序或 二分查找 程序的代碼提交歷史,並在上游的問題跟蹤系統裡報告錯誤,以便修復問題。

注意: 處理內核的倒退問題需要 稍微不同的方法

內核升級後部分外設無法使用[編輯 | 編輯原始碼]

通常(但可能不僅僅)表現為:

  • 新插入的 USB 設備顯示在 dmesg 中,但不在 /dev/ 中,
  • 如果文件系統在內核更新前沒有在使用,就無法掛載,
  • 如果筆記本上的有線/無線連接在內核更新前沒有在使用,就無法使用,
  • modprobe 加載一個內核更新前沒有加載的模塊時提示 FATAL: Module module not found in directory /lib/module/kernelversion

正如 系統維護#在更新後重啟程序和系統 所述,更新軟件包時不會更新內核,內核在重新啟動時才會更新。同時,安裝新內核時,位於 /usr/lib/modules/kernelversion/ 中的內核模塊會被 pacman 刪除。 根據 FS#16702 中的解釋,這種方法可以避免在系統上留下包管理器管理範圍外的文件,但會導致上述症狀。要修復這類問題,請在更新內核後重新啟動系統。遠期目標(尚未實現)是使用版本化內核包:主要障礙是如何刪除無用的老版本內核。

另一種解決方案是 kernel-modules-hook,其中包含兩個 pacman 鈎子,在內核更新後使用 rsync 將內核模塊保留在文件系統上,並啟用 linux-modules-cleanup.service 在四周後刪除舊模塊。

軟件包管理[編輯 | 編輯原始碼]

參閱適用於一般主題的 Pacman#疑難解答,以及適用於 PGP 密鑰問題的 pacman/軟件包簽名#問題解決

修復受損的系統[編輯 | 編輯原始碼]

如果進行了 部分升級,請嘗試升級整個系統,可能還需要重啟一次。

# pacman -Syu

如果以往是啟動到圖形界面,但這次失敗了,可以嘗試按 Ctrl+Alt+F1Ctrl+Alt+F6 來獲得一個能運行 pacman 的控制台。

如果系統損壞嚴重無法運行 pacman使用U盤、光盤或帶 PXE 的網絡上的 Arch ISO 來啟動電腦。(不要執行安裝指南裡的其餘操作)

掛載根文件系統:

[ISO] # mount /dev/rootFileSystemDevice /mnt

掛載其餘的獨立分區,在它們前面加上前綴 /mnt,例如:

[ISO] # mount /dev/bootDevice /mnt/boot

嘗試使用原系統的 pacman

[ISO] # arch-chroot /mnt
[chroot] # pacman -Syu

如果失敗了,退出 chroot 並嘗試:

[ISO] # pacman -Syu --sysroot /mnt

如果也失敗了,嘗試:

[ISO] # pacman -Syu --root /mnt --cachedir /mnt/var/cache/pacman/pkg

fuser[編輯 | 編輯原始碼]

這篇文章的某些內容需要擴充。

原因: 需要更多關於其用法的信息 (在 Talk:常規故障排除 中討論)

fuser 是一個用於識別進程占用的資源(如打開的文件、文件系統和 TCP/UDP 端口)的命令行工具。

fuser 由軟件包 psmisc 提供,已經作為 base 元包的依賴安裝。更多信息請查看 fuser(1)

會話權限[編輯 | 編輯原始碼]

注意: 你必須使用 systemd 作為你的 init 進程,本地會話才能正常工作。[4] 它是各種設備的 polkit 權限和 ACL 所必需的 (參見 /usr/lib/udev/rules.d/70-uaccess.rules[5]

首先,確保你有一個帶 X 的可用本地會話:

$ loginctl show-session $XDG_SESSION_ID

在輸出中需要帶有 Remote=no and Active=yes 字樣。如果沒有,確保 X 運行在和登錄時一樣的 tty 裡面。這是保留登錄會話所必須的。

基本 polkit 操作不需要額外的配置。但有一些 polkit 操作需要請求額外的身份認證,即使是本地會話也是如此。為了達成這項工作,必須運行一個 polkit 身份認證組件。更多信息可參見 polkit#身份認證組件

錯誤信息: "error while loading shared libraries"[編輯 | 編輯原始碼]

如果在運行程序時遇到類似於這樣的錯誤:

error while loading shared libraries: libusb-0.1.so.4: cannot open shared object file: No such file or directory

使用 pacmanpkgfile 來查找包含丟失共享庫的軟件包:

$ pacman -F libusb-0.1.so.4
extra/libusb-compat 0.1.5-1
    usr/lib/libusb-0.1.so.4

在上述例子中,需要 安裝 軟件包 libusb-compat。也可能是依賴於該共享庫的程序需要按照 soname 增加 後的庫重新編譯。

這個錯誤也有可能意味着你用來安裝這個軟件的 PKGBUILD 裡沒有將這個共享庫作為它的依賴庫:如果來自官方源,請 報告一個 bug;如果來自 AUR,請在 AUR 網站相關頁面上把它報告給維護者。

參閱[編輯 | 編輯原始碼]