通用故障排除
本文解释了一些通用的故障排除方法。对于特定于应用程序的问题,请参考该程序的特定 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 或日志都可以在其中使用。
- 实际系统
- 根据损坏的严重程度,简单地调用调试 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
在启动过程的早期打印内核消息,以防内核在显示输出之前崩溃。您必须将vga
更改为 EFI 系统的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
许多导致整个系统不再响应并需要强制关机的致命卡死可能与错误的固件、驱动程序或硬件有关。尝试使用不同的内核(请参阅 内核#调试回归)甚至不同的 Linux 发行版或操作系统,更新固件和运行硬件诊断可能有助于找到问题。
如果卡死不允许收集任何类型的日志或调试所需的其他信息,请尝试在 live 环境中重现卡死。如果需要图形环境才能重现卡死,或者可以在 archiso 上重现卡死,请使用不同发行版的 live 环境,最好不是基于 Arch Linux 的发行版,以消除卡死与内核版本或补丁相关的可能性。如果卡死仍然发生在 live 环境中,则很可能可能与硬件有关。如果不再发生卡死,则有必要了解两个系统的差异。不同的配置、版本和内核参数的差异以及其他类似的更改可能已修复了卡死。
但是,闪烁的 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#Authentication agents 以获取更多信息。
如果您在使用程序时遇到类似于以下的错误:
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。
- Wikipedia:BIOS 启动分区
- REISUB
- 关于调试日志记录到串行控制台的 systemd 文档
- Archive.org 上的 如何隔离 Linux ACPI 问题