Оболочка пока петля не останавливается - PullRequest
0 голосов
/ 19 января 2012

Я пишу подпрограмму, которая будет определять, останавливается ли процесс и будет ли что-то делать, когда целевые процессы исчезнут.

Я придумал этот код (в качестве теста для моего будущего кода):

#!/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
.
.
    .

Я ожидаю, что вывод будетСОВЕРШЕНО ", как только я удалю файл ...

В чем проблема?

РЕШЕНИЕ:

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

Ответы [ 5 ]

6 голосов
/ 19 января 2012

Значение $? изменяется очень легко. В текущей версии вашего кода эта строка:

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 ] ; ...

это более чистый способ сделать это.

2 голосов
/ 19 января 2012

$? - это код возврата последней команды, в данном случае ваш sleep.

1 голос
/ 19 января 2012

Вы не должны дублировать проверяемую команду. Вы всегда можете написать:

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, если она соответствует чему угодно. В этом случае, я думаю, что это не является необходимым, но я считаю, что больше удобочитаемый. Я также отбросил вывод, чтобы немного почистить вещи.

1 голос
/ 19 января 2012

Вы можете переписать этот цикл намного проще, например так:

while [ -f aaa ]; do
   sleep 5;
   echo "sleeping...";
done
0 голосов
/ 02 марта 2012

Предположительно, ваша цель - дождаться, пока имя файла, содержащее строку $value, будет присутствовать в локальном каталоге, а не обязательно в одном файле.

попробовать:

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

Ваш исходный код не выполнен, поскольку $? заполняется кодом возврата команды echo при каждой итерации, следующей за первой.

Кстати, если вы собираетесь использовать ps вместо ls в будущем, вы подберете свой собственный grep, если вы не умны. Используйте ps -ef | grep [m]ysqlplus.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...