通用故障排除
本文解释了一些通用故障排除的方法。对于特定于应用程序的问题,请参考该程序的特定 wiki 页面。
通用步骤
始终阅读出现的任何错误消息至关重要。有时可能很难获得正确的错误消息,例如对于图形应用程序。
- 在终端中运行应用程序,以便可以检查输出。
- 如果仍然没有足够的信息进行调试,请增加详细程度(通常为
--verbose
/-v
/-V
或--debug
/-d
)。 - 有时没有这样的参数,需要在应用程序的配置文件中将其指定为指令。
- 应用程序也可能使用日志文件,这些文件通常位于
/var/log
、$HOME/.cache
或$HOME/.local
中 - 如果没有办法增加详细程度,始终可以运行 strace 和类似的工具。
- 如果仍然没有足够的信息进行调试,请增加详细程度(通常为
- 检查 journal。错误也可能在 journal 中留下痕迹,尤其是在它依赖于其他应用程序的情况下。
- dmesg 从内核环形缓冲区读取。如果由于某种原因无法访问磁盘,这将非常有用,但这也可能导致日志不完整,因为内核环形缓冲区的大小不是无限的。如果可能,请使用 journalctl。
- journalctl 比 dmesg 具有更多的 过滤选项,并且默认使用人类可读的时间戳。
- 始终建议检查相关的问题跟踪器,以查看是否存在已知问题和已有的解决方案。
- 根据上游的选择,通常会有一个问题跟踪器,有时还会有一个论坛,甚至例如 IRC 频道。
- 这里是 Arch Linux 错误跟踪器,它主要用于软件包错误。
额外支持
当请求支持时,请发布完整的输出/日志,而不仅仅是您认为重要的部分。信息来源包括
- 所涉及的任何命令的完整输出 - 不要只选择您认为相关的部分。
- systemd 的 journal。
- 对于更广泛的输出,请使用
systemd.log_level=debug
启动参数。这将产生大量的输出,因此仅在真正需要时才启用它。 - 不要使用
-x
参数,因为这会不必要地使输出混乱,并且更难以阅读。 - 使用
-b
,除非您需要以前启动的日志。不指定此项可能会导致非常大的粘贴,甚至可能太大而无法放入任何 pastebin。
- 对于更广泛的输出,请使用
- 相关的配置文件
- 涉及的驱动程序
- 涉及的软件包的版本
- 内核:
journalctl -k
或dmesg
(均需 root 权限)。 - Xorg:取决于设置,正在使用的 显示管理器 在这里也很重要。
Xorg.log
可能位于以下几个位置之一:系统 journal、/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 或 journal 在其中可用。
- 实际系统
- 根据损坏的程度,简单调用 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
来启用它。
调试内核模块
请参阅 Kernel modules#获取信息。
调试硬件
- 您可以通过遵循 udev#调试输出 来显示有关硬件的额外调试信息。
- 确保在您的系统上应用了 微代码 更新。
- 要测试 RAM,请参阅 Stress testing#MemTest86+。
- 要查看您的系统是否过热,请使用 lm_sensors。
- 要检查您的存储健康状况,请参阅 S.M.A.R.T.
调试冻结
不幸的是,冻结通常很难调试,其中一些需要很长时间才能重现。有些类型的冻结比其他类型的更容易调试
- 声音还在播放吗?如果是,则可能只是显示冻结。这可能是视频驱动程序的问题。
- 机器还在响应吗?如果切换到另一个 TTY 无效,请尝试 SSH。
- 磁盘活动 LED(如果存在)是否指示正在向磁盘写入大量数据?大量的交换可能会暂时冻结系统。有关大写入时冻结的信息,请参阅 此 StackExchange 答案。
如果其他方法都无效,请尝试干净的关机。按一次电源按钮可能会解除系统冻结并显示经典的“关机屏幕”,其中显示所有正在停止的单元。或者,使用 magic SysRq 键也可能有助于实现干净的关机。这非常重要,因为 journal 可能包含机器冻结原因的提示。在不干净的关机时,journal 可能不会写入磁盘。整个机器无响应的硬冻结更难调试,因为日志无法及时写入磁盘。
如果冻结不允许将任何内容写入磁盘,远程日志记录可能会有所帮助。从另一台设备调用的粗略远程日志记录解决方案可用于基本调试
$ ssh freezing_host journalctl -f
许多导致整个系统不再响应并需要强制关机的致命冻结可能与固件、驱动程序或硬件中的错误有关。尝试不同的内核(请参阅 Kernel#调试回归)甚至不同的 Linux 发行版或操作系统,更新固件和运行硬件诊断可能有助于找到问题。
如果冻结不允许收集任何类型的日志或调试所需的其他信息,请尝试在 live 环境中重现冻结。如果需要图形环境才能重现冻结,或者可以在 archiso 上重现冻结,请使用不同发行版的 live 环境,最好是基于非 Arch Linux 的发行版,以消除冻结与内核版本或补丁相关的可能性。如果冻结仍然发生在 live 环境中,则很可能与硬件可能有关。如果不再发生冻结,则有必要了解两个系统的差异。不同的配置、版本和内核参数的差异以及其他类似的更改可能已修复冻结。
但是,闪烁的大写锁定 LED 可能指示 内核 panic。某些设置可能在发生内核 panic 时不显示 TTY,这可能会造成混淆,并可能被解释为另一种冻结。
调试回归
如果更新导致问题,但 降级 特定软件包可以修复它,则很可能是 回归。如果这种情况发生在正常的完整系统升级之后,请检查您的 pacman.log
以确定哪个或哪些软件包可能导致了问题。调试回归的最重要部分是检查问题是否已修复,因为这可以节省大量时间。为此,首先确保应用程序已完全更新(例如,确保应用程序的版本与 官方存储库 中的版本相同)。如果已经是这样,或者如果更新它没有解决问题,请尝试使用实际的最新版本,通常是 -git 版本,该版本可能已在 AUR 中打包。如果这解决了问题,并且包含修复程序的版本尚未在官方存储库中,请等到新版本到达官方存储库中,然后切换回它。
如果问题仍然存在,请调试问题和/或 二分查找 应用程序,并在上游错误跟踪器上报告该错误,以便可以修复它。
内核升级后无法使用某些外围设备
这通常(但可能不只)表现为
- 新插入的 USB 设备在 dmesg 中显示,但在
/dev/
中不显示, - 如果文件系统在内核更新之前尚未使用,则无法挂载文件系统,
- 如果笔记本电脑上的有线/无线连接在内核更新之前尚未使用,则无法使用,
- 当使用 modprobe 加载内核软件包更新之前尚未使用过的模块时,出现
FATAL: Module module not found in directory /lib/module/kernelversion
。
正如 System maintenance#升级后重启或重新启动 中部分涵盖的那样,内核在您更新软件包时不会更新,而仅在您之后重新启动时才会更新。同时,位于 /usr/lib/modules/kernelversion/
中的内核模块在安装新内核时会被 pacman 删除。正如 FS#16702 中解释的那样,这种方法避免了在系统上留下未由软件包管理器处理的文件,但会导致上述症状。要修复这些症状,请在更新内核后系统地重新启动。长期演进(尚未实施)将是使用版本化的内核软件包:主要的障碍是如何处理一旦不再需要旧内核版本时的删除。
另一个解决方案作为 kernel-modules-hook 提供,其中两个 pacman 钩子使用 rsync 在内核更新后将内核模块保留在文件系统上,以及 linux-modules-cleanup.service
,它在 启用 后四周标记旧模块以供删除。
软件包管理
有关常规主题,请参阅 Pacman#故障排除,有关 PGP 密钥的问题,请参阅 pacman/Package signing#故障排除。
修复损坏的系统
如果执行了 部分升级,请尝试更新您的整个系统。可能需要重新启动。
# 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 工具列表 - 类似于 Memtest 的工具,可添加到 UltimateBootCD.com 上的 grub.cfg 中
- 维基百科:BIOS 启动分区
- REISUB
- systemd 关于调试日志记录到串行控制台的文档
- 如何在 Archive.org 上隔离 Linux ACPI 问题