Reputation: 338
I'm writing a routine that will identify if a process stops running and will do something once the processes targeted is gone.
I came up with this code (as a test for my future code):
#!/bin/bash
value="aaa"
ls | grep $value
while [ $? = 0 ];
do
sleep 5
ls | grep $value
echo $?
done;
echo DONE
My problem is that for some reason, the loop never stops and echoes 1 after I delete the file "aaa".
0
0 >>> I delete the file at that point (in another terminal)
1
1
1
1
.
.
.
I would expect the output to be "DONE" as soon as I delete the file...
What's the problem?
SOLUTION:
#!/bin/bash
value="aaa"
ls | grep $value
while [ $? = 0 ];
do
sleep 5
ls | grep $value
done;
echo DONE
Upvotes: 0
Views: 4968
Reputation: 2804
Presumably your objective is to wait until a filename containing the string $value
is present in the local directory and not necessarily a single filename.
try:
#!/bin/bash
value="aaa"
while ! ls *$value*; do
sleep 5
done
echo DONE
Your original code failed because $?
is filled with the return code of the echo
command upon every iteration following the first.
BTW, if you intend to use ps
instead of ls
in the future, you will pick up your own grep
unless you are clever. Use ps -ef | grep [m]ysqlplus
.
Upvotes: 0
Reputation: 212178
You ought not duplicate the command to be tested. You can always write:
while cmd; do ...; done
instead of
cmd while [ $? = 0 ]; do ...; cmd; done
In your case, you mention in a comment that the command you are testing is parsing the output of ps. Although there are very good arguments that you ought not do that, and that the followon processing should be done by the parent of the command for which you are waiting, we'll ignore that issue at the moment. You can simply write:
while ps -ef | grep -v "grep mysqldump" | grep mysqldump > /dev/null; do sleep 1200; done
Note that I changed the order of your pipe, since grep -v will return true if it matches anything. In this case, I think it is not necessary, but I believe is more readable. I've also discarded the output to clean things up a bit.
Upvotes: 1
Reputation: 784898
You can rewrite that loop in much simpler way like this:
while [ -f aaa ]; do
sleep 5;
echo "sleeping...";
done
Upvotes: 1
Reputation: 263177
The value of $?
changes very easily. In the current version of your code, this line:
echo $?
prints the status of the previous command (grep
) -- but then it sets $?
to 0, the status of the echo
command.
Save the value of $?
in another variable, one that won't be clobbered next time you execute a command:
#!/bin/bash
value="aaa"
ls | grep $value
status=$?
while [ $status = 0 ];
do
sleep 5
ls | grep $value
status=$?
echo $status
done;
echo DONE
If the ls | grep aaa
is intended to check whether a file named aaa
exists, this:
while [ ! -f aaa ] ; ...
is a cleaner way to do it.
Upvotes: 6
Reputation: 7727
$?
is the return code of the last command, in this case your sleep
.
Upvotes: 2