Shell脚本检测磁盘空间输出不符合预期,求问题原因及最佳实践
Shell磁盘使用率检测脚本故障排查与优化
问题根因
你遇到的输出恒为|disk:0的核心原因是管道开启子shell机制:
Shell中管道连接的每一段命令都会运行在独立的子进程中,你在while read循环内修改的disk_result是子shell的局部变量,循环结束后子shell退出,父shell中的disk_result仍为初始值0,因此输出永远不符合预期。
原写法是否属于最佳实践
不属于,存在3个明显的可优化点:
- 子shell变量隔离问题:就是上述的管道子Shell导致变量修改不生效的问题
- 命令冗余:已经用
awk提取了df的输出字段,后续反复调用awk、cut拆分变量属于多余操作,增加不必要的进程开销 - 鲁棒性不足:变量未做引号包裹,遇到带空格的挂载点名称时会出现解析错误
正确实现方案
方案1:最小改动修复原逻辑(用进程替换避免子Shell)
#!/bin/bash result="" ALERT=40 OUT_FLAG() { local check_value=$1 local result_value=$2 if [ ${check_value} -eq 0 ];then result="$result|${result_value}:0" else result="$result|${result_value}:1" fi } Check_disk() { local disk_result=0 # 用进程替换代替管道,while循环运行在当前Shell中,变量修改可生效 while read -r usep mountpoint; do if [ "$usep" -ge "$ALERT" ]; then disk_result=1 fi done < <(df -Pl | grep -vE "^Filesystem|tmpfs|cdrom" | awk '{print int($5) " " $6}') OUT_FLAG ${disk_result} "disk" } Check_disk echo "$result"
方案2:更简洁的最佳实践写法(用awk完成全部判断逻辑,减少Shell层开销)
直接让awk遍历所有分区使用率,只要有一个超过阈值就返回1,否则返回0,逻辑更简洁性能更好:
#!/bin/bash ALERT=40 # awk判断所有分区使用率,存在超过阈值的行则输出1,否则输出0 disk_status=$(df -Pl | awk -v alert="$ALERT" ' BEGIN{status=0} !/^Filesystem|tmpfs|cdrom/{ use = int($5) if(use >= alert) status=1 } END{print status} ') result="|disk:${disk_status}" echo "$result"
内容的提问来源于stack exchange,提问作者Echo_s
相关产品推荐
相关产品推荐

