порядок перенаправления стандартных потоков оболочки
Порядок имеет значение, так как результат отличается. Возьмите свой первый пример:
ls -al /doesNotExists 2>&1 1>/dev/null
Это направляет только стандартный вывод на nul, потому что стандартная ошибка была продублирована на стандартный вывод до того, как стандартный вывод был перенаправлен на dirlist.
ls -al /doesNotExists 1>/dev/null 2>&1
Это направляет как стандартный вывод, так и стандартную ошибку в nul.
Справочное руководство Bash: Перенаправления
Обратите внимание, что порядок перенаправлений является значительным. Например, команда
ls > dirlist 2>&1
направляет как стандартный вывод (дескриптор файла 1), так и стандартную ошибку (дескриптор файла 2) в файл dirlist, а команда
ls 2>&1 > dirlist
направляет только стандартный вывод в файл dirlist, потому что при стандартной ошибке была сделана копия стандартного вывода до того, как стандартный вывод был перенаправлен в dirlist.
Source Bash Справочное руководство: Перенаправления
Руководство
В Illustrated Redirection Tutorial есть хороший иллюстрированный учебник, который облегчает понимание:
Порядок перенаправления, т. Е. "> Файл 2> & 1" против "2> & 1> файл"
Хотя не имеет значения, где перенаправления появляются в командной строке, их порядок имеет значение. Они настроены слева направо.
2>&1 >file
Распространенной ошибкой является выполнение команды 2> & 1> file для перенаправления как stderr, так и stdout в файл. Посмотрим, что происходит. Сначала мы набираем команду в нашем типичном терминале, дескрипторы выглядят так:
--- +-----------------------+
standard input ( 0 ) ---->| /dev/pts/5 |
--- +-----------------------+
--- +-----------------------+
standard output ( 1 ) ---->| /dev/pts/5 |
--- +-----------------------+
--- +-----------------------+
standard error ( 2 ) ---->| /dev/pts/5 |
--- +-----------------------+
Затем наша оболочка Bash видит 2> & 1, поэтому она дублирует 1, и дескриптор файла выглядит следующим образом:
--- +-----------------------+
standard input ( 0 ) ---->| /dev/pts/5 |
--- +-----------------------+
--- +-----------------------+
standard output ( 1 ) ---->| /dev/pts/5 |
--- +-----------------------+
--- +-----------------------+
standard error ( 2 ) ---->| /dev/pts/5 |
--- +-----------------------+
Правильно, ничего не изменилось, 2 уже указывал на то же место, что и 1. Теперь Bash видит> файл и таким образом меняет стандартный вывод:
--- +-----------------------+
standard input ( 0 ) ---->| /dev/pts/5 |
--- +-----------------------+
--- +-----------------------+
standard output ( 1 ) ---->| file |
--- +-----------------------+
--- +-----------------------+
standard error ( 2 ) ---->| /dev/pts/5 |
--- +-----------------------+
И это не то, что мы хотим.
>file 2>&1
Теперь давайте посмотрим на правильную команду> file 2> & 1. Мы начинаем как в предыдущем примере, и Bash видит> file:
--- +-----------------------+
standard input ( 0 ) ---->| /dev/pts/5 |
--- +-----------------------+
--- +-----------------------+
standard output ( 1 ) ---->| file |
--- +-----------------------+
--- +-----------------------+
standard error ( 2 ) ---->| /dev/pts/5 |
--- +-----------------------+
Затем он видит наше дублирование 2> & 1:
--- +-----------------------+
standard input ( 0 ) ---->| /dev/pts/5 |
--- +-----------------------+
--- +-----------------------+
standard output ( 1 ) ---->| file |
--- +-----------------------+
--- +-----------------------+
standard error ( 2 ) ---->| file |
--- +-----------------------+
И вуаля, и 1 и 2 перенаправлены в файл.