Как некоторые терминальные программы могут игнорировать перенаправления и каналы?

292
Hanlon

Я возился со своей сетевой картой сегодня вечером, когда заметил что-то во время работы ip link help. Вот два случая, когда я заметил что-то другое:

ip link help | grep set 

а также

ip link help > ip_link_help.txt 

Первая команда не имеет никакого эффекта, т.е. вместо перенаправления вывода ip link helpиз stdoutto grep, канал просто игнорируется, а вывод ip link helpотправляется в stdout.

Второй случай немного другой. Несмотря ip link helpна то, что игнорирует символ перенаправления >и просто печатает в stdout, файл file.txtвсе равно создается (но он пуст).

0

1 ответ на вопрос

3
Kamil Maciorowski

ip link helpпечатает со стандартной ошибкой (stderr, дескриптор файла 2); его стандартный вывод (stdout, дескриптор файла 1) не получает данных. Обычно два потока идут к терминалу, так что вы не можете различить их на первый взгляд. |или >влияет на стандартный вывод. После его использования вы знаете, что любые данные, которые будут перенаправлены, должны быть направлены в stdout; все остальное - в другое место: обычно в stderr, хотя некоторые программы печатают некоторые данные непосредственно в терминал ( ipэто не одна из них).

В первом случае вы можете перенаправить stderr в файловый дескриптор stdout, а затем построить конвейер:

ip link help 2>&1 | grep set 

где 2>&1указывает оболочке перенаправлять дескриптор файла 2на то, на что 1указывает дескриптор файла . С этим синтаксисом, если команда выведет что-то в stdout и stderr, все получится grep.

Во втором случае оболочка создает (при необходимости) и усекает файл перед ipзапуском. Вы можете увидеть это, вызвав

a_command_that_doesnt_even_exist > foo.txt 

foo.txtбудет создан, несмотря на очевидную ошибку. Это потому, что он создается первым, еще до того, как оболочка попытается запустить команду.

Для захвата stderr в файл используйте 2>перенаправление только stderr:

ip link help 2> ip_link_help.txt 

Аналогично 1>перенаправляет только стандартный вывод. Шорт, который >вы использовали, строго эквивалентен 1>.


Искусственный пример команды, которая печатает на терминал тремя различными способами:

echo "standard output"; echo "standard error" >&2; echo "terminal" >/dev/tty 

Выход:

standard output standard error terminal 

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

(echo "standard output"; echo "standard error" >&2; echo "terminal" >/dev/tty) >stdout.txt 2>stderr.txt 

Это все равно будет печатать последнюю строку.

@JakeGould я не собираюсь начинать войну редактирования, но я сознательно решил отличить код (реальный код, который * предназначен * для запуска) от случайного вывода, который * не * код (он не предназначен для запуска; выгоды от форматирования как код). Kamil Maciorowski 5 лет назад 0
И здесь общепринято, что вывод терминала также может отображаться как «код». Добавление кавычек в подобный код на самом деле не то, что делается на сайтах Stack Exchange. JakeGould 5 лет назад 0
@JakeGould Всегда есть возможности для улучшения. :) Kamil Maciorowski 5 лет назад 0

Похожие вопросы