在shell脚本中添加计数器

时间:2012-11-30 03:41:08

标签: bash shell

我的shell脚本中有以下代码,如果找不到任何文件,它将继续处于休眠状态。它睡了半个小时,但目前我没有任何计数器,如只执行下面的代码20次然后退出程序,如果文件仍然不存在(意味着在20次检查后不做任何事情并退出完整的脚本)。

解决此问题的最佳方法是什么?通过查看已经尝试了20次的电子邮件,我也知道了。

希望我足够清楚。

while true; do
  if /home/hadoop/latest/bin/hadoop fs -ls /apps/hdtech/bds/quality-rt/dt=$DATE_YEST_FORMAT2 then
       echo "Files Present" | mailx -s "File Present"  -r admin@host.com admin@host.com
       break
  else
       echo "Sleeping for half an hour" | mailx -s "Time to Sleep Now"  -r admin@host.com admin@host.com
       sleep 1800
  fi
done

4 个答案:

答案 0 :(得分:85)

以下是您实施计数器的方法:

counter=0
while true; do
  if /home/hadoop/latest/bin/hadoop fs -ls /apps/hdtech/bds/quality-rt/dt=$DATE_YEST_FORMAT2 then
       echo "Files Present" | mailx -s "File Present"  -r admin@host.com admin@host.com
       exit 0
  elif [[ "$counter" -gt 20 ]]; then
       echo "Counter: $counter times reached; Exiting loop!"
       exit 1
  else
       counter=$((counter+1))
       echo "Counter: $counter time(s); Sleeping for another half an hour" | mailx -s "Time to Sleep Now"  -r admin@host.com admin@host.com
       sleep 1800
  fi
done

一些解释:

  • counter=$((counter+1)) - 这是你增加一个计数器的方法。在这种情况下,$ counter在双括号内是可选的。
  • elif [[ "$counter" -gt 20 ]]; then - 检查$counter是否不大于20。如果是这样,它会输出相应的消息并突破你的while循环。

答案 1 :(得分:12)

试试这个:

counter=0
while true; do
  if /home/hadoop/latest/bin/hadoop fs -ls /apps/hdtech/bds/quality-rt/dt=$DATE_YEST_FORMAT2 then
       echo "Files Present" | mailx -s "File Present"  -r admin@host.com admin@host.com
       break
  elif [[ "$counter" -gt 20 ]]; then
       echo "Counter limit reached, exit script."
       exit 1
  else
       let counter++
       echo "Sleeping for another half an hour" | mailx -s "Time to Sleep Now"  -r admin@host.com admin@host.com
       sleep 1800
  fi
done

<强>解释

  • break - 如果文件存在,它将中断并允许脚本处理文件。
  • [[ "$counter" -gt 20 ]] - 如果计数器变量大于20,则脚本将退出。
  • let counter++ - 每次通过时将计数器递增1。

答案 2 :(得分:0)

您可以使用 for 循环而不是 while 来执行此操作:

max_loop=20
for ((count = 0; count < max_loop; count++)); do
  if /home/hadoop/latest/bin/hadoop fs -ls /apps/hdtech/bds/quality-rt/dt=$DATE_YEST_FORMAT2 then
       echo "Files Present" | mailx -s "File Present"  -r admin@host.com admin@host.com
       break
  else
       echo "Sleeping for half an hour" | mailx -s "Time to Sleep Now"  -r admin@host.com admin@host.com
       sleep 1800
  fi
done

if [ "$count" -eq "$max_loop" ]; then
  echo "Maximum number of trials reached" >&2
  exit 1
fi

答案 3 :(得分:0)

#!/usr/bin/env bash
counter=0
while [[ "$counter" -lt 20 ]] 
do
  if [[ $counter -gt 0 ]] ; then
    echo "Counter: $counter time(s); Sleeping for another half an hour" | mailx -s "Time to Sleep Now"  -r admin@host.com admin@host.com
    sleep 1800  
  fi
  if /home/hadoop/latest/bin/hadoop fs -ls /apps/hdtech/bds/quality-rt/dt=$DATE_YEST_FORMAT2 ; then
       echo "Files Present" | mailx -s "File Present"  -r admin@host.com admin@host.com
       exit 0
  fi
  : $((counter++))
done

echo "Counter: $counter times reached; Exiting loop!"
exit 1

这是另一种看法。我添加了这段代码来说明这些要点:

  1. while 可以将您的计数器作为条件 - 这消除了检查循环中变量值的需要。
  2. 由于 if 分支导致循环结束(通过 break 或 exit ),因此不需要最后的 else
  3. 我提供了一种不同的语法来增加计数器。老实说,我从未见过 koola 的版本 (let counter++),但我非常喜欢它(对我来说更简单)。
  4. 我不能 100% 确定某些 while 循环提供的答案实际上循环了 20 次。相反,我认为其中一些循环了 21 次。
  5. 所提供的解决方案实际上会向管理员发送额外的电子邮件 - 如果您无论如何都要退出,则无需告诉管理员您要睡半个小时。我在 while 循环的开头添加了一个额外的 if 以避免额外的电子邮件(和睡眠)。

这是 20 次未能找到文件的运行的输出:

Counter: 1 time(s); Sleeping for another half an hour
Counter: 2 time(s); Sleeping for another half an hour
...
Counter: 19 time(s); Sleeping for another half an hour
Counter: 20 times reached; Exiting loop!

if 的缺点是我们检查文件 20 次,但只睡眠 19 次。