【问题标题】:scope of variable in pipe管道中变量的范围
【发布时间】:2009-11-24 12:22:55
【问题描述】:

如果使用率超过 10%,以下 shell 脚本将检查磁盘空间并将变量 diskfull 更改为 1 最后一个回显总是显示0 我在 if 子句中尝试了global diskfull=1,但它不起作用。 如果磁盘消耗超过 10%,如何将变量更改为 1

#!/bin/sh
diskfull=0

ALERT=10
df -HP | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{ print $5 " " $1 }' | while read output;
do
  #echo $output
  usep=$(echo $output | awk '{ print $1}' | cut -d'%' -f1  )
  partition=$(echo $output | awk '{ print $2 }' )
  if [ $usep -ge $ALERT ]; then
     diskfull=1
     exit
  fi
done

echo $diskfull

【问题讨论】:

  • 您确定正在执行 if 语句的主体吗?很有可能 if 被评估为 false 并且 diskfull=1 行永远不会执行。
  • 感谢所有回复。我所做的是我以退出状态 1 退出了 if 子句,然后在“完成”后立即将其保存到 diskfull 变量。这种解决方法似乎奏效了。

标签: shell pipe


【解决方案1】:

这是在管道中使用while 的副作用。有两种解决方法:

1) 将while 循环和它使用的所有变量放在一个单独的范围内,如 levislevis86 所示

some | complicated | pipeline | {
    while read line; do
        foo=$( some calculation )
    done
    do_something_with $foo
}
# $foo not available here

2) 如果您的 shell 允许,请使用 进程替换,您可以将管道的输出重定向到 while 循环的输入

while read line; do
    foo=$( some calculation )}
done < <(some | complicated | pipeline)
do_something_with $foo

【讨论】:

【解决方案2】:

当使用管道时,外壳接缝使用子外壳来完成工作。由于这些子 shell 不知道 $diskfull,因此值永远不会改变。

见: http://www.nucleardonkey.net/blog/2007/08/variable_scope_in_bash.html

我修改了你的脚本如下。它适用于我,也应该适用于您的系统。

#!/bin/sh
diskfull=0

ALERT=10
stats=`df -HP | grep -vE '^Filesystem|tmpfs|cdrom|none|udev' | awk '{ print $5 "_" $1 }'`
for output in $stats
do
  usep=$(echo $output | awk '{ print $1}' | cut -d'%' -f1  )
  partition=$(echo $output | sed s/.*_// )
  #echo $partition -  $usep
  if [ $usep -le $ALERT ]; then
     diskfull=1
     break
  fi
done
echo $diskfull

【讨论】:

    【解决方案3】:

    @OP,使用大括号或 ()

    count=0
    max=10
    diskfull=0
    df -HP | { while read disk b c d used e
    do    
        if [ "$count" -gt 1 ];then
            used=${used%?}
            if [ "$used" -gt "$max" ];then
                echo "overload: $disk, used: $used%"
                diskfull=1
            fi
        fi
        count=$(( count+1 ))
    done 
    echo "diskfull: $diskfull" 
    }
    

    【讨论】:

      【解决方案4】:

      我认为您一定不会到达 diskfull=1 行,因为如果您到达了,您将不会得到任何输出——下面的 exit 行将退出脚本。

      我不知道为什么这不起作用,但请注意 awk 可以处理其余的工作:

      diskfull=$(df -HP | grep -vE '^Filesystem|tmpfs|cdrom' | awk 'BEGIN { x = 0 } { if ($5 + 0 >= '$ALERT') { x = 1 } } END { print x }')
      

      这样你就不需要while循环了。

      【讨论】:

        【解决方案5】:

        你可以用 gawk 做到这一点(不需要使用 grep)。对于警报,您可以向 root 发送电子邮件。

        threshold=10
        df -HP | awk -v t="$threshold" -v msg="" 'NR>1 && $5+0 > t{ 
            msg=msg $1" is "$5"\n"
        }END{print msg}' | mail root 
        

        或者先检查是否有“味精”

        threshold=10
        result=$(df -HP | awk -v t="$threshold" -v msg="" 'NR>1 && $5+0 > t{ 
            msg=msg $1" is "$5"\n"
        }END{print msg}')
        if [ -n "$result" ];then
          echo "Overload"
          echo "$result" | mail root
        
        fi
        

        【讨论】:

          【解决方案6】:

          在这一行:

          usep=$(echo $output | awk '{ print $1}' | cut -d'%' -f1  )
          

          不必使用cut。你可以这样做:

          usep=$(echo $output | awk -F% '{ print $1}' )
          

          【讨论】:

          • 使用 gawk,可以使用 $5+0 将字段更改为整数。 % 是“自动消失”。 (因为没有更好的词)
          【解决方案7】:

          为了处理 bash 循环中的变量作用域问题,可以将变量保存在一个临时文件中,然后cat 将其保存到变量中。这不是最聪明和最有效的解决方案,但它很容易阅读和思考。

          如果有人想尝试与 Glenn 的 solution 不同的东西,可以试试这个:

          some | complicated | pipeline | {
          while read line; do
              foo=$( some calculation )
          done
          do_something_with $foo
          
          echo $foo > foo.tmp
          }
          
          # $foo not available here
          foo=$(cat foo.tmp)
          # $foo available here. do anything with it
          rm foo.tmp
          

          请注意,仅当您有创建文件的权限(或指定您有权限的目录的绝对路径)时才有效

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-06-10
            • 2018-02-09
            • 1970-01-01
            • 1970-01-01
            • 2022-07-01
            • 1970-01-01
            • 1970-01-01
            • 2020-08-10
            相关资源
            最近更新 更多