2012-01-19 258 views
0

我正在编写一个例程,它将识别进程是否停止运行,并在目标进程结束后执行某些操作。shell while循环不停止

我想出了这个代码(为我将来的代码测试):

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

我的问题是,由于某种原因,该循环永远不会停止,呼应1我删除文件“AAA”之后。

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

我期望的输出被“DONE”只要我删除文件...

什么问题?

SOLUTION:

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

回答

6

$?的值很容易改变。在当前版本的代码,这条线:

echo $? 

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

保存的$?另一个变量,一个价值不会被打一顿在下一次执行命令:如果ls | grep aaa用来检查一个名为aaa文件是否存在,这

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

while [ ! -f aaa ] ; ... 

是一个更干净的方式来做到这一点。

+0

谢谢,这仅仅是一个例子。我的最终命令是: ps -ef | grep“mysqldump”| grep -v“grep mysqldump” while [$? = 0]; \t do \t sleep 1200 \t ps -ef | grep“mysqldump”| grep -v“grep mysqldump”; 完成; tar cvzf [dumpdir] [files] rm [files] – Rgonomike

+2

@Rgonomike:你可以这样写:“while ps -ef | ... | grep mysqldump; do sleep 1200; done”。这将简化代码。 (虽然解析ps的方法是错误的,但你真正想要的是让mysqldump的父节点执行后续处理,因为当mysqldump退出时它会发出警报。) –

2

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

+0

我按照你的建议编辑了脚本(只是移动了我的睡眠命令)。它仍然不起作用,虽然...相同的结果。 还有其他建议吗? – Rgonomike

+0

现在'$?'是'echo'命令的结果。 –

+0

确实!好的问题解决了。 谢谢。 – Rgonomike

1

您可以重写环路更简单的方式是这样的:

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

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

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

 
while cmd; do ...; done 

,而不是在你的情况,你的评价是正在测试的命令解析PS的输出不在话下。虽然有很好的论点,你不应该这样做,并且后续处理应该由你正在等待的命令的父母来完成,但我们现在将忽略这个问题。你可以简单的写:

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

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

+1

有一个技巧可以避免'grep ... | grep -v grep':'grep'[m] ysqldump'' –

0

推测你的目标是等到包含字符串$value的文件名存在于本地目录中,而不一定是单个文件名。

尝试:

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

你原来的代码失败,因为$?充满echo命令一旦在第一每次迭代的返回码。

顺便说一句,如果你打算在未来使用ps而不是ls,除非你很聪明,否则你会选择自己的grep。使用ps -ef | grep [m]ysqlplus