2012-02-17 18 views
10

2>&1 chuyển hướng trong Bourne shell lấy đầu ra được gửi đến một bộ mô tả tập tin 2 (theo mặc định, lỗi chuẩn) và gửi nó thay cho tệp mô tả 1 (theo mặc định là đầu ra tiêu chuẩn).Chuyển hướng "2 <& 1" làm gì trong trình bao Bourne?

Nhưng chuyển hướng 2<&1 làm gì?

Nó có gửi stderr đến stdin không?

Lý thuyết của tôi là nó được gửi stdin để stderr (ví dụ tương tự như 1>&2) nhưng thực nghiệm, đó là không phải như vậy:

$ 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 

Lưu ý rằng tiêu chuẩn ra khỏi VÀ sai số chuẩn cả hai đi đến nộp OUT3 nơi stdout đã được chuyển hướng.

+0

Là một lưu ý - đây là một (phải) lỗi một đồng nhân viên đưa vào khi anh ta sử dụng sai '<' thay vì '>'. Tôi chỉ cố gắng không hiểu chính xác những gì Shell đang làm với nó. Cho đến nay, nó SEEMS như thể nó giống như '2> & 1' – DVK

+0

' bash --version'? –

+0

@ user112358132134 - 'GNU bash, phiên bản 2.03.0 (1) -release (sparc-sun-solaris2.5.1)' – DVK

Trả lời

6

Nhà điều hành <& bản sao một “đầu vào "Mô tả tập tin. Theo IEEE Std 1003.1-2001 (còn gọi là Đặc điểm kỹ thuật Unix đơn v3, kế thừa cho POSIX), nó được cho là lỗi khi nói 2<&1 nếu 1 không phải là một bộ mô tả tập tin mở cho đầu vào. Tuy nhiên, nó xuất hiện rằng bash là lười biếng và không quan tâm nếu bộ mô tả tập tin được mở cho đầu vào hoặc đầu ra.

Vì vậy, cả hai 2<&12>&1 chỉ đơn giản là thực hiện các cuộc gọi hệ thống dup2(1, 2), mà các bản sao tập tin mô tả từ 1 tới tập tin mô tả 2.

Bạn có thể kiểm tra bằng cách chạy lệnh như thế này, kể từ khi chuyển hướng được thực hiện từ trái sang phải:

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

Sau đó, trong cửa sổ khác, chạy lsof trên quy trình sleep. Bạn sẽ thấy rằng cả hai mô tả tập tin 1 và 2 trỏ đến /dev/null. Ví dụ (trên máy Mac của tôi):

:; 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 
+0

Vì vậy, bạn đang nói '2 <& 1' là ** có hiệu quả ** tương đương với' 2> & 1' trong Bash (đặc biệt là đối với lệnh không đọc từ STDIN), ngay cả khi về mặt lý thuyết thì không nên, đúng không? – DVK

+0

Không hoàn toàn. '2 <& 1' tương đương với' 1> & 2'. –

+0

xin lỗi, điều đó dường như không phù hợp với thử nghiệm của tôi (xem câu hỏi). ERR đã được chuyển hướng đến OUT, dường như, không ngược lại – DVK

0

Từ man bash dưới 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. 

Vì vậy, trong trường hợp của , có vẻ như 2 (stderr) được thực hiện cho được một bản sao của 1 (stdout). Tôi đã thử nghiệm nó theo cách khác xung quanh 1<&2 làm cho stdout là bản sao của stderr.

Vì vậy, trong một chương trình thử nghiệm:

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

Khi chạy trên dòng lệnh, chào là đầu ra cho stderr không stdout

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

Thử nghiệm của bạn đã kiểm tra chuyển hướng sai. Tôi biết những gì 2> & 1 không - xin vui lòng đọc câu hỏi cẩn thận – DVK

+0

Bài kiểm tra trong câu trả lời của tôi là cho 1 <& 2 trong chương trình thử nghiệm, 2> & 1 chỉ đảm bảo rằng 1 <& 2 đã thực sự trùng lặp stderr – vmpstr

4

Nhìn vào các mã phân tích cú pháp trong nguồn cho Bash, có vẻ như 2>&1 được xử lý trong cùng một cách như 2<&1.

phân tích cú pháp.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); 
     } 

Nhìn qua các nguồn chuyển hướng redir.c, các hằng số r_duplicating_inputr_duplicating_output dường như được đối xử theo cách tương tự. Tương tự như chức năng make_redirection trong make_cmd.c.

kiểm tra với một chương trình đơn giản mà in "yay" để stdout và "nay" để stderr, tôi có thể khẳng định kết quả xét nghiệm của bạn:

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

+1, câu trả lời tuyệt vời – DVK