Почему «if $ (ps aux | grep ...)» всегда успешно работает в Bash? - PullRequest
23 голосов
/ 23 января 2012

Почему следующий оператор if завершается успешно?

if $(ps aux | grep -q "bla bla") ; then echo "found" ; fi

Ответы [ 5 ]

34 голосов
/ 23 января 2012

Поскольку grep сам процесс возвращается ps. Вы можете «обмануть» grep, чтобы он не соответствовал самому себе, окружив один из символов поиска в классе символов [ ], который не меняет функциональность: Просто сделай:

if ps aux | grep -q "[b]la bla" ; then echo "found" ; fi

Также использование процесса подстановки $() не является необходимым. if будет работать при успешном выполнении последней команды в цепочке конвейеров, что вам и нужно.

Примечание : причина, по которой трюк класса символов работает, заключается в том, что вывод ps все еще содержит скобки класса символов, но когда grep обрабатывает строку поиска, он использует скобки в качестве синтаксиса, а не фиксированная строка для соответствия.

8 голосов
/ 23 января 2012

Если вы извлечете вывод из ps aux, вы всегда получите процесс, показывающий вашу предыдущую команду.Чтобы это исправить, вы можете дважды передать вывод в grep, один раз, чтобы удалить строку с «grep» в нем, и снова для процесса, который вы ищете.

ps aux | grep -v "grep" | grep "Finder"
7 голосов
/ 23 января 2012

процесс 'grep' уже запущен к моменту запуска ps, поэтому вывод ps включает его.

Попробуйте использовать pgrep.

pgrep именно для этой цели:

if pgrep "bla bla" ; then echo "found" ; fi

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

$( немного важен и немного меняет значение.Хотя в этом случае из-за того, что grep -q никогда не выводится, вы можете просто обойтись без $(.Возможно, вы захотите начать с чего-то вроде (как указано другими):

if ps aux | grep -v 'grep' | grep -q 'bla bla'; then
    echo 'Found'
fi

В любом случае, вы начали с

if $(ps aux | grep -q "bla bla") ; then echo "found" ; fi

с $(, командой внутри $( ) выполняется, и результат этой команды используется в качестве командной строки для внешней команды.Выполните эти четыре эксперимента:

# if $(echo nonexistant ; true) ; then echo "found" ; fi
nonexistant: command not found

# if $(echo nonexistant ; false) ; then echo "found" ; fi
nonexistant: command not found

# if $(echo  ; true) ; then echo "found" ; fi
found

# if $(echo  ; false) ; then echo "found" ; fi

Таким образом, согласно этому вы получите get found, если оба эти условия выполняются:

  • Команда внутри $( ), созданная нетoutput
  • и команда была успешной

Это говорит о том, что ps aux | grep -q "bla bla" был успешным и не создал выходных данных.Неудивительно, что grep -q не создает вывода.Вот для чего -q.Следовательно, ваша команда должна была иметь истинный статус, что означает, что grep успешно нашел совпадение.Мы знаем, что grep всегда найдет совпадение в этом случае, потому что список процессов из ps будет включать в себя grep;grep всегда найдет себя.

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

Вам необходимо отфильтровать процесс, который является grep ping для 'bla bla':

$ if ps aux | grep -v 'grep' | grep -q 'bla bla'; then
    echo 'Found'
fi
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...