Что делает перенаправление "2 <& 1" в оболочке Bourne?
2>&1
redirect в оболочке Bourne выводит результат, отправленный в дескриптор файла 2 (по умолчанию, стандартную ошибку) и отправляет его вместо этого в файл дескриптор 1 (по умолчанию стандартный вывод).
Но что делает перенаправление 2<&1
?
Он отправляет stderr в stdin?
Моя теория заключалась в том, что она отправляла stdin в stderr (например, такой же, как 1>&2
), но экспериментально, это не так:
$ perl -e 'print "OUT\n"; print STDERR "ERR\n"; \
while (<>) { print "IN WAS $_\n";}' \
> out3 2<&1
df
$ cat out3
ERR
OUT
IN WAS df
Обратите внимание, что стандартная ошибка и стандартная ошибка обоих отправились в файл out3, где stdout был перенаправлен.
Ответы
Ответ 1
Оператор <&
дублирует дескриптор файла ввода. Согласно IEEE Std 1003.1-2001 (aka Single Unix Specification v3, преемник POSIX), предполагается, что это ошибка, чтобы сказать 2<&1
, если 1 не является файловым дескриптором, открытым для ввода. Тем не менее, похоже, что bash
ленив и не заботится, открыт ли дескриптор файла для ввода или вывода.
Итак, как 2<&1
, так и 2>&1
просто выполните системный вызов dup2(1, 2)
, который копирует дескриптор файла 1 в дескриптор файла 2.
Вы можете проверить, выполнив такую команду, так как перенаправления выполняются слева направо:
sleep 99999 1>/dev/null 2<&1
Затем в другом окне запустите lsof
в процессе sleep
. Вы увидите, что оба файловых дескриптора 1 и 2 указывают на /dev/null
. Пример (на моем Mac):
:; ps axww | grep sleep
8871 s001 R+ 0:00.01 grep sleep
8869 s003 S+ 0:00.01 sleep 99999
:; lsof -p 8869 | tail -2
sleep 8869 mayoff 1w CHR 3,2 0t0 316 /dev/null
sleep 8869 mayoff 2w CHR 3,2 0t0 316 /dev/null
Ответ 2
Рассматривая код анализатора в источнике для Bash, кажется, что 2>&1
обрабатывается так же, как 2<&1
.
parse.y
| NUMBER LESS_AND NUMBER
{
redir.dest = $3;
$$ = make_redirection ($1, r_duplicating_input, redir);
}
...
| NUMBER GREATER_AND NUMBER
{
redir.dest = $3;
$$ = make_redirection ($1, r_duplicating_output, redir);
}
Просматривая источник перенаправления redir.c
, константы r_duplicating_input
и r_duplicating_output
, похоже, обрабатываются одинаково. То же, что и в make_redirection
в make_cmd.c
.
Тестирование с помощью простой программы, которая выводит "yay" на stdout и "nay" на stderr, я могу подтвердить ваши результаты теста:
$ ./a.out > out 2>&1
$ cat out
nay
yay
$ ./a.out > out 2<&1
$ cat out
nay
yay
$ ./a.out > out 1>&2
yay
nay
$ cat out
$ ./a.out > out 1<&2
yay
nay
$ cat out
$
Ответ 3
От man bash
в разделе REDIRECTION:
Duplicating File Descriptors
The redirection operator
[n]<&word
is used to duplicate input file descriptors. If word
expands to one or more digits, the file descriptor
denoted by n is made to be a copy of that file descrip‐
tor. If the digits in word do not specify a file
descriptor open for input, a redirection error occurs.
If word evaluates to -, file descriptor n is closed. If
n is not specified, the standard input (file descriptor
0) is used.
Таким образом, в случае 2 < 1, кажется, что 2
(stderr) делается копией 1
(stdout). Я протестировал его другим способом 1<&2
, чтобы stdout являлся копией stderr.
Итак, в тестовой программе:
#!/bin/bash
echo hello 1<&2
При запуске в командной строке hello выводится на stderr not stdout
$ ./test > /dev/null
hello
$ ./test > /dev/null 2>&1
$