Ответ 1
% (sh myscript.sh 3>&2 2>&1 1>&3) 2>/dev/null
I'm stderr
% (sh myscript.sh 3>&2 2>&1 1>&3) >/dev/null
I'm stdout
Для оболочки script:
#!/bin/sh
echo "I'm stdout";
echo "I'm stderr" >&2;
Есть ли способ вызвать этот script такой, что только stderr будет распечатываться, когда последняя часть команды равна 2 > /dev/null, т.е.
$ > sh myscript.sh SOME_OPTIONS_HERE 2>/dev/null
I'm stderr
Или, альтернативно:
$ > sh myscript.sh SOME_OPTIONS_HERE >/dev/null
I'm stdout
Это вопрос в конце набора лекционных слайдов, но после почти дня работы над этим я почти уверен, что это своего рода опечатка. Поворот не работает. 2 > & - не работает. У меня нет идей!
% (sh myscript.sh 3>&2 2>&1 1>&3) 2>/dev/null
I'm stderr
% (sh myscript.sh 3>&2 2>&1 1>&3) >/dev/null
I'm stdout
Для полноты, основанной на комментарии от @200_success выше, вероятно, лучше переместить файловый дескриптор 3 с помощью 1>&3-
$ (sh myscript.sh 3>&2 2>&1 1>&3-) 2>/dev/null
I'm stderr
$ (sh myscript.sh 3>&2 2>&1 1>&3-) >/dev/null
I'm stdout
Вместо того, чтобы обменивать файловые дескрипторы на основе каждого процесса, используя exec
, вы можете менять stdin и stderr для всех следующих команд, запущенных текущей оболочкой:
$ (exec 3>&2 2>&1 1>&3- ; sh myscript.sh ; sh myscript.sh ) 2>/dev/null
I'm stderr
I'm stderr
$ (exec 3>&2 2>&1 1>&3- ; sh myscript.sh ; sh myscript.sh ) >/dev/null
I'm stdout
I'm stdout
Перемещение дескриптора файла (1>&3-
) не является переносимым, не все его реализации POSIX поддерживают его. Это ksh93-ism и bash -ism. (подробнее здесь https://unix.stackexchange.com/questions/65000/practical-use-for-moving-file-descriptors)
Также можно закрыть FD 3 после выполнения перенаправления.
ls 3>&2 2>&1 1>&3 3>&-
выводит содержимое текущего рабочего каталога из stderr.
Синтаксис 3>&-
или 3<&-
закрывает дескриптор файла 3.
bash хакерская вики может быть очень полезной в таких вещах. Там есть способ сделать это, который не упоминается среди этих ответов, поэтому Я поставлю свои два цента.
Семантика >&N
, для числового N, означает перенаправление на цель
файловый дескриптор N. Слово target важно, поскольку дескриптор может изменить цель позже, но как только мы скопировали эту цель, нам все равно. Причина, по которой порядок, в котором мы заявляем о перенаправлении, имеет значение.
Итак, вы можете сделать это следующим образом:
./myscript.sh 2>&1 >/dev/null
Это означает:
перенаправить stderr в цель stdout, то есть выходной поток stdout. Теперь stderr скопировал цель stdout
Измените stdout на /dev/null. Это не повлияет на stderr, так как он "скопировал" цель, прежде чем мы ее изменили.
Нет необходимости в третьем файловом дескрипторе.
Интересно, как я просто не могу сделать >&-
вместо >/dev/null
. Это фактически закрывает stdout, поэтому я получаю сообщение об ошибке (на stderr target, то есть фактическое stdout, конечно: D)
line 3: echo: write error: Bad file descriptor
Вы можете видеть, что этот порядок имеет значение, пытаясь заменить перенаправления:
./myscript.sh >/dev/null 2>&1
Это не сработает, потому что:
/dev/null
/dev/null
снова.