#!/bin/bash
# 定义巡检日志文件路径,所有日志将记录在此文件中
LOG_FILE="/var/log/system_inspection.log"
# 定义一个函数,将消息输出到日志文件并同时显示在屏幕上
log() {
# 使用 `date` 获取当前时间,并将消息格式化后追加到日志文件,同时输出到屏幕
echo "$(date +"%Y-%m-%d %H:%M:%S") : $*" | tee -a "$LOG_FILE"
}
# 系统类型检查函数,用于判断系统的包管理工具
os_check() {
# 检查是否是基于 Red Hat 的系统(CentOS/RedHat)
if [ -e /etc/redhat-release ]; then
# 提取 Red Hat 系统的发行版本名称
REDHAT=$(awk '{print $1}' /etc/redhat-release)
else
# 如果不是 Red Hat 系统,则检查是否是 Debian 系列系统(如 Ubuntu)
DEBIAN=$(awk '{print $1}' /etc/issue)
fi
# 根据不同的系统,确定使用 yum 还是 apt-get 作为包管理器
if [[ "$REDHAT" == "CentOS" || "$REDHAT" == "Red" ]]; then
P_M="yum" # CentOS/Red Hat 使用 yum
elif [[ "$DEBIAN" == "Ubuntu" || "$DEBIAN" == "ubuntu" ]]; then
P_M="apt-get" # Ubuntu 使用 apt-get
else
# 如果不是支持的系统,记录日志并退出脚本
log "Operating system does not support."
exit 1
fi
}
# 检查当前是否是以 root 用户身份执行脚本
if [ "$LOGNAME" != "root" ]; then
# 如果不是 root 用户,则提示用户并退出
log "Please use the root account operation."
exit 1
fi
# 定义一个函数,用于检查并安装所需的系统工具
install_tool() {
local tool_name="$1"
local package_name="$2"
# 使用 `which` 检查工具是否已安装
if ! which "$tool_name" &>/dev/null; then
# 如果工具未安装,记录日志并安装
log "$tool_name not found, installing..."
os_check # 先调用系统检查函数,确保已确定包管理工具
$P_M install "$package_name" -y | tee -a "$LOG_FILE" # 安装工具并将过程记录到日志
fi
}
# 检查并安装 vmstat 和 iostat 工具
install_tool "vmstat" "procps"
install_tool "iostat" "sysstat"
# 定义 CPU 负载监控功能
cpu_load() {
log "Checking CPU load..."
# 连续执行3次CPU监控,每秒获取一次数据
for i in {1..3}; do
log "Sample $i:" # 每次循环时记录样本编号
# 使用 vmstat 提取 CPU 利用率、用户使用、系统使用和I/O等待时间,并写入日志
vmstat | awk 'NR==3 { print "Util:", 100-$15"%", "User:", $13"%", "System:", $14"%", "I/O wait:", $16"%" }' | tee -a "$LOG_FILE"
sleep 1 # 每次间隔1秒
done
}
# 定义硬盘 I/O 负载监控功能
disk_load() {
log "Checking Disk I/O load..."
# 连续执行3次硬盘I/O监控,每秒获取一次数据
for i in {1..3}; do
log "Sample $i:" # 每次循环时记录样本编号
# 使用 iostat 提取每个硬盘的利用率、读写速度,并写入日志
iostat -x -k | awk '/^[v|s]/{OFS=": "; print $1, "Util:", $NF"%", "Read/s:", $6"KB", "Write/s:", $7"KB"}' | tee -a "$LOG_FILE"
sleep 1 # 每次间隔1秒
done
}
# 定义硬盘使用率检查功能
disk_use() {
log "Checking Disk usage..."
# 使用 df -h 检查所有分区的使用率,如果使用率超过 90%,记录到日志
df -h | awk '/^\/dev/ && int(substr($5, 1, length($5)-1)) > 90 { print $6 " = " $5 }' | tee -a "$LOG_FILE"
}
# int(substr($5, 1, length($5)-1))
# $5+0
# 这两种写法都可以实现的都是将字符串转整数 然后进行计算比较
# 学习阶段都练习一下
# 定义硬盘 inode 使用率检查功能
disk_inode() {
log "Checking Disk inode usage..."
# 使用 df -i 检查所有分区的 inode 使用率,如果 inode 使用率超过 90%,记录到日志
df -i | awk '/^\/dev/ && $5+0 > 90 { print $6 " = " $5 }' | tee -a "$LOG_FILE"
}
# 定义内存使用率检查功能
mem_use() {
log "Checking Memory usage..."
# 使用 free -m 获取内存总量、已使用量、空闲量,并记录到日志
free -m | awk '/^Mem:/ { print "Total:", $2"MB", "Used:", $3"MB", "Free:", $4"MB" }' | tee -a "$LOG_FILE"
}
# 定义 TCP 连接状态检查功能
tcp_status() {
log "Checking TCP connection status..."
# 使用 ss -ant 检查TCP连接状态,并统计各状态的数量,记录到日志
ss -ant | awk '!/State/ { status[$1]++ } END { for (i in status) print i, status[i] }' | tee -a "$LOG_FILE"
}
# 定义 CPU 占用前10个进程检查功能
cpu_top10() {
log "Checking top 10 CPU consuming processes..."
# 使用 ps 命令获取占用 CPU 前10个进程,并记录到日志
ps aux --sort=-%cpu | awk 'NR<=11 { print $2, $3"%", $11 }' | tee -a "$LOG_FILE"
}
# 定义内存占用前10个进程检查功能
mem_top10() {
log "Checking top 10 Memory consuming processes..."
# 使用 ps 命令获取占用内存前10个进程,并记录到日志
ps aux --sort=-%mem | awk 'NR<=11 { print $2, $4"%", $11 }' | tee -a "$LOG_FILE"
}
# 定义网络流量检查功能
traffic() {
# 提示用户输入网卡名称
read -p "Enter network card name (e.g., eth0): " eth
# 检查输入的网卡名称是否有效
if ifconfig "$eth" &>/dev/null; then
log "Checking Network traffic on $eth..."
# 连续执行3次网络流量检查,每秒获取一次数据
for i in {1..3}; do
# 获取当前的网络流量信息
traffic_info=$(ifconfig "$eth")
# 从网络流量信息中提取 RX 和 TX 字节数
OLD_IN=$(echo "$traffic_info" | awk '/RX bytes/ {print $5}' | cut -d: -f2)
OLD_OUT=$(echo "$traffic_info" | awk '/TX bytes/ {print $5}' | cut -d: -f2)
# 等待1秒
sleep 1
# 获取新的网络流量信息
traffic_info=$(ifconfig "$eth")
# 从新的网络流量信息中提取 RX 和 TX 字节数
NEW_IN=$(echo "$traffic_info" | awk '/RX bytes/ {print $5}' | cut -d: -f2)
NEW_OUT=$(echo "$traffic_info" | awk '/TX bytes/ {print $5}' | cut -d: -f2)
# 计算进出流量差值,并记录到日志
RX_DIFF=$((NEW_IN - OLD_IN))
TX_DIFF=$((NEW_OUT - OLD_OUT))
log "In: $RX_DIFF Bytes, Out: $TX_DIFF Bytes"
done
else
# 如果网卡名称无效,记录日志
log "Invalid network card name."
fi
}
# 主功能菜单,使用 select 提供交互选项
while true; do
select input in cpu_load disk_load disk_use disk_inode mem_use tcp_status cpu_top10 mem_top10 traffic quit all_check; do
case $input in
cpu_load) cpu_load ;;
disk_load) disk_load ;;
disk_use) disk_use ;;
disk_inode) disk_inode ;;
mem_use) mem_use ;;
tcp_status) tcp_status ;;
cpu_top10) cpu_top10 ;;
mem_top10) mem_top10 ;;
traffic) traffic ;;
quit)
log "Exiting."
exit 0
;;
# 执行所有检查功能
all_check)
log "Starting Full System Check..."
cpu_load
disk_load
disk_use
disk_inode
mem_use
tcp_status
cpu_top10
mem_top10
traffic
log "Full System Check Completed."
break
;;
# 处理无效选项
*)
log "Invalid option."
;;
esac
done
done
shell_AWK 获取系统状态信息
于 2024-09-07 10:32:27 首次发布