ithuang
ithuang
发布于 2025-07-13 / 3 阅读
0

Shell 脚本模块化巡检系统并生成 HTML 报告

Shell 脚本模块化巡检系统并生成 HTML 报告

脚本整体介绍与使用

这些脚本集合了多个系统巡检和配置功能,旨在自动化收集系统信息、监控关键资源、检查安全性,并生成一份易于查看和分享的 HTML 格式报告。脚本遵循模块化设计原则,所有功能模块分开实现,易于扩展和维护。下面是本脚本的详细介绍与使用步骤。

1. 脚本介绍

为什么要写这些脚本?

随着系统运维任务日益增多,手动检查系统健康状况、资源使用情况以及安全配置等变得繁琐且容易出错。为了提高运维效率,减少人为错误,自动化脚本应运而生。这个脚本的目的是通过模块化设计自动化收集系统信息、检查资源使用情况和安全性,并生成HTML格式的报告,方便系统管理员查看与分享。通过这种方式,脚本能够节省时间,简化操作,确保系统运行的稳定与安全。

这些脚本提供了什么功能?

这些脚本的主要功能包括:

  1. 系统信息收集模块:自动收集系统的基本信息,如操作系统版本、内核版本、系统架构等。
  2. 内存使用情况检查模块:检查系统内存的使用情况,包括总内存、已用内存、剩余内存等。
  3. 磁盘使用情况检查模块:检查磁盘使用情况,显示磁盘挂载、使用率和剩余空间等。
  4. 网络配置检查模块:收集网络接口信息、IP地址、路由信息及监听端口。
  5. SSH公私钥检查模块:检查SSH公私钥的安全性。
  6. 防火墙配置模块:配置Firewalld防火墙规则(可选)。
  7. HTML报告生成模块:将收集到的系统信息生成HTML格式的巡检报告,便于查看和分享。
  8. 主脚本:整合所有模块,执行系统巡检并生成最终报告。

这些脚本的基本运行说明

  1. 为这些脚本添加执行权限: 通过命令为所有脚本文件添加执行权限:
chmod +x *.sh
  1. 执行主脚本 **main.sh**: 运行主脚本来开始巡检:
./main.sh

主脚本会依次执行各个模块,收集系统信息、检查内存、磁盘、网络等状态,并最终生成报告。

  1. 查看报告: 执行完成后,HTML报告将保存到/tmp/system_audit_report.html,可以用浏览器打开查看报告内容。

开发周期

  1. 阶段 1:需求分析与设计阶段(2天) 与企业沟通,明确脚本的功能需求和报告格式。
  2. 阶段 2:模块开发(3天) 开发各个功能模块并进行单元测试,确保每个模块的功能正常。
  3. 阶段 3:集成与优化(5天) 集成所有模块到主脚本中,进行集成测试并进行性能优化。
  4. 阶段 4:部署与维护(长期) 将脚本部署到生产环境,并根据实际情况进行维护和优化。

2. 脚本功能模块概述

2.1 系统信息收集模块 (system_info.sh)

该模块用于收集系统的基础信息,例如操作系统版本、内核版本、系统架构等,确保能够了解系统的基本状态。

2.2 内存使用情况检查模块 (memory_info.sh)

此模块用于检查系统的内存使用情况,包括总内存、已用内存、剩余内存等,帮助管理员了解内存资源的使用状况。

2.3 磁盘使用情况检查模块 (disk_info.sh)

此模块负责检查系统的磁盘使用情况,显示磁盘的挂载情况、使用率、剩余空间等信息,以帮助管理员监控磁盘空间的使用情况。

2.4 网络配置检查模块 (network_info.sh)

此模块检查系统的网络配置,包括网络接口、IP地址、路由信息以及当前的监听端口,帮助管理员评估系统的网络配置和安全状况。

2.5 SSH 公私钥检查模块 (ssh_keys_check.sh)

该模块检查系统的SSH公私钥文件,评估其安全性,并报告是否存在潜在的安全风险。

防火墙配置模块 (configure_firewalld.sh)

此模块负责配置系统的防火墙规则。它通过配置文件定义哪些端口和IP可以访问系统,提供基础的安全防护。

HTML 报告生成模块 (generate_html_report.sh)

该模块将所有收集到的系统信息转换为HTML格式,生成易于分享和查看的报告,方便在团队或其他相关方之间传播。

2.8 主脚本 (main.sh)

主脚本是执行系统巡检的核心,加载并调用其他模块,执行各个功能,最后生成完整的HTML报告。

3. 脚本使用步骤

3.1. 给脚本添加执行权限

首先,为每个脚本文件添加执行权限。可以通过以下命令为每个脚本添加执行权限:

chmod +x system_info.sh
chmod +x memory_info.sh
chmod +x disk_info.sh
chmod +x network_info.sh
chmod +x ssh_keys_check.sh
chmod +x generate_html_report.sh
chmod +x configure_firewalld.sh
chmod +x main.sh

3.2. 执行主脚本

执行主脚本 main.sh 来开始系统巡检和防火墙配置。运行以下命令:

./main.sh

主脚本会依次调用各个功能模块,执行系统信息收集、内存使用情况检查、磁盘使用情况检查、网络配置检查、SSH密钥检查、防火墙配置等操作,最后生成完整的HTML报告。

3.3. 查看报告

脚本执行完成后,会在 /tmp/ 目录下生成一个 HTML 格式的巡检报告,报告文件路径为 /tmp/system_audit_report.html。可以通过浏览器打开该文件来查看系统巡检的详细信息。

4. 模块化设计

本脚本采用模块化设计,将不同的功能拆分成独立的脚本模块,每个模块负责一个特定的功能。这样可以确保脚本结构清晰,并使得后续的维护和扩展更加简便。例如,如果需要新增一个检查项,可以直接编写新的模块,并在主脚本中调用。

5. 防火墙配置模块(进阶功能)

脚本还提供了防火墙配置模块,通过 configure_firewalld.sh 脚本可以自动化配置 Firewalld 防火墙规则。管理员只需编辑配置文件 firewalld_rules.conf,指定需要开放的端口和IP地址等规则,脚本将根据这些配置自动设置防火墙规则。

6. HTML 报告生成

所有的系统巡检信息将被汇总成一份 HTML 格式的报告,报告包括以下内容:

  • 系统信息(如操作系统版本、内核版本等)
  • 内存使用情况
  • 磁盘使用情况
  • 网络配置
  • SSH公私钥检查
  • 防火墙配置

报告内容通过 <pre> 标签进行格式化,确保显示效果清晰,便于阅读。

7. 可扩展性与定制化

该脚本的设计允许根据实际需要进行扩展和定制。管理员可以根据实际需求修改脚本中的检查项或防火墙规则,也可以新增模块来进行其他系统巡检任务。

例如,用户可以添加一个磁盘IO监控模块、CPU负载检查模块,或是将报告的格式进行自定义。此外,脚本提供了对Firewalld的基本配置功能,可以根据网络环境修改防火墙规则。

8. 整体概述

通过这套系统巡检脚本,管理员可以自动化地收集系统信息、监控资源使用情况、检查安全性,并生成详细且美观的 HTML 格式报告。脚本采用模块化设计,便于扩展和维护,适用于多种环境的自动化运维需求。

  • 模块化设计:每个功能被独立封装为模块,增强了代码的可读性和可维护性。
  • HTML报告:系统巡检结果以HTML格式呈现,方便共享和查看。
  • 扩展性:脚本结构简单清晰,易于扩展,适用于多种运维场景。

无论是用于日常巡检,还是进行安全审计,这些脚本都能大大提高系统运维的效率和准确性。

9. 核心模块讲解与实战演示

创建/shell_check_project目录并进入

[root@hab1 /root]# cd /shell/
[root@hab1 /shell]# mkdir shell_check_project
[root@hab1 /shell]# cd shell_check_project/
[root@hab1 /shell/shell_check_project]# pwd
/shell/shell_check_project

9.1. 系统信息收集模块 (**system_info.sh**)

该模块用于收集系统的基础信息,如操作系统版本、内核版本、系统架构等。

编辑脚本:

[root@hab1 /shell/shell_check_project]# vim system_info.sh
[root@hab1 /shell/shell_check_project]# cat system_info.sh
#!/bin/bash

# 系统信息模块
collect_system_info() {
    echo "系统版本:"
    cat /etc/os-release &>/dev/null || cat /etc/redhat-release &>/dev/null || echo '未知系统'

    echo "内核版本: $(uname -r)"
    echo "系统架构: $(uname -m)"
    uptime -s | xargs -I {} echo "启动时间: {}"
    uptime -p | xargs -I {} echo "运行时间: {}"

    # 打印巡检结果
    echo "系统信息收集完毕!"
}

脚本说明

#!/bin/bash

# ==================== 系统信息收集模块 ====================
# 功能:采集服务器的系统版本、内核、架构、启动时间、运行时长等基础信息
collect_system_info() {
    # 输出标题
    echo "系统版本:"

    # 尝试读取系统版本信息
    # 优先读取 /etc/os-release(通用Linux),失败则读取 /etc/redhat-release(CentOS/RHEL),都失败则输出“未知系统”
    # &>/dev/null 表示屏蔽命令执行时的错误输出
    cat /etc/os-release &>/dev/null || cat /etc/redhat-release &>/dev/null || echo '未知系统'
    
    # 获取并打印 Linux 内核版本号
    echo "内核版本: $(uname -r)"
    # 获取并打印系统架构(如 x86_64 / aarch64)
    echo "系统架构: $(uname -m)"
    
    # uptime -s:获取系统真实启动时间(格式:年-月-日 时:分:秒)
    # xargs -I {}:将前面命令的结果替换到 {} 位置,拼接输出
    uptime -s | xargs -I {} echo "启动时间: {}"
    
    # uptime -p:获取系统已运行时长(友好显示格式,如 up 2 days, 3 hours)
    uptime -p | xargs -I {} echo "运行时间: {}"
    
    # 提示信息:系统信息模块执行完成
    echo "系统信息收集完毕!"
}

9.2. 磁盘使用情况检查模块 (**disk_info.sh**)

该模块检查系统的磁盘使用情况。

编辑脚本:

[root@hab1 /shell/shell_check_project]# vim disk_info.sh
[root@hab1 /shell/shell_check_project]# cat disk_info.sh
#!/bin/bash

# 磁盘使用情况模块
collect_disk_info() {
    echo "磁盘使用情况:"
    df -hT

    # 打印巡检结果
    echo "磁盘使用情况收集完毕!"
}

脚本说明

#!/bin/bash

# ==================== 磁盘使用情况模块 ====================
# 功能:采集服务器磁盘分区、文件系统类型、容量、使用量、挂载点等信息
collect_disk_info() {
    # 输出模块标题
    echo "磁盘使用情况:"

    # 查看磁盘分区使用情况
    # df 命令:报告文件系统磁盘空间使用情况
    # -h:以人类易读的单位显示(KB/MB/GB/TB)
    # -T:显示文件系统类型(ext4/xfs/nfs等)
    df -hT
    
    # 提示信息:磁盘信息模块执行完成
    echo "磁盘使用情况收集完毕!"
}

9.3. HTML 报告生成模块 (**generate_html_report.sh**)

该模块将所有检查结果整合为HTML报告。

编辑脚本:

[root@hab1 /shell/shell_check_project]# vim generate_html_report.sh
[root@hab1 /shell/shell_check_project]# cat generate_html_report.sh
#!/bin/bash

# HTML报告生成模块
generate_html_report() {
    local output_file="$1"
    echo "<html><head><meta charset='utf-8'><title>系统巡检报告</title>" > "$output_file"
    echo "<style>body{font-family:'Arial';background:#f4f4f4;color:#333;margin:20px;}</style>" >> "$output_file"
    echo "</head><body>" >> "$output_file"
    echo "<h1>系统巡检报告</h1>" >> "$output_file"
    echo "<h2>系统信息</h2><pre>$(cat /tmp/system_info.txt)</pre>" >> "$output_file"
    echo "<h2>磁盘使用情况</h2><pre>$(cat /tmp/disk_info.txt)</pre>" >> "$output_file"
    echo "</body></html>" >> "$output_file"

    # 打印巡检结果
    echo "HTML报告生成完毕!"
}

脚本说明

#!/bin/bash

# ==================== HTML报告生成模块 ====================
# 功能:将收集好的系统信息、磁盘信息整合生成可视化HTML格式报告
# 参数:$1 传入生成的HTML报告文件路径(如 report.html)
generate_html_report() {
    # 定义局部变量,接收第一个参数:HTML输出文件路径
    local output_file="$1"

    # 清空并写入HTML头部结构,设置字符集为UTF-8、报告标题
    echo "<html><head><meta charset='utf-8'><title>系统巡检报告</title>" > "$output_file"
    # 写入CSS样式:设置页面字体、背景色、文字颜色、边距,让报告更美观
    echo "<style>body{font-family:'Arial';background:#f4f4f4;color:#333;margin:20px;}</style>" >> "$output_file"
    # 闭合head标签,开始页面主体内容
    echo "</head><body>" >> "$output_file"

    # 写入报告主标题
    echo "<h1>系统巡检报告</h1>" >> "$output_file"

    # 读取临时文件中的系统信息,用<pre>标签保留原始格式输出到HTML
    echo "<h2>系统信息</h2><pre>$(cat /tmp/system_info.txt)</pre>" >> "$output_file"
    # 读取临时文件中的磁盘信息,用<pre>标签保留原始格式输出到HTML
    echo "<h2>磁盘使用情况</h2><pre>$(cat /tmp/disk_info.txt)</pre>" >> "$output_file"

    # 闭合页面主体和HTML标签
    echo "</body></html>" >> "$output_file"

    # 提示信息:HTML报告生成完成
    echo "HTML报告生成完毕!"
}

9.4. 主脚本 (**main.sh**)

主脚本将调用各个功能模块,并生成最终的HTML报告。

编辑脚本:

[root@hab1 /shell/shell_check_project]# vim main.sh
[root@hab1 /shell/shell_check_project]# cat main.sh
#!/bin/bash

# 加载各个功能模块
source ./system_info.sh
source ./disk_info.sh
source ./generate_html_report.sh

# 执行系统巡检
echo "开始系统巡检..."

# 收集系统信息
collect_system_info &> /tmp/system_info.txt
sleep 1

# 收集磁盘信息
collect_disk_info &> /tmp/disk_info.txt
sleep 1

# 生成HTML报告
generate_html_report "/tmp/system_audit_report.html"

echo "系统巡检完成!报告路径:/tmp/system_audit_report.html"

脚本说明

#!/bin/bash

# ==================== 系统巡检主脚本 ====================
# 功能:主入口程序,负责加载功能模块、执行巡检、生成最终报告
# 说明:统一调度系统信息、磁盘信息采集,并输出HTML报告

# 加载各个功能模块文件(引入外部脚本函数)
# source:读取并执行指定脚本,将里面的函数加载到当前环境
source ./system_info.sh       # 加载系统信息采集模块
source ./disk_info.sh         # 加载磁盘信息采集模块
source ./generate_html_report.sh  # 加载HTML报告生成模块

# 执行系统巡检(开始提示)
echo "开始系统巡检..."

# 收集系统信息
# 调用函数并将所有输出(标准输出+错误输出)重定向到临时文件
collect_system_info &> /tmp/system_info.txt
# 等待1秒,保证文件写入完成(防止多模块同时写入冲突)
sleep 1

# 收集磁盘信息
# 调用函数并将所有输出重定向到临时文件
collect_disk_info &> /tmp/disk_info.txt
# 等待1秒,保证文件写入完成
sleep 1

# 生成HTML报告
# 调用报告生成函数,传入报告保存路径
generate_html_report "/tmp/system_audit_report.html"

# 巡检完成提示,输出最终报告路径
echo "系统巡检完成!报告路径:/tmp/system_audit_report.html"

9.5. 实战演示

9.5.1. 查看脚本整体情况

[root@hab1 /shell/shell_check_project]# tree
.
├── disk_info.sh
├── generate_html_report.sh
├── main.sh
└── system_info.sh

0 directories, 4 files

9.5.2. 给脚本添加执行权限

首先,为每个脚本文件添加执行权限:

[root@hab1 /shell/shell_check_project]# chmod +x *.sh
[root@hab1 /shell/shell_check_project]# ll
总用量 16
-rwxr-xr-x 1 root root 181  4月 13 22:52 disk_info.sh
-rwxr-xr-x 1 root root 694  4月 13 22:53 generate_html_report.sh
-rwxr-xr-x 1 root root 461  4月 13 22:55 main.sh
-rwxr-xr-x 1 root root 435  4月 13 22:51 system_info.sh

9.5.3. 执行主脚本

执行主脚本 main.sh 来开始系统巡检:

[root@hab1 /shell/shell_check_project]# ./main.sh
开始系统巡检...
HTML报告生成完毕!
系统巡检完成!报告路径:/tmp/system_audit_report.html
[root@hab1 /shell/shell_check_project]# date -R
Mon, 13 Apr 2026 22:59:40 +0800

9.5.4. 查看报告

脚本执行后,会生成 HTML 格式的巡检报告。可以通过浏览器查看:

[root@hab1 /shell/shell_check_project]# cat /tmp/system_audit_report.html
<html><head><meta charset='utf-8'><title>系统巡检报告</title>
<style>body{font-family:'Arial';background:#f4f4f4;color:#333;margin:20px;}</style>
</head><body>
<h1>系统巡检报告</h1>
<h2>系统信息</h2><pre>系统版本:
内核版本: 5.14.0-511.el9.x86_64
系统架构: x86_64
启动时间: 2026-04-13 20:04:48
运行时间: up 2 hours, 54 minutes
系统信息收集完毕!</pre>
<h2>磁盘使用情况</h2><pre>磁盘使用情况:
文件系统            类型      容量  已用  可用 已用% 挂载点
devtmpfs            devtmpfs  4.0M     0  4.0M    0% /dev
tmpfs               tmpfs     871M     0  871M    0% /dev/shm
tmpfs               tmpfs     349M  5.2M  344M    2% /run
efivarfs            efivarfs  256K   54K  198K   22% /sys/firmware/efi/efivars
/dev/mapper/cs-root xfs        47G  3.8G   43G    9% /
/dev/nvme0n1p2      xfs       960M  226M  735M   24% /boot
/dev/nvme0n1p1      vfat      599M  7.5M  592M    2% /boot/efi
tmpfs               tmpfs     175M  4.0K  175M    1% /run/user/0
磁盘使用情况收集完毕!</pre>
</body></html>

Shell 脚本模块化巡检系统并生成 HTML 报告1.png

10. 编写或测试过程中可能遇到的重大问题

10.1.1. 问题 1:数据格式不一致或信息缺失

  • 问题描述:在不同版本的操作系统中,收集的系统信息可能格式不一致。例如,/etc/os-release 在某些系统上不存在,导致信息收集失败。
  • 如何发现:通过在不同环境下测试脚本时发现,一些系统无法读取操作系统版本信息。
  • 解决方案:在脚本中加入更多的容错处理和兼容性检查。例如,检查多个路径或使用uname命令来补充操作系统信息。
cat /etc/os-release 2>/dev/null || cat /etc/redhat-release 2>/dev/null || uname -o

10.1.2. 问题 2:模块间数据传递问题

  • 问题描述:在某些情况下,模块之间的数据传递可能出现问题,例如内存使用情况模块和系统信息模块的输出没有正确存储,导致生成报告时数据缺失。
  • 如何发现:通过测试脚本时发现,报告中缺少部分信息。
  • 解决方案:确保每个模块的输出被正确重定向到临时文件中,并且在生成报告时读取这些文件。例如,在每个模块中使用> /tmp/xxx.txt来保存数据。

脚本结构与模块化设计

创建/shell_check_project目录并进入

将脚本拆分为多个独立模块,并通过主脚本将这些模块组合起来:

1. 系统信息收集模块 (**system_info.sh**)

该模块用于收集系统的基础信息,如操作系统版本、内核版本、系统架构等。

编辑脚本:

[root@hab1 /shell/shell_check_project]# vim system_info.sh
[root@hab1 /shell/shell_check_project]# cat system_info.sh
#!/bin/bash

# 系统信息模块
collect_system_info() {
    echo "系统版本:"
    cat /etc/os-release &>/dev/null || cat /etc/redhat-release &>/dev/null || echo '未知系统'

    echo "内核版本: $(uname -r)"
    echo "系统架构: $(uname -m)"
    uptime -s | xargs -I {} echo "启动时间: {}"
    uptime -p | xargs -I {} echo "运行时间: {}"

    # 打印巡检结果
    echo "系统信息收集完毕!"
}

脚本说明

#!/bin/bash

# ==================== 系统信息采集模块 ====================
# 函数功能:收集服务器的系统版本、内核、架构、开机时间、运行时长等基础信息
collect_system_info() {
    # 输出标题:系统版本
    echo "系统版本:"

    # 获取系统发行版信息(兼容绝大多数 Linux)
    # &>/dev/null 表示屏蔽命令执行失败或者成功提示
    # 优先读取 /etc/os-release → 失败则读取 CentOS/RHEL 专用文件 → 都失败显示“未知系统”
    cat /etc/os-release &>/dev/null || cat /etc/redhat-release 2>/dev/null || echo '未知系统'
    
    # uname -r:获取 Linux 内核版本号
    echo "内核版本: $(uname -r)"
    
    # uname -m:获取系统架构(x86_64 表示 64 位,aarch64 表示 ARM 架构)
    echo "系统架构: $(uname -m)"
    
    # uptime -s:获取系统**确切启动时间**(格式:年-月-日 时:分:秒)
    # xargs -I {}:把前面的结果替换到 {} 位置,实现格式化输出
    uptime -s | xargs -I {} echo "启动时间: {}"
    
    # uptime -p:获取系统**已运行时长**(人性化显示,如 up 3 days, 2 hours)
    uptime -p | xargs -I {} echo "运行时间: {}"
    
    # 模块执行完成提示
    echo "系统信息收集完毕!"
}

2. 内存使用情况检查模块 (**memory_info.sh**)

该模块检查系统的内存使用情况,包括总内存、已用内存和交换空间。

编辑脚本:

[root@hab1 /shell/shell_check_project]# vim memory_info.sh
[root@hab1 /shell/shell_check_project]# cat memory_info.sh
#!/bin/bash

# 内存使用情况模块
collect_memory_info() {
    echo "内存使用情况:"
    free -h

    # 打印巡检结果
    echo "内存使用情况收集完毕!"
}

脚本说明

#!/bin/bash

# ==================== 内存使用情况模块 ====================
# 功能:采集服务器物理内存、交换分区(Swap)的总容量、已用、空闲等信息
collect_memory_info() {
    # 输出模块标题
    echo "内存使用情况:"
    
    # 查看内存使用详情
    # free 命令:显示系统内存和交换分区使用情况
    # -h:以人类易读的单位显示(KB/MB/GB),方便查看
    free -h
    
    # 提示信息:内存信息模块执行完成
    echo "内存使用情况收集完毕!"
}

3. 磁盘使用情况检查模块 (**disk_info.sh**)

该模块检查系统的磁盘使用情况。

编辑脚本:

[root@hab1 /shell/shell_check_project]# vim disk_info.sh
[root@hab1 /shell/shell_check_project]# cat disk_info.sh
#!/bin/bash

# 磁盘使用情况模块
collect_disk_info() {
    echo "磁盘使用情况:"
    df -hT

    # 打印巡检结果
    echo "磁盘使用情况收集完毕!"
}

脚本说明

#!/bin/bash

# ==================== 磁盘使用情况模块 ====================
# 功能:收集系统磁盘分区、文件系统类型、总容量、已用、剩余、使用率、挂载点等信息
collect_disk_info() {
    # 输出模块标题
    echo "磁盘使用情况:"

    # 显示磁盘使用情况
    # df    :查看文件系统磁盘占用
    # -h    :以人类易读的单位显示(GB/MB)
    # -T    :显示文件系统类型(ext4/xfs/nfs等)
    df -hT

    # 提示信息:磁盘信息收集完成
    echo "磁盘使用情况收集完毕!"
}

4. 网络配置检查模块 (**network_info.sh**)

该模块检查系统的网络配置信息。

编辑脚本:

[root@hab1 /shell/shell_check_project]# vim network_info.sh
[root@hab1 /shell/shell_check_project]# cat network_info.sh
#!/bin/bash

# 网络配置模块
collect_network_info() {
    echo "网络配置:"
    ip -4 -o addr show
    ip route show
    ss -tulpen

    # 打印巡检结果
    echo "网络配置收集完毕!"
}

脚本说明

#!/bin/bash

# ==================== 网络配置信息模块 ====================
# 功能:收集服务器IP地址、路由表、监听端口等核心网络信息
collect_network_info() {
    # 输出模块标题
    echo "网络配置:"

    # 查看IPv4地址信息
    # -4      :只显示IPv4协议
    # -o      :精简格式输出(一行一个网卡,方便查看)
    # addr show:显示所有网络接口的IP地址
    ip -4 -o addr show

    # 查看系统路由表(默认网关、路由规则)
    ip route show

    # 查看监听端口与网络连接
    # ss      :查看网络套接字(比netstat更高效)
    # -t      :显示TCP端口
    # -u      :显示UDP端口
    # -l      :仅显示监听状态的端口
    # -p      :显示占用端口的进程
    # -e      :显示扩展信息
    # -n      :以数字形式显示IP和端口(不反向解析)
    ss -tulpen
    
    # 提示信息:网络信息收集完成
    echo "网络配置收集完毕!"
}

脚本说明

#!/bin/bash

# ==================== 网络配置信息模块 ====================
# 功能:收集服务器IP地址、路由表、监听端口等核心网络信息
collect_network_info() {
    # 输出模块标题
    echo "网络配置:"

    # 查看IPv4地址信息
    # -4      :只显示IPv4协议
    # -o      :精简格式输出(一行一个网卡,方便查看)
    # addr show:显示所有网络接口的IP地址
    ip -4 -o addr show

    # 查看系统路由表(默认网关、路由规则)
    ip route show

    # 查看监听端口与网络连接
    # ss      :查看网络套接字(比netstat更高效)
    # -t      :显示TCP端口
    # -u      :显示UDP端口
    # -l      :仅显示监听状态的端口
    # -p      :显示占用端口的进程
    # -e      :显示扩展信息
    # -n      :以数字形式显示IP和端口(不反向解析)
    ss -tulpen
    
    # 提示信息:网络信息收集完成
    echo "网络配置收集完毕!"
}

5. SSH 公私钥检查模块 (**ssh_keys_check.sh**)

该模块检查 SSH 公私钥的安全性。

编辑脚本:

[root@hab1 /shell/shell_check_project]# vim ssh_keys_check.sh
[root@hab1 /shell/shell_check_project]# cat ssh_keys_check.sh
#!/bin/bash

# SSH公私钥检查模块
check_ssh_keys() {
    SSH_DIR="$HOME/.ssh"

    if [ -d "$SSH_DIR" ]; then
        echo "SSH 目录存在: $SSH_DIR"
        ls -l "$SSH_DIR"
        if [ -f "$SSH_DIR/id_rsa" ]; then
            echo "检测到私钥: $SSH_DIR/id_rsa"
            stat -c '权限: %A  大小: %s bytes  修改时间: %y' "$SSH_DIR/id_rsa"
        fi
    else
        echo "SSH 目录不存在: $SSH_DIR"
    fi

    # 打印巡检结果
    echo "SSH密钥检查完毕!"
}

脚本说明

#!/bin/bash

# ==================== SSH 公私钥检查模块 ====================
# 功能:检查当前用户的 SSH 目录是否存在、目录下文件详情、私钥文件及权限等安全信息
check_ssh_keys() {
    # 定义 SSH 密钥默认存放路径(当前用户家目录下的 .ssh 文件夹)
    SSH_DIR="$HOME/.ssh"
    
    # 判断 SSH 目录是否存在(-d 表示检测是否为目录)
    if [ -d "$SSH_DIR" ]; then
        # 目录存在时输出提示
        echo "SSH 目录存在: $SSH_DIR"
        # 列出 SSH 目录下所有文件的详细信息(权限、属主、大小、时间等)
        ls -l "$SSH_DIR"
        
        # 进一步检查是否存在默认的 RSA 私钥文件 id_rsa
        if [ -f "$SSH_DIR/id_rsa" ]; then
            echo "检测到私钥: $SSH_DIR/id_rsa"
            # 查看私钥文件详情:权限、大小、修改时间
            stat -c '权限: %A  大小: %s bytes  修改时间: %y' "$SSH_DIR/id_rsa"
        fi
    else
        # 目录不存在时输出提示
        echo "SSH 目录不存在: $SSH_DIR"
    fi
    
    # 模块执行完成提示
    echo "SSH密钥检查完毕!"
}

6. HTML 报告生成模块 (**generate_html_report.sh**)

该模块将所有检查结果整合为HTML报告。

[root@hab1 /shell/shell_check_project]# vim generate_html_report.sh
[root@hab1 /shell/shell_check_project]# cat generate_html_report.sh
#!/bin/bash

# HTML报告生成模块
generate_html_report() {
    local output_file="$1"
    echo "<html><head><meta charset='utf-8'><title>系统巡检报告</title>" > "$output_file"
    echo "<style>body{font-family:'Arial';background:#f4f4f4;color:#333;margin:20px;}</style>" >> "$output_file"
    echo "</head><body>" >> "$output_file"
    echo "<h1>系统巡检报告</h1>" >> "$output_file"
    echo "<h2>系统信息</h2><pre>$(cat /tmp/system_info.txt)</pre>" >> "$output_file"
    echo "<h2>内存使用情况</h2><pre>$(cat /tmp/memory_info.txt)</pre>" >> "$output_file"
    echo "<h2>磁盘使用情况</h2><pre>$(cat /tmp/disk_info.txt)</pre>" >> "$output_file"
    echo "<h2>网络配置</h2><pre>$(cat /tmp/network_info.txt)</pre>" >> "$output_file"
    echo "<h2>SSH公私钥检查</h2><pre>$(cat /tmp/ssh_keys_check.txt)</pre>" >> "$output_file"
    echo "</body></html>" >> "$output_file"

    # 打印巡检结果
    echo "HTML报告生成完毕!"
}

脚本说明

#!/bin/bash

# ==================== HTML报告生成模块 ====================
# 功能:将所有巡检模块收集的信息整合,生成一份美观的HTML格式报告
# 参数:$1 传入生成的HTML报告保存路径
generate_html_report() {
    # 定义局部变量,接收第一个参数:HTML输出文件路径
    local output_file="$1"

    # 写入HTML文档开头,设置UTF-8编码和报告标题
    echo "<html><head><meta charset='utf-8'><title>系统巡检报告</title>" > "$output_file"
    # 写入CSS样式,优化报告页面显示效果(字体、背景、颜色、边距)
    echo "<style>body{font-family:'Arial';background:#f4f4f4;color:#333;margin:20px;}</style>" >> "$output_file"
    # 闭合头部标签,开始页面主体内容
    echo "</head><body>" >> "$output_file"

    # 输出报告主标题
    echo "<h1>系统巡检报告</h1>" >> "$output_file"

    # 读取各模块临时文件内容,用<pre>标签保留命令行原始格式输出到HTML
    echo "<h2>系统信息</h2><pre>$(cat /tmp/system_info.txt)</pre>" >> "$output_file"
    echo "<h2>内存使用情况</h2><pre>$(cat /tmp/memory_info.txt)</pre>" >> "$output_file"
    echo "<h2>磁盘使用情况</h2><pre>$(cat /tmp/disk_info.txt)</pre>" >> "$output_file"
    echo "<h2>网络配置</h2><pre>$(cat /tmp/network_info.txt)</pre>" >> "$output_file"
    echo "<h2>SSH公私钥检查</h2><pre>$(cat /tmp/ssh_keys_check.txt)</pre>" >> "$output_file"

    # 闭合页面主体和HTML标签
    echo "</body></html>" >> "$output_file"

    # 提示信息:HTML报告生成完成
    echo "HTML报告生成完毕!"
}

7. 主脚本 (**main.sh**)

主脚本将调用各个功能模块,并生成最终的HTML报告。

[root@hab1 /shell/shell_check_project]# vim main.sh
[root@hab1 /shell/shell_check_project]# cat main.sh
#!/bin/bash

# 加载各个功能模块
source ./system_info.sh
source ./memory_info.sh
source ./disk_info.sh
source ./network_info.sh
source ./ssh_keys_check.sh
source ./generate_html_report.sh

# 执行系统巡检
echo "开始系统巡检..."

# 收集系统信息
collect_system_info > /tmp/system_info.txt
sleep 1

# 收集内存信息
collect_memory_info > /tmp/memory_info.txt
sleep 1

# 收集磁盘信息
collect_disk_info > /tmp/disk_info.txt
sleep 1

# 收集网络信息
collect_network_info > /tmp/network_info.txt
sleep 1

# 检查SSH密钥
check_ssh_keys > /tmp/ssh_keys_check.txt
sleep 1

# 生成HTML报告
generate_html_report "/tmp/system_audit_report.html"

echo "系统巡检完成!报告路径:/tmp/system_audit_report.html"

脚本说明

#!/bin/bash

# ==================== 系统巡检主程序 ====================
# 功能:系统巡检入口脚本,统一调度所有模块,生成HTML可视化报告
# 模块包含:系统信息、内存、磁盘、网络、SSH密钥检查

# 加载所有功能模块(将外部脚本函数引入当前脚本环境)
source ./system_info.sh       # 系统基础信息模块
source ./memory_info.sh      # 内存使用情况模块
source ./disk_info.sh        # 磁盘使用情况模块
source ./network_info.sh     # 网络配置信息模块
source ./ssh_keys_check.sh   # SSH密钥安全检查模块
source ./generate_html_report.sh # HTML报告生成模块

# 巡检开始提示
echo "开始系统巡检..."

# 1. 收集系统信息,输出写入临时文件
collect_system_info > /tmp/system_info.txt
sleep 1

# 2. 收集内存使用信息,输出写入临时文件
collect_memory_info > /tmp/memory_info.txt
sleep 1

# 3. 收集磁盘使用信息,输出写入临时文件
collect_disk_info > /tmp/disk_info.txt
sleep 1

# 4. 收集网络配置信息,输出写入临时文件
collect_network_info > /tmp/network_info.txt
sleep 1

# 5. 检查SSH密钥安全,输出写入临时文件
check_ssh_keys > /tmp/ssh_keys_check.txt
sleep 1

# 生成最终HTML巡检报告
generate_html_report "/tmp/system_audit_report.html"

# 巡检完成提示,显示报告保存路径
echo "系统巡检完成!报告路径:/tmp/system_audit_report.html"

脚本使用步骤

查看脚本整体情况

[root@hab1 /shell/shell_check_project]# tree
.
├── disk_info.sh
├── generate_html_report.sh
├── main.sh
├── memory_info.sh
├── network_info.sh
├── ssh_keys_check.sh
└── system_info.sh

0 directories, 7 files

1. 给脚本添加执行权限

首先,为每个脚本文件添加执行权限:

[root@hab1 /shell/shell_check_project]# chmod +x *.sh
[root@hab1 /shell/shell_check_project]# ll
总用量 28
-rwxr-xr-x 1 root root 181  4月 13 22:52 disk_info.sh
-rwxr-xr-x 1 root root 977  4月 13 23:16 generate_html_report.sh
-rwxr-xr-x 1 root root 751  4月 13 23:18 main.sh
-rwxr-xr-x 1 root root 184  4月 13 23:08 memory_info.sh
-rwxr-xr-x 1 root root 211  4月 13 23:11 network_info.sh
-rwxr-xr-x 1 root root 508  4月 13 23:15 ssh_keys_check.sh
-rwxr-xr-x 1 root root 435  4月 13 22:51 system_info.sh

2. 执行主脚本

执行主脚本 main.sh 来开始系统巡检:

./main.sh


[root@hab1 /shell/shell_check_project]# ./main.sh
开始系统巡检...
HTML报告生成完毕!
系统巡检完成!报告路径:/tmp/system_audit_report.html

3. 查看报告

脚本执行后,会生成 HTML 格式的巡检报告。可以通过浏览器查看:

/tmp/system_audit_report.html

Shell 脚本模块化巡检系统并生成 HTML 报告2.png

Shell 脚本模块化巡检系统并生成 HTML 报告3.png

Firewalld 防火墙配置模块(进阶)

创建/shell_check_project目录并进入

1. 主脚本:**main.sh**

这个脚本是主要的执行脚本,加载并调用每个模块。

[root@hab1 /shell/shell_check_project]# vim main.sh
[root@hab1 /shell/shell_check_project]# cat main.sh
#!/bin/bash

# 加载各个功能模块
source ./system_info.sh
source ./memory_info.sh
source ./disk_info.sh
source ./network_info.sh
source ./ssh_keys_check.sh
source ./configure_firewalld.sh
source ./generate_html_report.sh

# 执行系统巡检
echo "开始系统巡检..."

# 收集系统信息
collect_system_info > /tmp/system_info.txt
sleep 1

# 收集内存信息
collect_memory_info > /tmp/memory_info.txt
sleep 1

# 收集磁盘信息
collect_disk_info > /tmp/disk_info.txt
sleep 1

# 收集网络信息
collect_network_info > /tmp/network_info.txt
sleep 1

# 检查SSH密钥
check_ssh_keys > /tmp/ssh_keys_check.txt
sleep 1

# 配置防火墙
configure_firewalld > /tmp/firewalld_config.txt
sleep 1

# 生成HTML报告
generate_html_report "/tmp/system_audit_report.html"

echo "系统巡检完成!报告路径:/tmp/system_audit_report.html"

脚本说明

#!/bin/bash

# ==================== 系统巡检主程序(完整版) ====================
# 功能:系统巡检 + 安全配置入口脚本
# 包含模块:系统/内存/磁盘/网络/SSH/防火墙,最终生成HTML报告

# 加载所有功能模块文件(引入函数到当前脚本环境)
source ./system_info.sh           # 系统基础信息采集模块
source ./memory_info.sh           # 内存使用情况采集模块
source ./disk_info.sh             # 磁盘使用情况采集模块
source ./network_info.sh          # 网络配置信息采集模块
source ./ssh_keys_check.sh        # SSH密钥安全检查模块
source ./configure_firewalld.sh   # 新增:Firewalld 防火墙配置/检查模块
source ./generate_html_report.sh  # HTML报告生成模块

# 巡检开始提示
echo "开始系统巡检..."

# 1. 收集系统基础信息 → 写入临时文件
collect_system_info > /tmp/system_info.txt
sleep 1

# 2. 收集内存使用信息 → 写入临时文件
collect_memory_info > /tmp/memory_info.txt
sleep 1

# 3. 收集磁盘使用信息 → 写入临时文件
collect_disk_info > /tmp/disk_info.txt
sleep 1

# 4. 收集网络配置信息 → 写入临时文件
collect_network_info > /tmp/network_info.txt
sleep 1

# 5. 检查SSH密钥安全 → 写入临时文件
check_ssh_keys > /tmp/ssh_keys_check.txt
sleep 1

# 6. 防火墙配置与状态检查 → 写入临时文件
configure_firewalld > /tmp/firewalld_config.txt
sleep 1

# 调用HTML生成函数,整合所有信息生成最终报告
generate_html_report "/tmp/system_audit_report.html"

# 巡检完成提示,输出报告路径
echo "系统巡检完成!报告路径:/tmp/system_audit_report.html"

2. 防火墙配置文件:**firewalld_rules.conf**

在此文件中,可以定义要使用的防火墙规则:

[root@hab1 /shell/shell_check_project]# vim firewalld_rules.conf
[root@hab1 /shell/shell_check_project]# cat firewalld_rules.conf
# 只需正确写出的外网网卡(如 ens160)即可
EXTERNAL_INTERFACE=ens160
# 也支持 INTERFACE=ens160(两者任选其一)

# 可选:public 的 target(不需要就注释掉)
# TARGET=DROP

# 外网默认接受的端口(数组内允许范围)
EXTERNAL_TCP_PORTS=(
  500-600
  666
)
EXTERNAL_UDP_PORTS=(
  9030
  10001-11200
)

# 外网富规则(IP+端口)
EXTERNAL_ALLOWED_IPS=(
  119.29.112.81
  119.29.112.82
)
EXTERNAL_TCP_RICH_PORTS=(
  666
  1024-2012
  22
  36000
)
EXTERNAL_UDP_RICH_PORTS=(
  2012-65535
  666
)

# 可以继续写原生命令(必须带 --permanent 让配置永久生效)
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.88.1" port port="22" protocol="tcp" accept'
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" protocol value="icmp" accept'

3. Firewalld 防火墙配置模块:**configure_firewalld.sh**

此模块包含了Firewalld防火墙规则的配置部分,将简化并只配置内网和外网的基本策略。

[root@hab1 /shell/shell_check_project]# vim configure_firewalld.sh
[root@hab1 /shell/shell_check_project]# cat configure_firewalld.sh
#!/bin/bash

configure_firewalld() {
# 任何错误、未定义变量、管道失败都立刻停下来
set -Eeuo pipefail

# 启动 firewalld
systemctl enable --now firewalld

# 定义配置文件
CFG="${1:-firewalld_rules.conf}"
LOG="/tmp/firewalld_config.txt"

[[ -r "$CFG" ]] || { echo "配置文件不可读: $CFG" >&2; exit 1; }
# shellcheck source=/dev/null
source "$CFG"

# 取外网网卡变量(EXTERNAL_INTERFACE 或 INTERFACE)
INTERFACE="${EXTERNAL_INTERFACE:-${INTERFACE:-}}"
[[ -n "${INTERFACE}" ]] || { echo "请在配置中设置 EXTERNAL_INTERFACE=ens160(或 INTERFACE=ens160)" >&2; exit 1; }

log(){ echo "[$(date +'%F %T')] $*" | tee -a "$LOG"; }
run(){ log "+ $*"; "$@" >>"$LOG" 2>&1; }

log "=== 只配置 public 区域 + 网卡 ${INTERFACE} ==="

# 绑定网卡到 public(幂等)
run firewall-cmd --permanent --zone=public --add-interface="${INTERFACE}"

# 可选:设置 public 的 target(如 TARGET=DROP)
if [[ -n "${TARGET:-}" ]]; then
  run firewall-cmd --permanent --zone=public --set-target="${TARGET}"
fi

# —— 数组式端口:只处理 EXTERNAL_* —— #
add_ports(){
  local proto=$1; shift
  local -a ports=("$@")
  for p in "${ports[@]:-}"; do
    [[ -n "$p" ]] || continue
    run firewall-cmd --permanent --zone=public --add-port="${p}/${proto}"
  done
}

# 基础端口(全网放开)
add_ports tcp "${EXTERNAL_TCP_PORTS[@]:-}"
add_ports udp "${EXTERNAL_UDP_PORTS[@]:-}"

# 白名单 + 端口(rich-rule)
add_rich_ip_ports(){
  local proto=$1; shift
  local -a ports=("$@")
  for ip in "${EXTERNAL_ALLOWED_IPS[@]:-}"; do
    [[ -n "$ip" ]] || continue
    for p in "${ports[@]:-}"; do
      [[ -n "$p" ]] || continue
      run firewall-cmd --permanent --zone=public \
        --add-rich-rule="rule family='ipv4' source address='${ip}' port port='${p}' protocol='${proto}' accept"
    done
  done
}
add_rich_ip_ports tcp "${EXTERNAL_TCP_RICH_PORTS[@]:-}"
add_rich_ip_ports udp "${EXTERNAL_UDP_RICH_PORTS[@]:-}"

# —— 执行配置文件里的原生命令 —— #
# 仅执行以 "firewall-cmd" 开头且包含 "--permanent" 的行(不会执行 reload / list 等)
log "执行配置文件中的原生 firewalld 规则..."
while IFS= read -r line; do
  line="$(echo "$line" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')"
  [[ -z "$line" || "$line" =~ ^# ]] && continue
  [[ "$line" == firewall-cmd* && "$line" == *"--permanent"* ]] || continue
  # 忽略 reload / list 之类
  if echo "$line" | grep -Eq -- '--reload|--list-'; then
    continue
  fi
  # shellcheck disable=SC2086
  run bash -c "$line"
done < "$CFG"

# 生效与摘要
run firewall-cmd --reload
{
  echo
  echo "===== public 最终配置 ====="
  firewall-cmd --zone=public --list-all
} >>"$LOG" 2>&1

echo "配置Firewalld防火墙完成,详情见 ${LOG} 或者 firewall-cmd --zone=public --list-all"
}

脚本说明

#!/bin/bash

# 定义防火墙配置函数,所有防火墙操作都封装在此函数内
configure_firealld() {

# 严格模式:任何错误、未定义变量、管道命令失败都会立即终止脚本,避免错误扩散
# set -E:捕获函数内部错误
# set -e:命令执行失败立即退出
# set -u:使用未定义变量直接报错退出
# set -o pipefail:管道中任意命令失败,整个管道返回失败
set -Eeuo pipefail

# 启动并开机自启 firewalld 防火墙服务
# systemctl:系统服务管理命令
# enable:设置开机自启
# --now:立即启动服务
systemctl enable --now firewalld

# 定义配置文件路径:优先使用传入的第1个参数,没有则默认使用 firewalld_rules.conf
# ${1:-xxx}:如果$1不存在/为空,就使用后面的默认值
CFG="${1:-firewalld_rules.conf}"

# 定义日志文件路径,所有操作日志会记录在这里
LOG="/tmp/firewalld_config.txt"

# 判断配置文件是否存在且可读
# [[ -r "$CFG" ]]:检查文件是否存在且可读
# ||:或逻辑,前面条件不满足则执行后面的语句
# { ... }:代码块,将多条命令作为一个整体执行
# >&2:将错误信息输出到标准错误(stderr)
# exit 1:脚本异常退出,返回状态码1
[[ -r "$CFG" ]] || { echo "配置文件不可读: $CFG" >&2; exit 1; }

# 加载配置文件,读取配置文件中定义的变量(网卡、端口、IP等)
# shellcheck source=/dev/null:告诉shellcheck检查工具忽略此文件的来源检查
source "$CFG"

# 获取外网网卡名称:优先使用 EXTERNAL_INTERFACE,不存在则使用 INTERFACE,都不存在则为空
INTERFACE="${EXTERNAL_INTERFACE:-${INTERFACE:-}}"

# 判断网卡变量是否有值,无值则提示并退出
# [[ -n "${INTERFACE}" ]]:判断变量是否非空
[[ -n "${INTERFACE}" ]] || { echo "请在配置中设置 EXTERNAL_INTERFACE=ens160(或 INTERFACE=ens160)" >&2; exit 1; }

# 日志函数:输出带时间戳的日志,并同时写入日志文件
# $*:所有传入函数的参数
# tee -a:追加写入文件,同时在屏幕输出
log(){ echo "[$(date +'%F %T')] $*" | tee -a "$LOG"; }

# 执行命令函数:先打印要执行的命令,再执行命令,并将命令输出写入日志
# "+ $*":日志中标记这是执行的命令行
# "$@":执行传入的所有参数(即原命令)
# >>"$LOG" 2>&1:标准输出+标准错误都追加写入日志
run(){ log "+ $*"; "$@" >>"$LOG" 2>&1; }

# 打印开始配置日志
log "=== 只配置 public 区域 + 网卡 ${INTERFACE} ==="

# 将指定网卡永久绑定到 public 区域(幂等:重复执行不会报错)
# firewall-cmd:firewalld防火墙命令行工具
# --permanent:永久生效(重启后依然存在)
# --zone=public:指定操作的区域为public
# --add-interface:将网卡添加到区域
run firewall-cmd --permanent --zone=public --add-interface="${INTERFACE}"

# 可选配置:设置public区域的默认策略(如拒绝所有未匹配流量 TARGET=DROP)
# ${TARGET:-}:如果TARGET变量未定义,则视为空
# --set-target:设置区域默认目标(ACCEPT/DROP/REJECT)
if [[ -n "${TARGET:-}" ]]; then
  run firewall-cmd --permanent --zone=public --set-target="${TARGET}"
fi

# 定义函数:批量添加协议+端口到防火墙(永久开放)
# $1:第一个参数,协议(tcp/udp)
# shift:丢弃第一个参数,剩下的都是端口
# local -a ports=("$@"):定义本地数组变量,存储端口列表
add_ports(){
  local proto=$1; shift
  local -a ports=("$@")

  # 循环遍历端口数组
  # ${ports[@]:-}:数组所有元素,为空则不循环
  for p in "${ports[@]:-}"; do
    [[ -n "$p" ]] || continue  # 端口为空则跳过本次循环
    # --add-port:开放端口,格式 端口/协议
    run firewall-cmd --permanent --zone=public --add-port="${p}/${proto}"
  done
}

# 调用函数:批量开放【全网可访问】的TCP/UDP端口
# 从配置文件读取 EXTERNAL_TCP_PORTS、EXTERNAL_UDP_PORTS 数组
add_ports tcp "${EXTERNAL_TCP_PORTS[@]:-}"
add_ports udp "${EXTERNAL_UDP_PORTS[@]:-}"

# 定义函数:给指定IP白名单 + 指定端口 开通访问权限(富规则)
# $1:协议(tcp/udp)
# $2...:端口列表
# 双层循环:先循环IP,再循环端口
add_rich_ip_ports(){
  local proto=$1; shift
  local -a ports=("$@")

  # 遍历白名单IP
  for ip in "${EXTERNAL_ALLOWED_IPS[@]:-}"; do
    [[ -n "$ip" ]] || continue  # IP为空则跳过
    # 遍历对应协议端口
    for p in "${ports[@]:-}"; do
      [[ -n "$p" ]] || continue  # 端口为空则跳过
      # 添加富规则:仅允许指定IP访问指定端口
      # --add-rich-rule:添加高级规则
      # family='ipv4':IPv4协议
      # source address:来源IP
      # port port:目标端口
      # protocol:协议
      # accept:允许通行
      run firewall-cmd --permanent --zone=public \
        --add-rich-rule="rule family='ipv4' source address='${ip}' port port='${p}' protocol='${proto}' accept"
    done
  done
}

# 调用函数:给白名单IP开放【限制IP访问】的TCP/UDP端口
add_rich_ip_ports tcp "${EXTERNAL_TCP_RICH_PORTS[@]:-}"
add_rich_ip_ports udp "${EXTERNAL_UDP_RICH_PORTS[@]:-}"

# —— 执行配置文件里的原生 firewalld 命令(高级扩展) —— #
log "执行配置文件中的原生 firewalld 规则..."

# 逐行读取配置文件内容
while IFS= read -r line; do
  # 去除行首、行尾空白字符
  line="$(echo "$line" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')"

  # 空行 或 # 开头的注释行 → 跳过
  [[ -z "$line" || "$line" =~ ^# ]] && continue

  # 只处理:以 firewall-cmd 开头 且 包含 --permanent 的行
  [[ "$line" == firewall-cmd* && "$line" == *"--permanent"* ]] || continue

  # 忽略包含 --reload / --list- 的命令(避免重复生效、查询)
  if echo "$line" | grep -Eq -- '--reload|--list-'; then
    continue
  fi

  # 执行配置文件中的防火墙命令
  # bash -c:以bash执行字符串命令
  # SC2086:关闭shellcheck变量拆分警告
  # shellcheck disable=SC2086
  run bash -c "$line"
done < "$CFG"

# 重新加载防火墙规则,使所有永久配置立即生效
run firewall-cmd --reload

# 将最终配置详情写入日志
{
  echo
  echo "===== public 最终配置 ====="
  firewall-cmd --zone=public --list-all  # 查看public区域所有规则
} >>"$LOG" 2>&1

# 控制台输出完成提示
echo "配置Firewalld防火墙完成,详情见 ${LOG} 或者 firewall-cmd --zone=public --list-all"

}  # 函数结束

4. HTML 报告生成模块:**generate_html_report.sh**

这个模块负责将所有收集到的信息汇总并生成HTML格式的报告。

编辑脚本:

[root@hab1 /shell/shell_check_project]# vim generate_html_report.sh
[root@hab1 /shell/shell_check_project]# cat generate_html_report.sh
#!/bin/bash

# HTML报告生成模块
generate_html_report() {
    local output_file="$1"
    echo "<html><head><meta charset='utf-8'><title>系统巡检报告</title>" > "$output_file"
    echo "<style>body{font-family:'Arial';background:#f4f4f4;color:#333;margin:20px;}</style>" >> "$output_file"
    echo "</head><body>" >> "$output_file"
    echo "<h1>系统巡检报告</h1>" >> "$output_file"
    echo "<h2>系统信息</h2><pre>$(cat /tmp/system_info.txt)</pre>" >> "$output_file"
    echo "<h2>内存使用情况</h2><pre>$(cat /tmp/memory_info.txt)</pre>" >> "$output_file"
    echo "<h2>磁盘使用情况</h2><pre>$(cat /tmp/disk_info.txt)</pre>" >> "$output_file"
    echo "<h2>网络配置</h2><pre>$(cat /tmp/network_info.txt)</pre>" >> "$output_file"
    echo "<h2>SSH公私钥检查</h2><pre>$(cat /tmp/ssh_keys_check.txt)</pre>" >> "$output_file"
    echo "<h2>Firewalld 配置</h2><pre>$(cat /tmp/firewalld_config.txt)</pre>" >> "$output_file"
    echo "</body></html>" >> "$output_file"

    # 打印巡检结果
    echo "HTML报告生成完毕!"
}

脚本说明

#!/bin/bash

# ==================== HTML报告生成模块 ====================
# 功能:读取所有巡检模块的临时文件,生成一份完整、美观的系统巡检HTML报告
# 参数:$1 传入生成的HTML报告保存路径
generate_html_report() {
    # 定义局部变量,接收第一个参数:HTML输出文件路径
    local output_file="$1"

    # 写入HTML文档开头,设置UTF-8编码,避免中文乱码
    echo "<html><head><meta charset='utf-8'><title>系统巡检报告</title>" > "$output_file"
    # 写入CSS样式,优化页面显示效果
    echo "<style>body{font-family:'Arial';background:#f4f4f4;color:#333;margin:20px;}</style>" >> "$output_file"
    # 闭合头部标签,开始页面主体内容
    echo "</head><body>" >> "$output_file"

    # 报告大标题
    echo "<h1>系统巡检报告</h1>" >> "$output_file"

    # 读取各个模块信息,用 <pre> 标签保留命令行原始格式(不乱码、不换行)
    echo "<h2>系统信息</h2><pre>$(cat /tmp/system_info.txt)</pre>" >> "$output_file"
    echo "<h2>内存使用情况</h2><pre>$(cat /tmp/memory_info.txt)</pre>" >> "$output_file"
    echo "<h2>磁盘使用情况</h2><pre>$(cat /tmp/disk_info.txt)</pre>" >> "$output_file"
    echo "<h2>网络配置</h2><pre>$(cat /tmp/network_info.txt)</pre>" >> "$output_file"
    echo "<h2>SSH公私钥检查</h2><pre>$(cat /tmp/ssh_keys_check.txt)</pre>" >> "$output_file"
    # 新增:读取防火墙配置信息并展示
    echo "<h2>Firewalld 配置</h2><pre>$(cat /tmp/firewalld_config.txt)</pre>" >> "$output_file"

    # 闭合页面标签,完成HTML结构
    echo "</body></html>" >> "$output_file"

    # 控制台提示:报告生成完成
    echo "HTML报告生成完毕!"
}

5. 脚本使用步骤

  1. 给脚本添加执行权限

首先,为每个脚本文件添加执行权限:

chmod +x system_info.sh
chmod +x memory_info.sh
chmod +x disk_info.sh
chmod +x network_info.sh
chmod +x ssh_keys_check.sh
chmod +x generate_html_report.sh
chmod +x configure_firewalld.sh
chmod +x main.sh
  1. 执行主脚本

执行主脚本 main.sh 来开始系统巡检和防火墙配置:

[root@hab1 /shell/shell_check_project]# ./main.sh
开始系统巡检...
HTML报告生成完毕!
系统巡检完成!报告路径:/tmp/system_audit_report.html
[root@hab1 /shell/shell_check_project]#

Shell 脚本模块化巡检系统并生成 HTML 报告4.png

Shell 脚本模块化巡检系统并生成 HTML 报告5.png

6. 移除 Firewalld 防火墙规则的脚本(拓展)

[root@hab1 /shell/shell_check_project]# vim remove_firewalld.sh
[root@hab1 /shell/shell_check_project]# cat remove_firewalld.sh
#!/bin/bash

# 任何错误、未定义变量、管道失败都立刻停下来
set -Eeuo pipefail

CFG="${1:-firewalld_rules.conf}"
LOG="/tmp/firewalld_remove.txt"

[[ -r "$CFG" ]] || { echo "配置文件不可读: $CFG" >&2; exit 1; }
# shellcheck source=/dev/null
source "$CFG"

INTERFACE="${EXTERNAL_INTERFACE:-${INTERFACE:-}}"
[[ -n "${INTERFACE}" ]] || { echo "请在配置中设置 EXTERNAL_INTERFACE=ens160(或 INTERFACE=ens160)" >&2; exit 1; }

log(){ echo "[$(date +'%F %T')] $*" | tee -a "$LOG"; }
run(){ log "+ $*"; "$@" >>"$LOG" 2>&1; }

run systemctl start firewalld

# 只处理 public:移除数组里添加的内容
remove_ports(){
  local proto=$1; shift
  local -a ports=("$@")
  for p in "${ports[@]:-}"; do
    [[ -n "$p" ]] || continue
    run firewall-cmd --permanent --zone=public --remove-port="${p}/${proto}" || true
  done
}
remove_ports tcp "${EXTERNAL_TCP_PORTS[@]:-}"
remove_ports udp "${EXTERNAL_UDP_PORTS[@]:-}"

remove_rich_ip_ports(){
  local proto=$1; shift
  local -a ports=("$@")
  for ip in "${EXTERNAL_ALLOWED_IPS[@]:-}"; do
    [[ -n "$ip" ]] || continue
    for p in "${ports[@]:-}"; do
      [[ -n "$p" ]] || continue
      run firewall-cmd --permanent --zone=public \
        --remove-rich-rule="rule family='ipv4' source address='${ip}' port port='${p}' protocol='${proto}' accept" || true
    done
  done
}
remove_rich_ip_ports tcp "${EXTERNAL_TCP_RICH_PORTS[@]:-}"
remove_rich_ip_ports udp "${EXTERNAL_UDP_RICH_PORTS[@]:-}"

# 尝试把配置文件里的 add-* 反向移除(三类常见)
log "尝试反向移除配置文件中的原生命令..."
while IFS= read -r line; do
  line="$(echo "$line" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')"
  [[ -z "$line" || "$line" =~ ^# ]] && continue
  [[ "$line" == firewall-cmd* && "$line" == *"--permanent"* ]] || continue

  if echo "$line" | grep -q -- "--add-port="; then
    # --add-port=XXX/yyy  -> --remove-port=XXX/yyy
    rm_line="$(echo "$line" | sed 's/--add-port=/--remove-port=/')"
    run bash -c "$rm_line" || true
  elif echo "$line" | grep -q -- "--add-service="; then
    rm_line="$(echo "$line" | sed 's/--add-service=/--remove-service=/')"
    run bash -c "$rm_line" || true
  elif echo "$line" | grep -q -- "--add-rich-rule="; then
    rm_line="$(echo "$line" | sed 's/--add-rich-rule=/--remove-rich-rule=/')"
    run bash -c "$rm_line" || true
  fi
done < "$CFG"

# 可选:把网卡从 public 解绑(按需保留/删除)
run firewall-cmd --permanent --zone=public --remove-interface="${INTERFACE}" || true

run firewall-cmd --reload
echo "移除Firewalld规则完成,详情见 ${LOG} 或者 firewall-cmd --zone=public --list-all"

运行实现移除

[root@hab1 /shell/shell_check_project]# bash remove_firewalld.sh
Warning: ALREADY_ENABLED: rule family="ipv4" source address="192.168.88.1" port port="22" protocol="tcp" accept
success
Warning: ALREADY_ENABLED: rule family="ipv4" protocol value="icmp" accept
success
[2026-04-14 09:59:34] + systemctl start firewalld
[2026-04-14 09:59:34] + firewall-cmd --permanent --zone=public --remove-port=500-600/tcp
[2026-04-14 09:59:34] + firewall-cmd --permanent --zone=public --remove-port=666/tcp
[2026-04-14 09:59:35] + firewall-cmd --permanent --zone=public --remove-port=9030/udp
[2026-04-14 09:59:35] + firewall-cmd --permanent --zone=public --remove-port=10001-11200/udp
[2026-04-14 09:59:35] + firewall-cmd --permanent --zone=public --remove-rich-rule=rule family='ipv4' source address='119.29.112.81' port port='666' protocol='tcp' accept
[2026-04-14 09:59:35] + firewall-cmd --permanent --zone=public --remove-rich-rule=rule family='ipv4' source address='119.29.112.81' port port='1024-2012' protocol='tcp' accept
[2026-04-14 09:59:36] + firewall-cmd --permanent --zone=public --remove-rich-rule=rule family='ipv4' source address='119.29.112.81' port port='22' protocol='tcp' accept
[2026-04-14 09:59:36] + firewall-cmd --permanent --zone=public --remove-rich-rule=rule family='ipv4' source address='119.29.112.81' port port='36000' protocol='tcp' accept
[2026-04-14 09:59:36] + firewall-cmd --permanent --zone=public --remove-rich-rule=rule family='ipv4' source address='119.29.112.82' port port='666' protocol='tcp' accept
[2026-04-14 09:59:37] + firewall-cmd --permanent --zone=public --remove-rich-rule=rule family='ipv4' source address='119.29.112.82' port port='1024-2012' protocol='tcp' accept
[2026-04-14 09:59:37] + firewall-cmd --permanent --zone=public --remove-rich-rule=rule family='ipv4' source address='119.29.112.82' port port='22' protocol='tcp' accept
[2026-04-14 09:59:37] + firewall-cmd --permanent --zone=public --remove-rich-rule=rule family='ipv4' source address='119.29.112.82' port port='36000' protocol='tcp' accept
[2026-04-14 09:59:37] + firewall-cmd --permanent --zone=public --remove-rich-rule=rule family='ipv4' source address='119.29.112.81' port port='2012-65535' protocol='udp' accept
[2026-04-14 09:59:38] + firewall-cmd --permanent --zone=public --remove-rich-rule=rule family='ipv4' source address='119.29.112.81' port port='666' protocol='udp' accept
[2026-04-14 09:59:38] + firewall-cmd --permanent --zone=public --remove-rich-rule=rule family='ipv4' source address='119.29.112.82' port port='2012-65535' protocol='udp' accept
[2026-04-14 09:59:38] + firewall-cmd --permanent --zone=public --remove-rich-rule=rule family='ipv4' source address='119.29.112.82' port port='666' protocol='udp' accept
[2026-04-14 09:59:39] 尝试反向移除配置文件中的原生命令...
[2026-04-14 09:59:39] + bash -c firewall-cmd --permanent --zone=public --remove-rich-rule='rule family="ipv4" source address="192.168.88.1" port port="22" protocol="tcp" accept'
[2026-04-14 09:59:39] + bash -c firewall-cmd --permanent --zone=public --remove-rich-rule='rule family="ipv4" protocol value="icmp" accept'
[2026-04-14 09:59:39] + firewall-cmd --permanent --zone=public --remove-interface=ens160
[2026-04-14 09:59:40] + firewall-cmd --reload
移除Firewalld规则完成,详情见 /tmp/firewalld_remove.txt 或者 firewall-cmd --zone=public --list-all

[root@hab1 /shell/shell_check_project]# firewall-cmd --zone=public --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens160
  sources:
  services: cockpit dhcpv6-client http https ssh
  ports:
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

总结

通过本次学习,实现了一个模块化设计的 系统巡检脚本,并集成了 Firewalld 防火墙配置 功能,能够自动配置防火墙规则并生成详细的 HTML 报告。该设计使得脚本功能清晰、易于维护,同时也便于后续扩展:

  1. 模块化设计:每个功能拆分为独立模块,增强了代码的可维护性和可扩展性。
  2. 灵活的功能扩展:可以轻松添加新的功能模块,如增加安全性检查、日志分析等。
  3. HTML报告生成:将收集到的信息输出为HTML格式,方便共享和查看。
  4. 防火墙配置:通过脚本实现了内外网防火墙策略的批量配置。

这种方法不仅提高了 系统巡检 的自动化程度,也为 安全审计 和 运维管理 提供了强大的支持。