Вопрос или проблема
Я хочу выполнить простой grep
на вывод dumpe2fs
, но я постоянно вижу dumpe2fs 1.46.5 (30-Dec-2021)
, отображающийся после моего grep
:
$ sudo dumpe2fs -h /dev/sdb2 | grep 'Block count:'
dumpe2fs 1.46.5 (30-Dec-2021)
Block count: 1247300
Но если я перенаправлю stderr
команды dumpe2fs
в stdout
с помощью |&
, тогда все будет работать должным образом:
$ sudo dumpe2fs -h /dev/sdb2 |& grep 'Block count:'
Block count: 1247300
Вопрос в том, почему dumpe2fs
записывает номер версии dumpe2fs 1.46.5 (30-Dec-2021)
в stderr
?!
Ответ или решение
Вопрос о том, почему утилита dumpe2fs
выводит номер своей версии в стандартный поток ошибок (stderr), является примером поведенческих особенностей командной строки, которые иногда могут сбивать с толку пользователей. Этот феномен обусловлен рядом технических и исторических причин, и чтобы подробно ответить на этот вопрос, рассмотрим теоретическую часть, примеры и практическое применение.
Теория
Стандартный поток ошибок (stderr) используется в UNIX-подобных операционных системах для вывода сообщений об ошибках и другой важной информации, которая не должна смешиваться с основным выводом программы. Это позволяет отделять диагностические сообщения от данных, с которыми работает программа, обеспечивая более удобную обработку и анализ.
Одной из практик, используемых разработчиками для информирования пользователей о версиях программного обеспечения, является вывод информации о версии через stderr. Это делается, чтобы версия всегда выводилась, даже если основной вывод программы перенаправляется или обрабатывается, как, например, в случае команды grep
.
Пример
В представленном вами сценарии:
$ sudo dumpe2fs -h /dev/sdb2 | grep 'Block count:'
dumpe2fs 1.46.5 (30-Dec-2021)
Block count: 1247300
Вы видите, что номер версии выводится, несмотря на использование grep
. Это потому, что grep
по умолчанию обрабатывает только стандартный вывод (stdout), а информация о версии, будучи отправленной в stderr, остается вне его зоны действия. Таким образом, версия утилиты dumpe2fs
выводится, подтверждая использование конкретной версии программы, что может быть полезно в тех случаях, когда необходимо диагностировать проблемы, связанные с версиями.
Когда вы используете команду |&
, то объединяете оба потока (stdout и stderr), что позволяет grep
обработать всё:
$ sudo dumpe2fs -h /dev/sdb2 |& grep 'Block count:'
Block count: 1247300
Теперь grep
извлекает только строку, содержащую текст "Block count:", а информация о версии, хотя и была выведена, игнорируется.
Применение
Понимание того, почему и как информация о версиях выводится, имеет практическое значение для системных администраторов и разработчиков, которые часто работают со скриптами и автоматизацией. Возможность отделить диагностическую информацию от основного вывода может существенно повысить надежность и читабельность скриптов.
Например, при программировании скриптов автоматической диагностики состояния дисковой системы весьма важно получать чистый и структурированный вывод, который можно легко анализировать и по которому можно принимать решения. Однако при необходимости отладки или в случае обнаружения ошибок важно иметь возможность быстро определить используемую версию утилиты, что может помочь в выявлении и исправлении известных багов, связанных с конкретными версиями.
Кроме того, это знание позволяет лучше понимать и управлять потоками данных в командной строке. В более сложных сценариях, где данные перенаправляются между несколькими программами, контроль над стандартными и ошибочными потоками становится критически важным. Например, вbash сценарии могут быть включены условия для более гибкой обработки ошибок и диагностики.
Подводя итог, следует отметить, что использование stderr для вывода вспомогательной информации, такой как версии программ, является лучшей практикой, позволяющей обеспечить более гибкую и прозрачную работу скриптов. Это облегчает диагностику и позволяет отделить основные данные от вспомогательной информации.