What does “2<&1” redirect do in Bourne shell?

柔情痞子 提交于 2019-12-23 07:28:37

问题


2>&1 redirect in Bourne shell takes the output sent to a file descriptor 2 (by default, standard error) and sends it instead to file descriptor 1 (by default a standard output).

But what does 2<&1 redirect do?

Does it send stderr to stdin?

My theory was that it was sending stdin to stderr (e.g. same as 1>&2) but experimentally, that is NOT the case:

$ 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

Note that standard out AND standard error both went to file out3 where stdout was redirected.


回答1:


The <& operator duplicates an “input” file descriptor. According to IEEE Std 1003.1-2001 (aka Single Unix Specification v3, the successor to POSIX), it's supposed to be an error to say 2<&1 if 1 is not a file descriptor open for input. However, it appears that bash is lazy and doesn't care if the file descriptor is open for input or for output.

So both 2<&1 and 2>&1 simply perform the system call dup2(1, 2), which copies file descriptor 1 to file descriptor 2.

You can check by running a command like this, since redirections are performed left-to-right:

sleep 99999 1>/dev/null 2<&1

Then in another window, run lsof on the sleep process. You'll see that both file descriptors 1 and 2 point to /dev/null. Example (on my 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:


Looking at the parser code in the source for Bash, it seems that 2>&1 is treated in the same way as 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);
        }

Looking through the redirection source redir.c, the constants r_duplicating_input and r_duplicating_output seem to be treated in the same way. Same as in the make_redirection function in make_cmd.c.

Testing with a simple program that prints "yay" to stdout and "nay" to stderr, I can confirm your test results:

$ ./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:


From man bash under 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.

So in the case of 2<&1, it seems that 2 (stderr) is made to be a copy of 1 (stdout). I've tested it with the other way around 1<&2 makes stdout to be a copy of stderr.

So in a test program:

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

When run on command line, hello is output to stderr not stdout

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


来源:https://stackoverflow.com/questions/9334315/what-does-21-redirect-do-in-bourne-shell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!