Что означает grep с перенаправлением stdout на / dev / null в скрипте задания? - PullRequest
0 голосов
/ 04 июля 2018

У меня есть скрипт bash, который передается как задание bash. Он создает несколько файлов, выполняет некоторые вычисления, перемещает выходные файлы куда-то еще и очищает. Для перемещения выходных файлов он содержит следующие строки:

set -e
mv $tmp/stdout.txt $current/tmp.stdout.txt
grep Report $current/tmp.stdout.txt >/dev/null 2>&1
mv $current/tmp.stdout.txt $current/stdout.txt
set +e

Если вычисление прошло успешно, выходной файл stdout.txt содержит несколько строк, которые начинаются с Report; но нет, если нет. Дальнейшая обработка проверяет, что файл $current/stdout.txt существует (и повторно отправляет задание).

Первый mv перемещает выходной файл из временного каталога в последний каталог с временным именем; а второй mv переименовывает выходной файл в его окончательное имя. Но какова цель 1011 * между ними? Если выходной файл содержит строки с Report, они перенаправляются на \dev\null и ничего не происходит. Если выходной файл не содержит строк с Report, он ничего не выводит ни в перенаправленный stdout, ни в перенаправленный stderr. Поэтому у меня сложилось впечатление, что эта строка ничего не делает, и я должен заменить mv + grep + mv на один mv. Какой функционал я здесь упускаю?

Ответы [ 3 ]

0 голосов
/ 04 июля 2018

Здесь важно set -e.

  • grep устанавливает свой статус выхода равным 0, входной файл успешно обработан и все результаты найдены, и ненулевое значение в противном случае.
  • set -e говорит оболочке завершиться, если любая проверенная команда имеет ненулевой статус выхода. (У него есть куча ошибок и предостережений, и обычно его не следует использовать; см. BashFAQ # 105 ).

Таким образом - если этот код не внедрен в контекст, который запускает один из нескольких сценариев, где set -e не имеет никакого эффекта - ваш сценарий завершается до второго mv, если grep не имеет совпадений.


Лучший способ написать этот раздел вашего сценария:

mv "$tmp/stdout.txt" "$current/tmp.stdout.txt" || exit
grep -q Report "$current/tmp.stdout.txt" || exit
mv "$current/tmp.stdout.txt" "$current/stdout.txt" || exit
  • grep -q более эффективен, чем grep >/dev/null, так как он может завершиться немедленно при обнаружении совпадения, тогда как в противном случае grep необходимо прочитать полностью до конца входного файла. (2>/dev/null - это, как правило, плохая практика, поскольку она скрывает ошибки, о которых вам нужно знать, чтобы отладить неправильное поведение; отсюда и устранение здесь).
  • Кавычки делают переменные с пробелами или символами глобуса безопасными, в противном случае они не были бы.
  • Помещение || exit в отдельные команды, которые вы хотите привести к фатальным ошибкам, значительно надежнее, чем зависимость от set -e по причинам, указанным в BashFAQ # 105 (пропустите аллегорию для приведенных ниже упражнений, если в спешке, или посмотрите https://www.in -ulm.de / ~ mascheck / различным / set-e / для списка случаев, когда поведение set -e, как известно, отличается в разных оболочках и / или выпуски оболочки).
0 голосов
/ 04 июля 2018

set -e настраивает bash для прерывания при первой обнаруженной ошибке. Если grep не удается (ничего не находит), bash завершится после grep.

Большинство grep версий, тем не менее, знают параметр -q, который делает их тихими (подавляет весь вывод), поэтому перенаправление больше не требуется. Кроме того, код, основанный на set -e, не прост в обслуживании. Правильный grep ... || exit 1 будет более явным.

0 голосов
/ 04 июля 2018

Grep вернет код ошибки, если совпадений не найдено.

set -e означает, что ошибка остановит скрипт.

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

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