Linux系统故障修复、日志管理与安全加固实战指南

前言

作为一名 Linux 运维工程师,你一定遇到过这样的场景:系统突然无法启动,屏幕上只留下一个 grub> 提示符;或者服务明明在运行,客户端却始终连接失败;又或者修改了端口后服务死活起不来,最后发现是 SELinux 在"作怪"。

这些问题的背后,往往涉及系统启动流程日志分析时间同步SELinux 安全策略等核心知识。本文将从实战角度出发,带你逐一攻克这些难题,让你在面对系统故障时从容应对。


一、系统启动故障修复:从 GRUB 到根文件系统

1.1 GRUB 引导配置文件丢失(grub.cfg)

现象 :开机后直接进入 grub> 命令行,看不到内核选择菜单。

原因/boot/grub2/grub.cfg 文件丢失或损坏,GRUB2 无法加载引导配置。

手动引导修复

复制代码
# 1. 列出所有磁盘分区
grub> ls
(hd0) (hd0,msdos1) (hd0,msdos2) (hd0,msdos3)

# 2. 找到 boot 分区(通常是第一个分区)
grub> set root=(hd0,msdos1)

# 3. 指定内核和 initramfs 路径
grub> linux /vmlinuz-5.14.0-362.el9.x86_64 root=/dev/mapper/rhel-root
grub> initrd /initramfs-5.14.0-362.el9.x86_64.img

# 4. 启动
grub> boot

根文件系统路径说明

  • 逻辑卷:/dev/mapper/卷组名-root(如 RHEL 为 /dev/mapper/rhel-root
  • 普通分区(SCSI):/dev/sda2
  • NVMe 磁盘:/dev/nvme0n1p2

进入系统后重新生成配置文件

复制代码
grub2-mkconfig -o /boot/grub2/grub.cfg

更简单的方法 :使用安装光盘进入救援模式chroot 到真实根目录后执行上述命令。


1.2 GRUB2 引导程序丢失(传统 BIOS)

现象:开机直接进入安装界面或网络启动,无法加载 GRUB。

原因:硬盘前 446 字节(MBR)的引导程序被破坏。

模拟故障(仅供测试):

复制代码
dd if=/dev/zero of=/dev/sda bs=446 count=1

修复方法(救援模式)

复制代码
# 进入救援模式,切换到真实根
chroot /mnt/sysimage
# 重新安装 GRUB
grub2-install /dev/sda

UEFI 环境 :引导程序位于 /boot/efi/,修复方式为重新安装 efi-filesystemshim-x64 两个 RPM 包,或从其他机器拷贝文件。


1.3 内核文件或 initramfs 丢失

现象 :开机提示找不到 vmlinuzinitramfs

修复方法:进入救援模式,重新安装内核相关的 RPM 包:

复制代码
# 查看已安装的内核版本
rpm -qa | grep kernel
# 重新安装内核(以 kernel-core 为例)
dnf reinstall kernel-core

1.4 boot 分区文件全部丢失

现象 :开机后 GRUB 提示 file '/boot/grub2/i386-pc/normal.mod' not found

修复方法:救援模式下重新安装 GRUB 并生成配置文件:

复制代码
chroot /mnt/sysimage
grub2-install /dev/sda
grub2-mkconfig -o /boot/grub2/grub.cfg

1.5 fstab 文件导致紧急模式

现象 :开机进入 emergency mode,提示挂载文件系统超时。

原因/etc/fstab 中配置了无法挂载的分区或错误的 UUID。

修复步骤

  1. 输入 root 密码进入 shell。
  2. 执行 mount -a 检查具体哪个挂载点出错。
  3. 编辑 /etc/fstab,注释或修正错误的行。
  4. 重启系统。

1.6 GRUB2 加固(防止密码重置)

为防止他人通过编辑内核菜单重置 root 密码,可以对 GRUB2 进行密码保护。

设置 GRUB2 密码

复制代码
grub2-setpassword
# 输入两次密码,生成 /boot/grub2/user.cfg

取消保护

复制代码
rm -f /boot/grub2/user.cfg

手动生成加密密码(可选)

复制代码
grub2-mkpasswd-pbkdf2
# 将生成的内容替换到 /boot/grub2/grub.cfg 中

二、日志管理:从临时到持久,从本地到集中

2.1 systemd-journald:临时日志的"第一现场"

systemd-journald 是系统启动后的第一个日志服务,日志默认保存在 /run/log/journal/(内存中),重启即丢失。

常用 journalctl 命令

复制代码
# 查看所有日志
journalctl

# 实时跟踪
journalctl -f

# 查看指定服务日志
journalctl -u sshd.service

# 查看指定时间段的日志
journalctl --since "2026-07-12 10:00:00" --until "2026-07-12 10:10:00"

# 查看启动日志(类似 dmesg)
journalctl -k

# 查看详细信息(含错误码)
journalctl -xe

持久化存储配置

复制代码
# 创建目录
mkdir /var/log/journal
# 重新加载 journald
systemctl restart systemd-journald
# 或强制执行刷新
journalctl --flush

持久化后,日志将保存在 /var/log/journal,重启不丢失。


2.2 rsyslog:分类存储的"档案室"

rsyslog 负责将日志按类型写入不同文件,默认存储于 /var/log/,属于持久化存储。

常见日志文件

|---------------------|-------------------|
| 文件 | 内容 |
| /var/log/messages | 通用系统日志(最常用) |
| /var/log/secure | 认证和安全日志(如 SSH 登录) |
| /var/log/cron | 计划任务日志 |
| /var/log/boot.log | 开机启动日志 |
| /var/log/dnf.log | 软件包管理日志 |
| /var/log/httpd/ | Apache 访问和错误日志 |

配置文件/etc/rsyslog.conf 定义了日志分类规则,例如:

复制代码
*.info;mail.none;authpriv.none;cron.none   /var/log/messages
authpriv.*   /var/log/secure

手动发送测试日志

复制代码
logger -t mytest -i -p user.info "This is a test log"

2.3 logrotate:自动轮转,防止日志撑爆磁盘

logrotate 定期切割、压缩、删除旧日志,默认每天轮转,保留 7 个副本。

全局配置/etc/logrotate.conf

自定义配置目录/etc/logrotate.d/

示例:自定义日志轮转策略

复制代码
cat /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 7
    missingok
    notifempty
    copytruncate
}

手动触发轮转

复制代码
logrotate -f /etc/logrotate.conf

2.4 集中日志服务器:统一收集,方便审计

服务端配置/etc/rsyslog.conf 打开 UDP/TCP 接收):

复制代码
module(load="imudp")
input(type="imudp" port="514")
module(load="imtcp")
input(type="imtcp" port="514")

重启服务并开放防火墙。

客户端配置(发送日志到服务器):

复制代码
# 在 /etc/rsyslog.conf 末尾添加
*.info @192.168.200.128   # UDP
# 或使用 @@ 表示 TCP

三、时间同步服务:chronyd 的前世今生

时间同步是集群环境的基石(Ceph、OpenStack、K8S 均要求时间一致)。RHEL 8 起,ntpdchronyd 取代。

查看时间状态

复制代码
timedatectl

手动设置时间(需先关闭 NTP 服务)

复制代码
timedatectl set-ntp 0
timedatectl set-time "2026-07-12 15:00:00"

修改时区

复制代码
timedatectl list-timezones
timedatectl set-timezone Asia/Shanghai

配置 chrony 客户端/etc/chrony.conf):

复制代码
pool ntp.aliyun.com iburst   # 指定时间源

查看同步状态

复制代码
chronyc sources
  • ^* 表示当前已同步的时间源
  • ^? 表示无法连接

部署内部时间服务器

在服务端的 /etc/chrony.conf 中添加:

复制代码
allow 192.168.0.0/16   # 允许的网段
local stratum 10       # 即使未同步也作为时间源

重启 chronyd 服务即可。


四、SELinux:安全加固的"卫士"与"拦路虎"

SELinux 是内核级安全模块,通过文件标签端口标签布尔值三项机制控制进程行为。

4.1 三种工作模式

|--------------|--------------------|
| 模式 | 行为 |
| enforcing | 强制执行策略,拒绝违规操作并记录日志 |
| permissive | 只告警不拦截,用于调试 |
| disabled | 完全关闭,不加载策略 |

查看当前模式

复制代码
getenforce

临时切换(需在 enforcing 或 permissive 之间):

复制代码
setenforce 0   # 切换为 permissive
setenforce 1   # 切换为 enforcing

永久修改 :编辑 /etc/selinux/config,设置 SELINUX=disabled 等,需重启生效。

注意disabled 模式下无法直接切换到其他模式,必须重启。


4.2 文件标签管理(安全上下文)

每个文件和进程都有 SELinux 标签(安全上下文)。进程的标签必须与文件标签匹配才能访问。

查看标签

复制代码
ps -efZ        # 进程标签
ll -Z /etc/passwd   # 文件标签(如 system_u:object_r:passwd_file_t:s0)

临时修改标签chcon):

复制代码
chcon -t httpd_sys_content_t /var/www/html/index.html
# 恢复默认标签
restorecon -v /var/www/html/index.html

永久修改标签semanage fcontext):

复制代码
semanage fcontext -a -t httpd_sys_content_t "/var/www/html(/.*)?"
restorecon -Rv /var/www/html

修改永久生效,即使重启也不会丢失。

典型场景 :将 /root/index.html 移动到 /var/www/html/,其标签仍为 admin_home_t,Apache 进程(httpd_t)无法读取,需修改标签为 httpd_sys_content_t


4.3 端口标签管理

服务监听端口也必须拥有正确的端口标签,否则 SELinux 会拒绝绑定。

查看端口标签

复制代码
semanage port -l | grep http
http_port_t   tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000

为自定义端口添加标签(例如 Apache 监听 82):

复制代码
semanage port -a -t http_port_t -p tcp 82

故障排查 :如果 Apache 修改了端口后启动失败,查看日志会提示 Permission denied: make_sock: could not bind to address,此时应为新端口添加标签。


4.4 布尔值管理:控制程序行为

布尔值用于允许或禁止某个进程访问其他资源(如 NFS、FTP 等)。

查看与 HTTP 相关的布尔值

复制代码
semanage boolean -l | grep http

开启 Apache 访问 NFS 共享

复制代码
setsebool -P httpd_use_nfs on

-P 表示永久生效,不加则临时生效。

常用布尔值

  • httpd_can_network_connect:允许 Apache 向外发起网络连接
  • httpd_enable_homedirs:允许访问用户家目录
  • ftp_home_dir:允许 FTP 访问家目录

4.5 查看 SELinux 日志

SELinux 日志默认记录在审计日志 /var/log/audit/audit.log 中,但不易读。借助 setroubleshoot 服务,可将其转换为易读格式并输出到 /var/log/messages

查看 SELinux 相关日志

复制代码
grep -i selinux /var/log/messages

使用 sealert 获取详细解决建议

复制代码
sealert -l <UUID>

常用诊断命令

复制代码
# 查看所有违反策略的事件
ausearch -m avc
# 或者使用 journalctl
journalctl -t setroubleshoot

结语

系统故障不可怕,可怕的是不知道从哪里入手。掌握 GRUB 引导修复、日志分析方法、时间同步配置以及 SELinux 策略调优,你就拥有了排查绝大多数系统级问题的"工具箱"。

在实际运维中,建议按以下顺序排错

  1. 查看日志(先 journalctl -xe,再 tail -f /var/log/messages
  2. 检查 SELinux 是否拦截(查看 audit.logmessages
  3. 检查时间同步是否正常(集群环境尤其重要)
  4. 最后才考虑启动层面的故障

希望这篇指南能成为你日常运维的得力助手。如果你遇到文中未覆盖的问题,欢迎留言讨论!


📌 本文基于 RHEL9 系列编写,部分命令可能因发行版或版本不同略有差异,请以实际环境为准。

相关推荐
贺国亚1 小时前
A2A协议与Agent互操作-Task生命周期
开发语言·qt
炸薯条!1 小时前
从零开始学C++(4) --类和对象
开发语言·c++·算法
渡我白衣1 小时前
打印宏与socket模块设计
java·linux·开发语言·c++·ide·人工智能·eclipse
Wang's Blog2 小时前
Go-Zero框架上手前奏2: 微服务核心要素 —— 拆分、通信与无状态设计
开发语言·微服务·golang
我是坏垠12 小时前
Crypto、Cipher与Password:Java加密开发的三个核心概念
java·开发语言·python
white_ant12 小时前
JDK LTS 版本升级迁移注意事项大全
java·开发语言
Bobolink_12 小时前
跨境业务网络环境评估,“干净、一致、独享”三个关键指标
开发语言·网络·php·跨境网络·网络环境
你怎么知道我是队长12 小时前
JavaScript的变量和数据类型介绍
开发语言·javascript·ecmascript