Что делает перенаправление «2 <& 1» в оболочке Bourne? - PullRequest
10 голосов
/ 17 февраля 2012

2>&1 редирект в оболочке 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.

Ответы [ 3 ]

6 голосов
/ 17 февраля 2012

Оператор <& дублирует дескриптор «входного» файла.Согласно IEEE Std 1003.1-2001 (так называемая 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
4 голосов
/ 18 февраля 2012

Глядя на код парсера в исходном коде 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
$
0 голосов
/ 17 февраля 2012

С man bash под НАПРАВЛЕНИЕ :

   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 </em>, кажется, что 2 (stderr ) является копией 1 ( stdout ).Я протестировал его с другой стороны: 1<&2 делает stdout копией stderr .

Итак, в тестовой программе:

#!/bin/bash
echo hello 1<&2

При запуске в командной строке привет выводится в stderr , а не stdout

$ ./test > /dev/null
hello
$ ./test > /dev/null 2>&1
$ 
...