问题
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