Однажды я заметил, что один из моих скриптов, сканирующих почтовые журналы, не выдал сообщение об одной записи, о наличии которой в журнале мне было известно (о ней меня оповестил другой скрипт). Работа скрипта начинается с использования
grep
для
фильтрации записей, которые меня не интересуют:
grep -hv 'a specific pattern' "$@" | exigrep '...' | [...]
Я, столкнувшись этим, чего только себе не напридумывал.
Может, я неправильно понимаю суть опции
-v
? А, может
быть, команда
exitgrep вытворяет что-то такое, о чём я и не подозреваю? В
итоге я решил обработать файл с использованием одной только команды
grep
, соединённой конвейером с командой
less
, и, пользуясь less
, сразу открыл
последние строки вывода, так как знал, что запись, которая в файле
была, но о которой скрипт мне не сообщил, находилась где-то ближе к
концу файла. Случилось то, чего я и ожидал. А именно, в
определённый момент команда grep
просто остановилась.
Я, в частности, увидел следующее:
2020-04-13 16:07:06 H=(111iu.com) [223.165.241.9] [...]2020-04-13 16:07:07 unexpected disconnection [...]Binary file /var/log/exim4/mainlog matches
Ну конечно. Крайне полезные сведения. В процессе чтения того, что до этого команда считала текстовым файлом, она столкнулась с некими интересными символами (в строке с информацией о подписи DKIM) и решила, что файл, на самом деле, был бинарным, поэтому ей не нужно обрабатывать остаток файла, не нужно сообщать больше ни о чём, кроме того, что сообщено в последней строке.
(Этот случай отличается от поведения
grep
, когда
программа
полагает, вводимая в заблуждение багом файловой системы и
собственной интеллектуальностью, что некоторые текстовые файлы
являются бинарными. То, что произошло в этот раз, объяснить гораздо
проще.)Мне, в целом, нравятся GNU-версии стандартных Unix-утилит и их дополнительные возможности. Сюда, правда, не относится то поведение GNU grep, с которым я столкнулся. Особенно когда результаты работы этой команды не выводятся в терминал. Я так думаю, что если программа начала выводить текстовые строки, то она должна и дальше их выводить, а не вести себя неким непредсказуемым образом.
Из этого всего я вынес ценный урок. Заключается он в том, что каждый раз, когда я обрабатываю текстовые файлы с помощью GNU grep (а в моих скриптах, в общем-то, я всегда обрабатываю текстовые файлы именно так), мне нужно явным образом указывать программе на то, что она должна воспринимать эти файлы именно как текстовые. Это, к сожалению, приведёт к утяжелению кода некоторых скриптов, так как порой я пользуюсь конвейерами, в которых используются несколько команд
grep
, применяемых для фильтрации и
обработки текста. В результате мне нужно либо снабдить все
используемые команды grep
опциями -a
,
либо выяснить, какая переменная окружения вида LC_
позволит, с минимальным воздействием на систему, это отключить,
либо взяться за нечто такое, что можно сравнить со здоровенной
кувалдой, использовав, как рекомендуется в справке по GNU grep,
переменную LC_ALL=C
.
P.S. Описанная здесь проблема касается не только Linux, так как GNU
grep используется не только на компьютерах, работающих под
управлением Linux. Тут всё зависит от того, что именно
устанавливают, и что именно попадает в переменную
PATH
. Например, на FreeBSD-машине, к которой у меня
есть доступ, GNU grep используется в виде
/usr/bin/grep
.
Приходилось ли вам сталкиваться с неожиданными эффектами,
возникающими при использовании Unix-команд?