Давайте посмотрим, что делает каждая вещь. Во-первых, скрипт test
, слегка модифицированный для добавления шебанга:
#!/bin/sh
echo a
echo b >&2
Команда echo a
записывает "a" в стандартный вывод.
Команда echo b
записывает «б» к стандартному выводу. Но за ним следует оператор перенаправления >&2
, отправляющий стандартный вывод echo
на стандартную ошибку содержащего сценария test
.
Следовательно, сценарий test
сначала будет писать " a "к его стандартному выводу, затем напишите" b "к его стандартной ошибке.
Далее у нас есть команда:
./test >/dev/null
Это запускает test
, но перенаправляет стандартный вывод от test
до /dev/null
. Следовательно, «a» отбрасывается, но «b» по-прежнему выводится на консоль, поскольку именно здесь по умолчанию отправляется стандартная ошибка test
.
Наконец, мы имеем:
echo b >&2 >/dev/null
Запускается echo b
, что само по себе выводит «b» на стандартный вывод. Затем оператор перенаправления >&2
отправляет стандартный вывод echo
на стандартную ошибку оболочки. Но затем второй оператор перенаправления >/dev/null
отправляет стандартный вывод echo
в другое место, а именно /dev/null
. Это похоже на присвоение переменной одному значению, а затем присвоение ее другому значению; второе назначение - то, которое вступает в силу. Следовательно, нет видимого вывода.
Операторы перенаправления обрабатываются слева направо. Каждый из них меняет источник ввода или вывода на или go после запуска команды. После обработки всех операторов перенаправления команда фактически вызывается.
Концептуально можно представить, что команда представляет собой черный ящик, а дескрипторы файлов ввода и вывода, такие как стандартный ввод и стандартный вывод, представляют собой небольшие порты, которые могут быть на связи Существует набор подключений по умолчанию (стандартный вывод блока на стандартный вывод его контейнера и т. Д. c.), Но перенаправление изменяет эти подключения. Учитывая эту идею, следующая диаграмма иллюстрирует эффект двух команд:
Во втором случае оператор >&2
выполняет подключение от стандартного вывода test
к стандартной ошибке оболочки, но это немедленно изменяется, поэтому это не имеет никакого эффекта.
Я думаю, вы запутались, ожидая, что оба случая будут вести себя одинаково, потому что в каждом случае в некотором смысле мы делаем >&2
, а затем >/dev/null
. Но поскольку операторы применяются на разных уровнях, они влияют на разные процессы, что приводит к разному поведению.