通用故障排除
本文介绍了一些通用故障排除方法。对于特定于应用程序的问题,请参考该程序的特定 wiki 页面。
通用步骤
始终阅读出现的任何错误消息至关重要。有时可能很难获得正确的错误消息,例如使用图形应用程序时。
- 在终端中运行应用程序,以便可以检查输出。
- 如果仍然没有足够的信息进行调试,请增加详细程度(通常为
--verbose
/-v
/-V
或--debug
/-d
)。 - 有时没有这样的参数,需要在应用程序的配置文件中将其指定为指令。
- 应用程序也可能使用日志文件,这些文件通常位于
/var/log
、$HOME/.cache
或$HOME/.local
中 - 如果没有办法增加详细程度,始终可以运行 strace 和类似的工具。
- 如果仍然没有足够的信息进行调试,请增加详细程度(通常为
- 检查 日志。错误也可能在日志中留下痕迹,尤其是在它依赖于其他应用程序的情况下。
- dmesg 从内核环形缓冲区读取。如果磁盘由于某种原因无法访问,这将非常有用,但这也可能导致日志不完整,因为内核环形缓冲区的大小不是无限的。如果可能,请使用 journalctl。
- journalctl 比 dmesg 具有更多的 过滤选项,并且默认使用人类可读的时间戳。
- 始终建议检查相关的问题跟踪器,以查看是否存在已知问题以及已有的解决方案。
- 根据上游的选择,通常会有一个问题跟踪器,有时还会有论坛,甚至例如 IRC 频道。
- 这里是 Arch Linux 错误跟踪器,主要用于软件包错误。
额外支持
当请求支持时,请发布完整的输出/日志,而不仅仅是您认为重要的部分。信息来源包括
- 任何涉及的命令的完整输出 - 不要只选择您认为相关的部分。
- systemd 的 日志。
- 对于更广泛的输出,请使用
systemd.log_level=debug
启动参数。这将产生大量的输出,因此仅在真正需要时才启用它。 - 不要使用
-x
参数,因为这会不必要地使输出混乱,并且更难以阅读。 - 除非您需要以前启动的日志,否则请使用
-b
。不指定此参数可能会导致非常大的粘贴,甚至可能对于任何 pastebin 来说都太大。
- 对于更广泛的输出,请使用
- 相关的配置文件
- 涉及的驱动程序
- 涉及的软件包的版本
- 内核:
journalctl -k
或dmesg
(两者都需要 root 权限)。 - Xorg:根据设置,此处使用的显示管理器也相关。
Xorg.log
可能位于以下几个位置之一:系统日志、/var/log/
或$HOME/.local/share/xorg/
。- 一些显示管理器(如 LightDM)也可能将
Xorg.log
放在其自己的日志目录中。
- Pacman:如果最近的升级破坏了某些东西,请查看
/var/log/pacman.log
。- 使用 pacman 的
--debug
参数可能很有用。
- 使用 pacman 的
发布此信息的更好方法之一是使用 pastebin。
然后将输出一个链接,您可以将其粘贴到论坛或 IRC。
此外,在提问之前,您可能希望查看 如何正确报告问题。
启动问题
在诊断启动问题时,非常重要的是要知道启动在哪个阶段失败。
- 固件(UEFI 或 BIOS)
- 通常只有非常基本的调试工具。
- 确保 安全启动 已禁用。
- 引导加载程序
- 此处完成的最常见的事情之一是更改内核参数。
- 引导加载程序阶段的常见启动问题可能是由 ACPI 引起的。
- initramfs
- 通常提供紧急 shell。
- 根据选择的钩子,dmesg 或日志都可以在其中使用。
- 实际系统
- 取决于它的损坏程度,简单调用 debug shell 可能就足够了。
如果任何阶段提供的调试工具都不足以修复损坏的组件,请尝试使用例如 带有最新 Arch Linux ISO 的 USB 闪存驱动器。
控制台消息
启动过程后,屏幕被清除,并出现登录提示符,使用户无法读取 init 输出和错误消息。可以使用以下部分中概述的方法修改此默认行为。
请注意,无论选择哪个选项,内核消息都可以在启动后使用 journalctl -k
或 dmesg
显示以供检查。要显示当前启动的所有日志,请使用 journalctl -b
。
流量控制
这是适用于大多数终端模拟器(包括虚拟控制台 (VC))的基本管理
- 按
Ctrl+s
暂停输出。 - 按
Ctrl+q
恢复输出。
这不仅暂停了输出,还暂停了尝试打印到终端的程序,因为只要输出暂停,它们就会阻塞在 write()
调用上。如果您的 init 看起来已冻结,请确保系统控制台未暂停。
要查看已显示的错误消息,请参阅 Getty#让启动消息保留在 tty1 上。
打印更多内核消息
大多数内核消息在启动期间被隐藏。您可以通过添加不同的内核参数来查看更多这些消息。最简单的参数是
debug
,它具有以下效果ignore_loglevel
,它对内核具有与debug
或loglevel=8
相同的效果(因为调试消息为7
),但会阻止稍后在启动时提高日志级别。
您可以添加的其他参数在某些情况下可能很有用,例如
earlyprintk=vga,keep
在启动过程的早期打印内核消息,以防内核在显示输出之前崩溃。对于 EFI 系统,您必须将vga
更改为efi
。log_buf_len=16M
分配一个更大的(16 MiB)内核消息缓冲区,以确保调试输出不会被覆盖。
生成调试内核消息
#打印更多内核消息 指示如何将内核日志缓冲区打印到控制台,但是该缓冲区本身不会包含任何消息(除了调试 systemd 输出)。此标题讨论了从内核日志中获取更多详细信息的方法。
动态调试
除非您满足以下任一条件,否则不会生成使用 pr_debug 或相关函数(如 dev_dbg()
、drm_dbg()
和 bt_dev_dbg()
)打印的消息
- 修改内核源代码以在所需位置定义
DEBUG
。 - 利用内核的 动态调试 功能来启用调试消息。
本节将讨论如何使用动态调试,如果您已经查看了内核日志(包含所有信息日志),并且想要从特定位置获得更多调试信息,这将非常有用。
首先,您必须运行使用 CONFIG_DYNAMIC_DEBUG
内核配置选项集编译的内核。对于 linux 而言,情况已经是这样了,因此如果您使用该内核,则无需执行任何操作。
然后,您需要知道要从哪里查看调试消息。以下是一些选项
- 使用内核模块名称,如果问题似乎隔离在模块中。例如,要排查 Intel 显卡,您可能会关注
i915
DRM 内核模块。 - 使用内核中与您感兴趣的功能相对应的目录。您将需要签出(或在线导航)内核源代码以了解结构。例如,要检查所有 DRM 内核模块的调试消息,您可以使用路径 drivers/gpu/drm。
使用消息的“源”,您必须提出一个动态调试查询,该查询指示要启用哪些调试消息,格式为
match_type match_parameter flags
其中
- match_type 是要进行的匹配类型。与前面给出的两个选项相对应,这可以是
module
或file
。 - match_parameter 是要监视的模块或文件路径。在后一种情况下,允许使用星号作为通配符。
- flags 指示对匹配执行的操作。这可以是
+p
以开始打印其消息,或-p
以撤消该操作。
以下是一些查询示例
module i915 +p
从i915
内核模块打印调试消息。file drivers/gpu/drm/* +p
从 DRM 驱动程序打印调试消息。file * +p
打印调试消息。
最后,要实际执行查询,您可以
- 在运行时执行,通过运行
# echo "query" > /sys/kernel/debug/dynamic_debug/control
- 在启动时执行,通过添加
dyndbg="query"
内核参数
这只是动态调试功能的简化概述;有关更多详细信息,请参阅 文档。
子系统特定调试
还有许多单独的调试参数,用于在特定子系统(例如 bootmem_debug
、sched_debug
)中启用调试。此外,initcall_debug
对于调查启动冻结可能很有用。(查找未返回的调用。)查看 内核参数文档 以获取具体信息。
netconsole
netconsole 是一个内核模块,它通过网络将所有内核日志消息(即 dmesg)发送到另一台计算机,而无需用户空间(例如 syslogd)参与。名称“netconsole”用词不当,因为它实际上不是“控制台”,更像是远程日志记录服务。
它可以内置或作为模块使用。内置 netconsole 在 NIC 卡之后立即初始化,并将尽快启动指定的接口。该模块主要用于从无头机器捕获内核 panic 输出,或在用户空间不再起作用的其他情况下使用。
恢复 Shell
在启动过程的某个阶段获得交互式 shell 可以帮助您准确找出问题发生的位置和原因。有几个内核参数可以执行此操作,但是它们都会启动一个普通的 shell,您可以 exit
以让内核恢复它正在执行的操作
rescue
在根文件系统重新挂载为读/写后不久启动 shellemergency
甚至更早启动 shell,在大多数文件系统挂载之前init=/bin/sh
(作为最后的手段)将 init 程序更改为 root shell。rescue
和emergency
都依赖于 systemd,但是即使 systemd 损坏,这也应该有效。
另一个选项是 systemd 的 debug-shell,它在 tty9
上添加了一个 root shell(可以使用 Ctrl+Alt+F9
访问)。可以通过将 systemd.debug_shell
添加到 内核参数,或者通过启用 debug-shell.service
来启用它。
调试内核模块
请参阅 内核模块#获取信息。
调试硬件
- 您可以通过遵循 udev#调试输出 来显示有关硬件的额外调试信息。
- 确保在您的系统上应用了 微码 更新。
- 要测试 RAM,请参阅 压力测试#MemTest86+。
- 要查看您的系统是否过热,请使用 lm_sensors。
- 要检查您的存储健康状况,请参阅 S.M.A.R.T.
调试冻结
不幸的是,冻结通常很难调试,并且有些冻结需要很长时间才能重现。有些类型的冻结比其他类型的冻结更容易调试
- 声音是否仍在播放?如果是,则可能只是显示器冻结。这可能是视频驱动程序的问题。
- 机器是否仍在响应?如果切换到另一个 TTY 无效,请尝试 SSH。
- 磁盘活动 LED(如果存在)是否指示正在向磁盘写入大量数据?大量交换可能会暂时冻结系统。有关大写入时冻结的信息,请参阅 此 StackExchange 答案。
如果其他方法都无效,请尝试干净关机。按一次电源按钮可能会解除系统冻结,并显示经典的“关机屏幕”,其中显示所有正在停止的单元。或者,使用 magic SysRq 键也可能有助于实现干净关机。这非常重要,因为日志可能包含机器冻结原因的提示。日志可能不会在不干净的关机时写入磁盘。整个机器无响应的硬冻结更难调试,因为日志无法及时写入磁盘。
如果冻结不允许写入任何内容到磁盘,远程日志记录可能会有所帮助。一种粗略的远程日志记录解决方案(需要从另一台设备调用)可用于基本调试
$ ssh freezing_host journalctl -f
许多导致整个系统不再响应并需要强制关机的致命冻结可能与固件、驱动程序或硬件错误有关。尝试不同的内核(请参阅 Kernel#调试回归)甚至不同的 Linux 发行版或操作系统,更新固件和运行硬件诊断可能有助于找到问题。
如果冻结不允许收集任何类型的日志或调试所需的其他信息,请尝试在实时环境中重现冻结。如果需要图形环境才能重现冻结,或者可以在 archiso 上重现冻结,请使用不同发行版的实时环境,最好是不基于 Arch Linux 的发行版,以消除冻结与内核版本或补丁相关的可能性。如果冻结仍然发生在实时环境中,则很可能可能与硬件相关。如果不再发生,则有必要了解两个系统之间的差异。不同的配置、版本和内核参数的差异以及其他类似的更改可能已修复了冻结。
但是,闪烁的 Caps Lock LED 可能表示 内核 panic。某些设置可能在发生内核 panic 时不显示 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
如果您通常启动到 GUI 并且 GUI 失败,也许您可以按 Ctrl+Alt+F1
到 Ctrl+Alt+F6
并进入工作 tty 以通过它运行 pacman。
如果系统损坏到您无法运行 pacman 的程度,请使用 USB 闪存驱动器、光盘或带有 PXE 的网络从每月 Arch ISO 启动。(不要遵循安装指南的其余部分。)
挂载您的根文件系统
# mount /dev/rootFileSystemDevice /mnt
挂载您单独创建的任何其他分区,并在所有分区前添加前缀 /mnt
,即
# mount /dev/bootDevice /mnt/boot
尝试在 chroot 时使用系统的 pacman
# arch-chroot /mnt # pacman -Syu
如果失败,请退出 chroot,然后尝试
# pacman -Syu --sysroot /mnt
如果失败,请尝试
# pacman -Syu --root /mnt --cachedir /mnt/var/cache/pacman/pkg
fuser
fuser 是一个命令行实用程序,用于识别使用资源(如文件、文件系统和 TCP/UDP 端口)的进程。
fuser 由 psmisc 软件包提供,该软件包应已作为 base 元软件包的依赖项安装。有关详细信息,请参阅 fuser(1)。
会话权限
/usr/lib/udev/rules.d/70-uaccess.rules
和 [5])首先,确保您在 X 中具有有效的本地会话
$ loginctl show-session $XDG_SESSION_ID
这应该在输出中包含 Remote=no
和 Active=yes
。如果不是,请确保 X 在登录发生的同一 tty 上运行。这是为了保留 logind 会话所必需的。
基本的 polkit 操作不需要进一步设置。某些 polkit 操作需要进一步身份验证,即使是本地会话也是如此。polkit 身份验证代理需要运行才能使其工作。有关此方面的更多信息,请参阅 polkit#身份验证代理。
如果在使用程序时,您收到类似于以下的错误
error while loading shared libraries: libusb-0.1.so.4: cannot open shared object file: No such file or directory
使用 pacman 或 pkgfile 搜索拥有缺失库的软件包
$ pacman -F libusb-0.1.so.4
extra/libusb-compat 0.1.5-1 usr/lib/libusb-0.1.so.4
在这种情况下,需要 安装 libusb-compat 软件包。或者,请求库的程序可能需要在 soname bump 后重建。
该错误也可能意味着您用于安装程序的软件包未在其 PKGBUILD 中将该库列为依赖项:如果是官方软件包,请报告错误;如果是 AUR 软件包,请使用其在 AUR 网站中的页面向维护者报告。
参见
- 面向新手的故障排除指南
- UBCD 工具列表 - 要添加到 UltimateBootCD.com 上的 grub.cfg 中的类似 Memtest 的工具
- 维基百科:BIOS 启动分区
- REISUB
- systemd 关于调试日志到串行控制台的文档
- 如何在 Archive.org 上隔离 Linux ACPI 问题