Bash脚本:显示进度指示器,直到while循环完成

时间:2016-06-19 14:21:40

标签: bash

我已经能够显示进度指示器,而某些进程一直运行直到完成,但是当我运行while循环时,我无法正确显示相同进度指示器的代码。例如,我在脚本内部执行此操作时执行此操作:

/bin/ping -c 10 $ipaddress > /pinglog & PID=$!
printf "["
while kill -0 $PID 2> /dev/null; do
    printf "."
    sleep 1
done
printf "] "

我还可以在脚本中使用sleep命令显示进度:

sleep 30 & PID=$!
printf "["
while kill -0 $PID 2> /dev/null; do
 printf  "."
 sleep 1
done
printf "] "

这两个例子都有效,我的输出如下:

[.........................}

这些点每秒都会继续,直到命令完成,这就是我想要的。但我现在试图使用while循环获得相同的输出,我无法得到我追求的结果。这是我到目前为止所拥有的。

while [[ ! $(/bin/grep -wo -m1 $VAR1 /logfile) ]] & PID=$!
printf "["
while kill -0 $PID 2> /dev/null; do
    printf "."
    sleep 1
done
printf "] "
do
sleep 5
done
echo $VAR1 was found

然而,当找到字符串并且输出如下所示时,它不会停止:

[.] [.] [.] [.] [.] and on and on...

我已经尝试移动实际的while循环do,sleep 5并在第一个printf语句之上完成,但结果更糟,我甚至没有获得进度指示器输出。我如何解决这个问题,以便获得与前2个示例相同的进度指示器输出,并在找到模式时停止?

2 个答案:

答案 0 :(得分:1)

while测试的命令是do之前的最后一个命令。因此,您的循环基本上是while ...; printf "] "; do ... ; end,并且由于printf永远不会失败,while永远不会终止。

虽然我不清楚你期望用while循环测试什么。如果期望复合命令[[ ! $(/bin/grep -wo -m1 $VAR1 /logfile) ]] &将被测试,您应该知道当您在后台运行命令时,状态代码仅反映bash是否能够按顺序分叉子项运行后台命令(几乎总是如此)。在命令完成之前,命令的状态代码不可用,因此如果您只想检查状态代码,它在后台运行它或多或少是毫无意义的。

如果您希望这样做,您可以对整个while循环进行后台处理;将&放在终止done复合语句的while之后。这可能就是你真正想要的东西:

printf "["
while ! grep -wqm1 "$VAR1" logfile; do
  sleep 1
done &
while kill -0 $! 2>/dev/null; do
  printf "."
done
printf "] "

注意:-q的{​​{1}}选项会导致它只生成状态返回。 (通过该更改,grep实际上是多余的。)这避免了必须使用-m1来测试输出。除非您100%确定[[不能包含空格或shell元字符,否则应使用引号括起扩展。不需要在变量中存储$VAR1,因为它将继续包含相同的值,直到您将其他命令作为背景。

答案 1 :(得分:0)

我已经解决了这个问题。要拥有[........]输出格式,你必须启动第一个printf" ["在第一个while循环开始之前。然后将sleep 5命令放在后台并在其PID上使用第二个while循环,而不是初始while循环本身,因为我们想要杀死sleep 5命令而不是while循环本身。这将允许点每隔一秒而不是每5秒在括号内重复,并允许找到搜索字符串。最后把最后的printf"]"在搜索字符串的while循环结束后,完成格式化的最后一次完成。这可以防止每五秒重复一次[。]。这对我有用:

printf "["
while [[ ! $(/bin/grep -wo -m1 $VAR1 /logfile) ]]
do
sleep 5 & PID=$!
while kill -0 $PID 2> /dev/null; do
    printf "."
    sleep 1
done
done
printf "] "
echo $VAR1 was found