Shell虽然循环没有停止

时间:2012-01-19 10:26:59

标签: bash shell while-loop

我正在编写一个例程,用于识别进程是否停止运行,并在目标进程消失后执行某些操作。

我想出了这段代码(作为我未来代码的测试):

#!/bin/bash
value="aaa"
ls | grep $value
while [ $? = 0 ]; 
    do
    sleep 5
    ls | grep $value
    echo $?
done;
echo DONE

我的问题是,由于某种原因,在删除文件“aaa”后,循环永不停止并回显1。

0
0    >>> I delete the file at that point (in another terminal)
1
1
1
1
.
.
    .

一旦删除文件,我希望输出为“DONE”...

有什么问题?

解决方案:

#!/bin/bash
value="aaa"
ls | grep $value
while [ $? = 0 ];
    do
    sleep 5
    ls | grep $value
done;
echo DONE

5 个答案:

答案 0 :(得分:6)

$?的值很容易变化。在当前版本的代码中,这一行:

echo $?

打印上一个命令的状态(grep) - 然后它将$?设置为0,即echo命令的状态。

$?的值保存在另一个变量中,该变量在下次执行命令时不会被破坏:

#!/bin/bash
value="aaa"
ls | grep $value
status=$?
while [ $status = 0 ]; 
    do
    sleep 5
    ls | grep $value
    status=$?
    echo $status
done;
echo DONE

如果ls | grep aaa旨在检查名为aaa的文件是否存在,请执行以下操作:

while [ ! -f aaa ] ; ...

是一种更干净的方式。

答案 1 :(得分:2)

$?是最后一个命令的返回码,在这种情况下是sleep

答案 2 :(得分:1)

你可以用这样简单的方式重写那个循环:

while [ -f aaa ]; do
   sleep 5;
   echo "sleeping...";
done

答案 3 :(得分:1)

您不应该复制要测试的命令。你总是可以写:

while cmd; do ...; done

而不是

cmd
while [ $? = 0 ]; do ...; cmd; done

在您的情况下,您在评论中提到您正在测试的命令正在解析ps的输出。虽然有很好的论据,你不应该这样做,并且跟随处理应该由你正在等待的命令的父进行,我们现在将忽略该问题。你可以简单地写一下:

while ps -ef | grep -v "grep mysqldump" |
    grep mysqldump > /dev/null; do sleep 1200; done

请注意,我更改了管道的顺序,因为如果grep -v将返回true 匹配任何东西在这种情况下,我认为没有必要,但我相信更多 可读。我也放弃了输出来清理一下。

答案 4 :(得分:0)

大概你的目标是等到包含字符串$value的文件名出现在本地目录中,而不一定是单个文件名。

尝试:

#!/bin/bash
value="aaa"
while ! ls *$value*; do
  sleep 5
done
echo DONE

原始代码失败,因为$?在第一次迭代后的每次迭代中都填充了echo命令的返回码。

顺便说一句,如果您打算将来使用ps代替ls,除非您聪明,否则您将选择自己的grep。使用ps -ef | grep [m]ysqlplus