一键掌控三线资源:极简 Shell 脚本实现 CPU·磁盘·内存可视化巡检
目录
前言
数值型 for 循环
语法格式
示例:打印 1 到 5
示例:打印5次Hello World
示例:计算 1 到 100 的累加和
遍历型 for 循环
语法格式
示例:遍历字符串列表
示例:遍历数组
示例:遍历文件列表
示例:这边会给一个IP地址的文件(ipddr.txt)需要 ping 文件中的IP(主机)判断是否能通
示例:统计 /var/log 有多少个文件,并且显示这些文件名
示例:需要ping 通 某个网段 机器 并且 输出 通和不通 反馈结果
示例:九九乘法表
while循环
条件判断型
典型示例
示例:实时监控httpd的运行状态
基本语法
case循环
快速示例
实用技巧
示例:设置系统开机、关机和重启
示例:用 case 编写一个查看 cpu 内存 硬盘 资源使用情况
总结
前言
在信息化高速发展的今天,服务器与终端设备的稳定运行已成为企业业务连续性的命脉。面对日益复杂的系统环境,运维人员需要随时掌握 CPU、磁盘、内存三大核心资源的实时状态,以便在性能瓶颈或故障萌芽阶段即可精准干预。然而,传统命令行工具虽然功能强大,却存在记忆负担高、操作路径长、输出可读性差等问题,极易在紧急排障时贻误战机。为此,我们设计了一款轻量级 Shell 交互脚本,将 top、df、free 等底层指令封装成一键式菜单,既保留原生命令的详尽数据,又通过友好提示与编号选择显著降低使用门槛。脚本遵循 POSIX 标准,兼容绝大多数 Linux 发行版,可直接运行于生产服务器、容器或虚拟机,真正做到了“开箱即用”。接下来,让我们一起体验它在日常巡检中所带来的效率跃升。
数值型 for 循环
语法格式
bash
复制
for ((初始值; 限制条件; 步长))
do循环体代码
done
-
初始值:循环变量的初始值。
-
限制条件:循环继续执行的条件。
-
步长:每次循环后循环变量的增量或减量。
示例:打印 1 到 5
bash
复制
#!/bin/bashfor ((i=1; i<=5; i++))
doecho "当前数字: $i"
done
输出结果:
复制
当前数字: 1
当前数字: 2
当前数字: 3
当前数字: 4
当前数字: 5
示例:打印5次Hello World
# shell脚本
for ((i=0;i<5;i++))
doecho "$i - Hello World"
done# 测试
[root@localhost shelldemo]# sh dome8.sh
0 - Hello World
1 - Hello World
2 - Hello World
3 - Hello World
4 - Hello World
示例:计算 1 到 100 的累加和
bash
复制
#!/bin/bashcount=0
for((i=0;i<=100;i++))
docount=$(($count + $i));
doneecho "累加的结果是:${count}";# 测试
[root@localhost shelldemo]# sh dome9.sh
累加的结果是:5050
输出结果:
1 到 10 的累加和为: 55
遍历型 for 循环
语法格式
bash
复制
for 变量名 in 数据1 数据2 数据3 ...
do循环体代码
done
-
变量名:依次取数据集合中的每个值。
-
数据集合:可以是显式列出的数据,也可以是数组、命令输出等。
示例:遍历字符串列表
bash
复制
#!/bin/bashfor animal in cat dog elephant
doecho "动物名称: $animal"
done
输出结果:
复制
动物名称: cat
动物名称: dog
动物名称: elephant
示例:遍历数组
bash
复制
#!/bin/bashmy_array=(A B C D)for element in ${my_array[@]}
doecho "数组元素: $element"
done
输出结果:
复制
数组元素: A
数组元素: B
数组元素: C
数组元素: D
示例:遍历文件列表
bash
复制
#!/bin/bashfor file in $(ls /root/shelldemo)
doecho "文件名: $file"
done
输出结果:
复制
文件名: file1.sh
文件名: file2.sh
文件名: file3.sh
示例:这边会给一个IP地址的文件(ipddr.txt)需要 ping 文件中的IP(主机)判断是否能通
# shell脚本
HT_IP=$(< ./ip.txt)
#for循环
for ip in $HT_IP
#ping
doping -c 3 -i 0.5 -W 2 $ip &>/dev/nullif [ $? -eq 0 ]; thenecho "$ip is up"elseecho "$ip is down"fi
#输出结果
done# 测试
[root@localhost shelldemo]# sh dome10.sh
192.168.10.101 is up
192.168.10.102 is down
192.168.10.103 is down
192.168.10.104 is down
192.168.10.105 is down
192.168.10.106 is up
192.168.10.1 is up
示例:统计 /var/log 有多少个文件,并且显示这些文件名
# shell脚本
# 将所有的文件列表用一个变量手记起来
file_list=$(ls -r /var/log/*);
count= 0
# for遍历,判断是否存在文件
for file in $file_list
# 如果存在的话,+1,并打印
doif [ -f $file ]; thenecho "$file是一个文件"let count++ fi
doneecho "/var/log文件夹下面一共有$count个文件"# 测试
[root@localhost shelldemo]# sh dome10.sh
192.168.10.101 is up
192.168.10.102 is down
192.168.10.103 is down
192.168.10.104 is down
192.168.10.105 is down
192.168.10.106 is up
192.168.10.1 is up
[root@localhost shelldemo]# vim dome10.sh
[root@localhost shelldemo]# vim dome11.sh
[root@localhost shelldemo]# chmod +x dome11.sh
[root@localhost shelldemo]# sh dome11.sh
dome11.sh:行3: 0: 未找到命令
/var/log/yum.log是一个文件
/var/log/Xorg.9.log是一个文件
/var/log/Xorg.0.log.old是一个文件
/var/log/Xorg.0.log是一个文件
/var/log/wtmp是一个文件
/var/log/wpa_supplicant.log是一个文件
/var/log/vmware-vmtoolsd-root.log是一个文件
/var/log/vmware-vmsvc-root.log是一个文件
/var/log/vmware-vgauthsvc.log.0是一个文件
/var/log/vmware-network.log是一个文件
/var/log/vmware-network.9.log是一个文件
/var/log/vmware-network.8.log是一个文件
/var/log/vmware-network.7.log是一个文件
/var/log/vmware-network.6.log是一个文件
/var/log/vmware-network.5.log是一个文件
/var/log/vmware-network.4.log是一个文件
/var/log/vmware-network.3.log是一个文件
/var/log/vmware-network.2.log是一个文件
/var/log/vmware-network.1.log是一个文件
/var/log/tallylog是一个文件
/var/log/spooler-20250827是一个文件
/var/log/spooler-20250817是一个文件
/var/log/spooler-20250810是一个文件
/var/log/spooler是一个文件
/var/log/secure-20250827是一个文件
/var/log/secure-20250817是一个文件
/var/log/secure-20250810是一个文件
/var/log/secure是一个文件
/var/log/mysqld.log是一个文件
/var/log/messages-20250827是一个文件
/var/log/messages-20250817是一个文件
/var/log/messages-20250810是一个文件
/var/log/messages是一个文件
/var/log/maillog-20250827是一个文件
/var/log/maillog-20250817是一个文件
/var/log/maillog-20250810是一个文件
/var/log/maillog是一个文件
/var/log/lastlog是一个文件
/var/log/grubby_prune_debug是一个文件
/var/log/firewalld是一个文件
/var/log/dmesg.old是一个文件
/var/log/dmesg是一个文件
/var/log/cron-20250827是一个文件
/var/log/cron-20250817是一个文件
/var/log/cron-20250810是一个文件
/var/log/cron是一个文件
/var/log/btmp是一个文件
/var/log/boot.log-20250830是一个文件
/var/log/boot.log-20250829是一个文件
/var/log/boot.log-20250827是一个文件
/var/log/boot.log-20250817是一个文件
/var/log/boot.log-20250816是一个文件
/var/log/boot.log-20250815是一个文件
/var/log/boot.log-20250814是一个文件
/var/log/boot.log是一个文件
/var/log文件夹下面一共有55个文件
示例:需要ping 通 某个网段 机器 并且 输出 通和不通 反馈结果
# shell脚本
# 交互式写一个网段
read -p "检查网段:" ip
# ping一下
ping -c 3 -i 0.5 -W 1 $ip >/dev/null 2>&1
# 用if判断
if [ $? -eq 0 ]; thenecho "$ip可以ping通">>ping.txt
elseecho "$ip不可以ping通">>ping.txt
fi# 测试
# 192.168.66.12不可能连接通
[root@localhost shelldemo]# sh dome12.sh
检查网段:192.168.66.12
[root@localhost shelldemo]# cat ping.txt
192.168.10.106可以ping通
192.168.66.12不可以ping通
示例:九九乘法表
# 遍历i从1到9
for i in $(seq 9);
do
# 遍历j从1到ifor j in $(seq $i);doecho -n "$i*$j=$((i*j)) "doneecho -e "\n"
done# 测试
[root@localhost shelldemo]# sh dome13.sh
1*1=1 2*1=2 2*2=4 3*1=3 3*2=6 3*3=9 4*1=4 4*2=8 4*3=12 4*4=16 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
示例:随机生成一个15位的密码
# shell脚本
# 随机生成一个10位数的密码
key="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
# 列出key的字符串数目
num=${#key}
# 遍历
for i in $(seq 15); doindex=$[RANDOM%$num]password=$password${key:$index:1}
doneecho "密码是$password"# 测试
[root@localhost shelldemo]# sh dome14.sh
密码是aMcDjfRetHA2Wi1
[root@localhost shelldemo]# sh dome14.sh
密码是sZdzcxaLMzUAnis
[root@localhost shelldemo]# sh dome14.sh
密码是4zQTx9YS4kWkBSm
while循环
条件判断型
适合「达到某个条件就停止」的场景。
bash
while [ 条件表达式 ]
do命令# 必须修改循环条件,否则死循环
done
示例:等待用户输入 yes/YES
# shell脚本
while [ "$y" != "yes" -a "$y" != "YES" ]do echo "请输入yes/YES停止循环"read y
doneecho "循环已经停止"# 测试[root@localhost shelldemo]# sh dome15.sh
请输入yes/YES停止循环
qwerty
请输入yes/YES停止循环
fd
请输入yes/YES停止循环
fghjk
请输入yes/YES停止循环
hgfd
请输入yes/YES停止循环
gfx
请输入yes/YES停止循环
456789
请输入yes/YES停止循环
resw
请输入yes/YES停止循环
9ok,
请输入yes/YES停止循环
fds
请输入yes/YES停止循环
yes
循环已经停止
-
数值运算型
用 Bash 的算术表达式(( ))
或let
,实现类 C 的循环。
bash
# shell脚本
i=1
while(($i<3))
doecho $ilet i++ # 或者((i++))
done# 测试
[root@localhost shelldemo]# sh dome16.sh
1
2
-
无限循环(死循环)
需要内部用break
或exit
退出。
bash
while true
doread -p "请输入字符串:" str[ "$str" == "quit" ] && exit 0
done
示例:死循环
# shell脚本
while true
doecho "请输入字符串:"read yif [ "$y" == "yes" ]; thenexit 0 # 退出fi
done# 测试
[root@localhost shelldemo]# chmod dome17.sh
chmod: "dome17.sh" 后缺少操作数
Try 'chmod --help' for more information.
[root@localhost shelldemo]# chmod +x dome17.sh
[root@localhost shelldemo]# sh dome17.sh
请输入字符串:
sdfg
请输入字符串:
xcv
请输入字符串:
oiug
请输入字符串:
cv
请输入字符串:
456
请输入字符串:
poih
请输入字符串:
xf
请输入字符串:
yea^Hs^H^[[3~^H
请输入字符串:
yes # 已退出
典型示例
-
计算 1…10 累加和
bash
count=0
num=1
while (( num <= 10 ))
docount=$(( count + num ))((num++))
done
echo "1-10 累加和:$count"
-
猜数字游戏(节选 while 片段)
num=$[RANDOM%100+1]
while true
doread -p "猜 1-100 的数:" caiif [ $cai -eq $num ]; thenecho "恭喜,猜对了!"exit 0elif [ $cai -gt $num ]; thenecho "猜大了"elseecho "猜小了"fi
done
示例:实时监控httpd的运行状态
# shell脚本
while ps -aux|grep httpd|grep -v grep &>/dev/null
doecho "httpd正在运行"sleep 2
doneecho "httpd不在运行"# 测试
# 此时httpd开启
[root@localhost shelldemo]# sh dome20.sh
httpd正在运行
httpd正在运行
httpd正在运行
httpd正在运行
httpd正在运行
httpd正在运行
httpd正在运行
httpd正在运行
...
# 此时关闭httpd
[root@localhost shelldemo]# sh dome20.sh
httpd不在运行
基本语法
case $变量 in模式1)命令1;;模式2)命令2;;*) # 通配符,相当于 default默认命令;;
esac # 反写 case,表示结束
-
每个分支必须以右括号
)
结束。 -
每个分支命令块以
;;
结束。 -
支持通配符:
*
匹配任意字符,?
匹配单个字符,|
表示“或”。
case循环
快速示例
bash
#!/bin/bash
case $1 in"hello")echo "Hello World!";;"test")echo "testing...";;"")echo "$0 没有参数";;*) # 其余任何输入echo "默认分支";;
esac
运行示例
$ ./demo.sh hello → Hello World!
$ ./demo.sh test → testing...
$ ./demo.sh → ./demo.sh 没有参数
$ ./demo.sh abc → 默认分支
实用技巧
-
多模式匹配
bashcase $opt iny|Y|yes|YES) echo "确认" ;;n|N|no|NO) echo "取消" ;; esac
-
模式里可包含通配符
bashcase $filename in*.tar.gz) tar -zxf "$filename" ;;*.zip) unzip "$filename" ;; esac
-
与
bashread
搭配做简单菜单read -p "选择操作[start|stop|restart]: " action case $action instart) systemctl start nginx ;;stop) systemctl stop nginx ;;restart)systemctl restart nginx ;;*) echo "未知操作" ;; esac
示例:设置系统开机、关机和重启
# shell脚本
case $1 in
"start")
systemctl start httpd.service
echo "服务已开启"
;;"stop")
systemctl stop httpd.service
echo "服务已关闭"
;;"restart")
systemctl stop httpd.service
systemctl start httpd.service
echo "服务已重启"
;;*)
echo "服务不存在,请输入正确的服务 start stop restart"
;;
esac
测试结果:
[root@localhost shelldemo]# sh dome18.sh start
服务已开启
[root@localhost shelldemo]# systemctl status httpd
● httpd.service - The Apache HTTP ServerLoaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)Active: active (running) since 六 2025-08-30 16:50:18 CST; 12s agoDocs: man:httpd(8)man:apachectl(8)Main PID: 10702 (httpd)Status: "Total requests: 0; Current requests/sec: 0; Current traffic: 0 B/sec"Tasks: 6CGroup: /system.slice/httpd.service├─10702 /usr/sbin/httpd -DFOREGROUND├─10706 /usr/sbin/httpd -DFOREGROUND├─10707 /usr/sbin/httpd -DFOREGROUND├─10708 /usr/sbin/httpd -DFOREGROUND├─10709 /usr/sbin/httpd -DFOREGROUND└─10710 /usr/sbin/httpd -DFOREGROUND8月 30 16:50:18 localhost.localdomain systemd[1]: Starting The Apache HTTP Server...
8月 30 16:50:18 localhost.localdomain httpd[10702]: AH00558: httpd: Could not reliably determine the server's fully qualifie...ssage
8月 30 16:50:18 localhost.localdomain systemd[1]: Started The Apache HTTP Server.
Hint: Some lines were ellipsized, use -l to show in full.
[root@localhost shelldemo]# sh dome18.sh stop
服务已关闭
[root@localhost shelldemo]# systemctl status httpd.service
● httpd.service - The Apache HTTP ServerLoaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)Active: inactive (dead)Docs: man:httpd(8)man:apachectl(8)8月 30 16:50:18 localhost.localdomain systemd[1]: Starting The Apache HTTP Server...
8月 30 16:50:18 localhost.localdomain httpd[10702]: AH00558: httpd: Could not reliably determine the server's fully qualifie...ssage
8月 30 16:50:18 localhost.localdomain systemd[1]: Started The Apache HTTP Server.
8月 30 16:50:38 localhost.localdomain systemd[1]: Stopping The Apache HTTP Server...
8月 30 16:50:39 localhost.localdomain systemd[1]: Stopped The Apache HTTP Server.
Hint: Some lines were ellipsized, use -l to show in full.
[root@localhost shelldemo]# sh dome18.sh asdfghj
服务不存在,请输入正确的服务 start stop restart
示例:用 case 编写一个查看 cpu 内存 硬盘 资源使用情况
# shell脚本
# 提示查看用户信息
echo "请查看用户信息"
echo "1.CPU的使用情况"
echo "2.磁盘的使用情况"
echo "3.内存的使用情况"
echo "4.退出"
# 用户交互
read -p "请输入选项1、2、3、4:" de
# case语句
case $de in
"1")
top -bn1|grep Cpu
;;"2")
df -h
;;"3")
free -m
;;"4")
exit 0
;;*)
echo "请输入正确的设备1、2、3、4"
;;esac# 运行
[root@localhost shelldemo]# sh dome22.sh
请查看用户信息
1.CPU的使用情况
2.磁盘的使用情况
3.内存的使用情况
4.退出
请输入选项1、2、3、4:1
%Cpu(s): 1.9 us, 20.8 sy, 0.0 ni, 77.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
[root@localhost shelldemo]# sh dome22.sh
请查看用户信息
1.CPU的使用情况
2.磁盘的使用情况
3.内存的使用情况
4.退出
请输入选项1、2、3、4:3total used free shared buff/cache available
Mem: 3770 1273 819 49 1677 2207
Swap: 3967 0 3967
[root@localhost shelldemo]# sh dome22.sh
请查看用户信息
1.CPU的使用情况
2.磁盘的使用情况
3.内存的使用情况
4.退出
请输入选项1、2、3、4:4
总结
通过上述脚本实践,我们深刻体会到“简单即是力量”的运维哲学:只需三十余行代码,便能把晦涩的系统指标转化为清晰易读的管理视图。用户仅需输入 1、2、3、4 即可在 CPU 负载、磁盘容量、内存占用与程序退出之间自由切换,无需再背冗长参数,也不必担心误操作带来的风险。脚本在真实环境中已验证可行,输出格式与系统原生工具保持一致,方便直接粘贴到监控平台或故障工单。未来可进一步扩展:加入循环菜单实现连续查询、用颜色高亮关键阈值、将结果重定向到日志文件,甚至结合 cron 定时执行,实现无人值守巡检。希望这段示例能为正在构建自动化运维体系的同行提供灵感,也期待社区共同迭代,让 Shell 脚本在 DevOps 时代继续焕发活力。