1. 当系统启动报错时我们该从哪里入手那天早上我像往常一样启动服务器突然看到一个刺眼的红色错误提示[FAILED] Failed to start Load Kernel Modules。作为一个运维老手我知道这背后可能隐藏着各种可能性 - 可能是内核模块缺失、配置文件错误甚至是硬件兼容性问题。但别担心跟着我的排查思路走你也能轻松解决这类问题。首先我们需要理解systemd-modules-load.service这个服务的作用。简单来说它就像系统启动时的模块管家负责根据配置文件自动加载所需的内核模块。当这个服务启动失败时通常意味着它在加载某些模块时遇到了问题。这时候我们需要像侦探一样一步步收集线索找出问题根源。2. 第一步查看服务状态和日志2.1 使用systemctl查看服务状态根据错误提示我们首先要做的就是查看systemd-modules-load.service的详细状态。打开终端输入systemctl status systemd-modules-load.service这个命令会给我们三个重要信息服务的运行状态是否active服务的启动时间最近一次的日志摘要在我的案例中输出显示服务确实启动失败了但更关键的是它提示我们可以查看更详细的日志。这就引出了我们的第二个工具journalctl。2.2 深入分析journalctl日志journalctl是systemd的日志管理工具它能让我们看到更详细的系统日志。针对这个特定的服务我们可以使用sudo journalctl -b _PID66这里的-b参数表示只查看本次启动的日志_PID66则指定了我们要查看的进程ID这个ID可以从之前的systemctl输出中获得。仔细查看日志输出我发现了关键线索Apr 06 01:44:30 am335x-evm systemd-modules-load[66]: Inserted module cryptodev Apr 06 01:44:30 am335x-evm systemd-modules-load[66]: [[0;1;31mFailed to find module usbserial[[0m Apr 06 01:44:30 am335x-evm systemd-modules-load[66]: [[0;1;31mFailed to find module ftdi_sio[[0m这段日志清楚地告诉我们系统成功加载了cryptodev模块但在尝试加载usbserial和ftdi_sio模块时失败了。这就是导致服务启动失败的罪魁祸首3. 第二步定位模块加载配置文件3.1 理解/etc/modules-load.d/目录结构现在我们知道是哪些模块加载失败了接下来需要找出系统是从哪里尝试加载这些模块的。在基于systemd的Linux系统中内核模块的自动加载配置通常存放在/etc/modules-load.d/目录下。这个目录下的配置文件遵循简单的格式每行一个模块名注释以#开头。系统启动时systemd-modules-load.service会读取这个目录下的所有.conf文件并尝试加载其中列出的模块。3.2 查找特定模块的配置文件为了找出usbserial和ftdi_sio模块是在哪个配置文件中指定的我们可以使用grep命令在整个目录中搜索grep -r usbserial\|ftdi_sio /etc/modules-load.d/在我的案例中输出显示这两个模块定义在/etc/modules-load.d/kobuki.conf文件中。这个文件可能来自某个特定的硬件驱动安装包比如机器人控制器的驱动。4. 第三步分析问题并实施解决方案4.1 理解问题的根本原因现在我们已经掌握了所有关键信息系统启动时尝试加载usbserial和ftdi_sio模块这些模块在当前内核中不存在加载请求来自/etc/modules-load.d/kobuki.conf文件这里可能有几种情况这些模块确实应该存在但内核编译时没有包含它们这些模块属于某个第三方驱动但驱动没有正确安装这个配置文件是之前安装的某个软件留下的但现在不再需要4.2 实施解决方案根据具体情况我们有几种解决方法方案一安装缺失的模块如果确实需要如果是必要的硬件驱动模块我们应该先尝试安装它们。对于常见的串口转换芯片驱动如usbserial、ftdi_sio可以尝试sudo apt install linux-modules-extra-$(uname -r)然后重新启动systemd-modules-load服务sudo systemctl restart systemd-modules-load.service方案二清理不必要的配置如果模块确实不需要如果这些模块不是系统必需的比如是之前安装的某个硬件驱动但现在不再使用最简单的解决方案就是清空或删除对应的配置文件echo /etc/modules-load.d/kobuki.conf或者直接删除文件sudo rm /etc/modules-load.d/kobuki.conf方案三注释掉特定行如果只想临时禁用如果只是想在保留配置的情况下临时禁用这些模块加载可以编辑文件在相应行前添加#注释sudo sed -i s/^usbserial$/#usbserial/ /etc/modules-load.d/kobuki.conf sudo sed -i s/^ftdi_sio$/#ftdi_sio/ /etc/modules-load.d/kobuki.conf5. 验证解决方案是否有效无论采用哪种解决方案最后都需要验证问题是否真的解决了。我们可以通过以下步骤进行验证重新加载systemd配置sudo systemctl daemon-reload重启有问题的服务sudo systemctl restart systemd-modules-load.service再次检查服务状态systemctl status systemd-modules-load.service如果服务状态显示active (exited)并且日志中没有新的错误信息就说明我们的解决方案生效了。6. 深入理解内核模块管理的最佳实践6.1 如何检查模块是否存在于系统中在决定如何处理缺失模块的问题前我们需要确认这些模块是否真的不存在于系统中。以下是几种检查方法方法一使用modinfo命令modinfo usbserial 2/dev/null || echo Module usbserial not found方法二查看/lib/modules目录find /lib/modules/$(uname -r) -name *usbserial*方法三尝试手动加载模块sudo modprobe usbserial如果模块确实不存在modprobe会返回Module usbserial not found的错误。6.2 内核模块的常见来源理解内核模块的来源有助于我们判断如何处理缺失模块的问题标准内核模块随Linux内核一起发布通常位于/lib/modules/$(uname -r)/kernel/drivers/目录下DKMS模块通过DKMSDynamic Kernel Module Support系统安装的第三方驱动手动编译的模块用户自己编译安装的驱动模块6.3 管理modules-load.d配置文件的建议为了避免类似问题我总结了以下几点经验每个硬件/软件使用单独的配置文件比如nvidia.conf、virtualbox.conf等这样在卸载软件时可以方便地删除对应的配置文件定期清理不再使用的配置文件在卸载硬件或软件后记得同时删除/etc/modules-load.d/目录下相关的配置文件添加有意义的注释在配置文件中说明每个模块的用途和依赖关系测试新配置在修改配置文件后可以手动运行systemd-modules-load服务来测试而不需要重启系统sudo systemctl restart systemd-modules-load.service sudo journalctl -u systemd-modules-load.service -b7. 扩展知识systemd-modules-load的高级调试技巧7.1 启用调试模式如果需要更详细的信息可以临时启用systemd-modules-load的调试输出sudo systemctl edit systemd-modules-load.service然后在编辑器中添加[Service] EnvironmentSYSTEMD_LOG_LEVELdebug保存退出后重新加载并重启服务sudo systemctl daemon-reload sudo systemctl restart systemd-modules-load.service sudo journalctl -u systemd-modules-load.service -b7.2 模拟测试模块加载在修改配置文件前可以先测试模块是否能正常加载sudo modprobe --dry-run usbserial这个命令会模拟模块加载过程但不会真正加载模块适合用来测试配置是否正确。7.3 处理模块依赖关系有些模块可能有依赖关系需要在配置文件中按正确顺序列出。可以使用modprobe命令查看模块依赖modprobe --show-depends usbserial如果模块有依赖确保在配置文件中先列出依赖模块。