You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 12:24:03