我正在编写一个例程,用于识别进程是否停止运行,并在目标进程消失后执行某些操作。
我想出了这段代码(作为我未来代码的测试):
#!/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
答案 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
。