Trong shell, ý nghĩa của 2


2284

Trong hệ vỏ Unix, nếu tôi muốn kết hợp stderrstdoutvào stdoutluồng để thao tác thêm, tôi có thể nối thêm phần sau vào cuối lệnh của mình:

2>&1

Vì vậy, nếu tôi muốn sử dụng headtrên đầu ra từ g++, tôi có thể làm một cái gì đó như thế này:

g++ lots_of_errors 2>&1 | head

vì vậy tôi chỉ có thể thấy một vài lỗi đầu tiên

Tôi luôn gặp khó khăn trong việc ghi nhớ điều này và tôi liên tục phải tìm kiếm nó, và điều đó chủ yếu là vì tôi không hiểu đầy đủ cú pháp của thủ thuật đặc biệt này.

Ai đó có thể phá vỡ điều này và giải thích nhân vật bằng nhân vật 2>&1 có nghĩa là gì?


50
@dbr Tôi không nghĩ đó chỉ là bash - Tôi tin rằng đó là một thứ vỏ bourne; do đó sh, bash, ksh, tro, dash, v.v.
súng

8
Đây là một phần của đoạn chuyển hướng mô tả các vỏ tương thích POSIX hoặc viết tắt là vỏ POSIX. ksh là một vỏ POSIX chẳng hạn. Xem: pubs.opengroup.org/onlinepub/009695399/utilities/iêng
jim mcnamara

12
Cấu trúc này cũng hoạt động trên Windows.
Vadzim

2
Nói chung là làm tốt 2>&1hơn 2> / dev / null ;-)
F. Hauri

11
Tôi nghĩ rằng tôi muốn đề cập đến đó |& là tốc ký 2>&1 |nếu bạn đang sử dụng zsh. Tôi không thể nói liệu điều đó có áp dụng cho các vỏ giống như bourne khác hay không nếu đó chỉ là tính năng zsh.
chrixian

Câu trả lời:


2557

Mô tả tệp 1 là đầu ra tiêu chuẩn ( stdout).
Mô tả tệp 2 là lỗi tiêu chuẩn (stderr ).

Đây là một cách để nhớ cấu trúc này (mặc dù nó không hoàn toàn chính xác): ban đầu, 2>1có thể trông giống như một cách tốt để chuyển hướng stderrđến stdout. Tuy nhiên, nó thực sự sẽ được hiểu là "chuyển hướng stderrđến một tệp có tên 1". &chỉ ra rằng những gì sau đây là một mô tả tập tin và không phải là một tên tệp. Vì vậy, cấu trúc trở thành : 2>&1.


281
Nhưng sau đó không nên &2>&1?
dokaspar

319
@Dominik: Không, &chỉ được hiểu là "mô tả tập tin" trong bối cảnh chuyển hướng. Viết command &2>&được phân tích cú pháp như command &2>&1, tức là "chạy commandtrong nền, sau đó chạy lệnh 2và chuyển hướng thiết bị xuất chuẩn của nó vào thiết bị xuất chuẩn".
Adam Rosenfield

15
Tại sao họ chọn những thứ phức tạp như vậy? Chỉ tò mò thôi.
Dấu phẩy

81
Nhưng làm thế nào bạn chuyển hướng stderr đến một tệp có tên '& 1'?
Martín Fixman

120
@Martin:2>'&1'

632
echo test > afile.txt

chuyển hướng stdout đến afile.txt. Điều này giống như làm

echo test 1> afile.txt

Để chuyển hướng stderr, bạn làm:

echo test 2> afile.txt

>& là cú pháp để chuyển hướng một luồng đến một bộ mô tả tệp khác - 0 là stdin, 1 là stdout và 2 là stderr.

Bạn có thể chuyển hướng thiết bị xuất chuẩn sang thiết bị xuất chuẩn bằng cách thực hiện:

echo test 1>&2 # or echo test >&2

Hoặc ngược lại:

echo test 2>&1

Vì vậy, trong ngắn hạn ... 2>chuyển hướng stderr đến một tệp (không xác định), nối thêm &1chuyển hướng stderr vào stdout.


5
điều này có ý nghĩa gì với bạn không java ... 2&1 >> data.log, tôi thấy một đồng nghiệp của mình đã làm điều này?
Thắng Phạm

5
@Harry trông giống như một cái vỏ không phải là bash, hay một lỗi đánh máy .. cmd 2>&1 >> somefile.logsẽ nối stdout / stderr vào một tệp - về cơ bản giống như trên, với phần >> filebổ sung
dbr

73
@dbr cmd 2>&1 >>filekhông chuyển hướng stderr đến tập tin, nhưng cmd >> file 2>&1không. Vấn đề đặt hàng. Trong trường hợp đầu tiên, stderr được chuyển hướng đến thiết bị xuất chuẩn của shell (có thể là tty nếu lệnh được nhập tương tác), và sau đó thiết bị xuất chuẩn được hướng đến tệp. Trong trường hợp thứ hai, thiết bị xuất chuẩn được hướng đến tệp và sau đó thiết bị xuất chuẩn được chuyển đến cùng một vị trí.
William Pursell

2
Tôi thích câu trả lời ở trên, nhưng nó có thể là một liên lạc rõ ràng hơn. "2> & 1" chuyển hướng stderr đến mục tiêu của thiết bị xuất chuẩn. Vì vậy, nếu bạn có một cái gì đó như "ls -l >> libraryContents 2> & 1" Kết quả sẽ là một tệp có tên thư mụcContents sẽ có nội dung của thư mục làm việc được gắn vào nó. Nếu có bất kỳ lỗi nào trong quá trình thực thi: các thông báo lỗi cũng sẽ được thêm vào tệp thư mụcContents, khi chúng xảy ra.
Max West

1
0(or 1,2)>&0(or 1,2)như một tùy chọn để kiểm soát đầu ra? Có echo test >test.log 2>&1giống như echo test 2>&1 >test.log?
Simin Jie

318

Một số thủ thuật về chuyển hướng

Một số đặc thù cú pháp về điều này có thể có hành vi quan trọng. Có một số mẫu ít về chuyển hướng, STDERR, STDOUT, và đối số đặt hàng .

1 - Ghi đè hoặc nối thêm?

Biểu tượng >có nghĩa là chuyển hướng .

  • >có nghĩa là gửi đến toàn bộ tệp đã hoàn thành , ghi đè mục tiêu nếu tồn tại (xem noclobbertính năng bash ở # 3 sau).
  • >>có nghĩa là gửi thêm vào sẽ nối vào mục tiêu nếu tồn tại.

Trong mọi trường hợp, tệp sẽ được tạo nếu chúng không tồn tại.

2 - Dòng lệnh shell phụ thuộc vào thứ tự !!

Để kiểm tra điều này, chúng ta cần một lệnh đơn giản sẽ gửi một cái gì đó trên cả hai đầu ra :

$ ls -ld /tmp /tnt
ls: cannot access /tnt: No such file or directory
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt 2>/dev/null
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

(Dự kiến ​​bạn không có một thư mục có tên /tnt ;). Vâng, chúng tôi có nó !!

Vì vậy, hãy xem:

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1

$ ls -ld /tmp /tnt 2>&1 >/dev/null
ls: cannot access /tnt: No such file or directory

Dòng lệnh cuối cùng đổ STDERRvào bảng điều khiển và dường như đó không phải là hành vi được mong đợi ... Nhưng ...

Nếu bạn muốn thực hiện một số lọc bài đăng về một đầu ra, đầu ra khác hoặc cả hai:

$ ls -ld /tmp /tnt | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$/<-- & --->/'

$ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->

Lưu ý rằng dòng lệnh cuối cùng trong đoạn này hoàn toàn giống như trong đoạn trước, nơi tôi đã viết dường như không phải là hành vi dự kiến (vì vậy, đây thậm chí có thể là một hành vi dự kiến).

Vâng, có một mẹo nhỏ về chuyển hướng, để thực hiện các thao tác khác nhau trên cả hai đầu ra :

$ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2  2>&1  | sed 's/^/E: /'
O: drwxrwxrwt 118 root root 196608 Jan  7 12:13 /tmp
E: ls: cannot access /tnt: No such file or directory

Nota: &9mô tả sẽ xảy ra tự phát vì) 9>&2 .

Phụ lục: không!Với phiên bản mới của( >4.0) có một tính năng mới và cú pháp gợi cảm hơn để thực hiện loại điều này:

$ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
E: ls: cannot access /tnt: No such file or directory

Và cuối cùng cho định dạng đầu ra xếp tầng như vậy:

$ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
     1  O: drwxrwxrwt 118 root root 196608 Jan  7 12:29 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

Phụ lục: không! Cùng một cú pháp mới, theo cả hai cách:

$ cat -n <(ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /'))
     1  O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

Khi STDOUTđi qua một bộ lọc cụ thể, STDERRđến một bộ lọc khác và cuối cùng cả hai đầu ra được hợp nhất sẽ đi qua bộ lọc lệnh thứ ba.

3 - Một từ về noclobbertùy chọn và >|cú pháp

Đó là về ghi đè :

Trong khi set -o noclobberhướng dẫn bash không ghi đè lên bất kỳ tệp hiện có nào, >|cú pháp cho phép bạn vượt qua giới hạn này:

$ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:15 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:19 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:21 CET 2013

Các tập tin được ghi đè mỗi lần, ngay bây giờ:

$ set -o noclobber

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

Đi qua với >|:

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:18:58 CET 2013

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:19:01 CET 2013

Bỏ cài đặt tùy chọn này và / hoặc tìm hiểu nếu đã được đặt.

$ set -o | grep noclobber
noclobber           on

$ set +o noclobber

$ set -o | grep noclobber
noclobber           off

$ date > $testfile ; cat $testfile
Mon Jan  7 13:24:27 CET 2013

$ rm $testfile

4 - Thủ thuật cuối cùng và hơn thế nữa ...

Để chuyển hướng cả hai đầu ra từ một lệnh đã cho, chúng tôi thấy rằng một cú pháp đúng có thể là:

$ ls -ld /tmp /tnt >/dev/null 2>&1

trong trường hợp đặc biệt này, có một cú pháp tắt: &>... hoặc>&

$ ls -ld /tmp /tnt &>/dev/null

$ ls -ld /tmp /tnt >&/dev/null

Nota: nếu 2>&1tồn tại, 1>&2cũng là một cú pháp đúng:

$ ls -ld /tmp /tnt 2>/dev/null 1>&2

4b- Bây giờ, tôi sẽ cho phép bạn suy nghĩ về:

$ ls -ld /tmp /tnt 2>&1 1>&2  | sed -e s/^/++/
++/bin/ls: cannot access /tnt: No such file or directory
++drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

$ ls -ld /tmp /tnt 1>&2 2>&1  | sed -e s/^/++/
/bin/ls: cannot access /tnt: No such file or directory
drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

4c- Nếu bạn quan tâm đến nhiều thông tin hơn

Bạn có thể đọc hướng dẫn sử dụng tốt bằng cách nhấn:

man -Len -Pless\ +/^REDIRECTION bash

trong một bảng điều khiển ;-)


5
Đọc thêm: Nếu bạn thích điều này, bạn có thể bảo vệ: Làm thế nào lạm dụng chuyển hướng có thể đưa ra những hành vi lạ
F. Hauri


130

Tôi tìm thấy bài viết tuyệt vời này về chuyển hướng: Tất cả về chuyển hướng

Chuyển hướng cả đầu ra tiêu chuẩn và lỗi tiêu chuẩn sang một tệp

$ lệnh &> tập tin

Lớp lót này sử dụng &>toán tử để chuyển hướng cả hai luồng đầu ra - stdout và stderr - từ lệnh sang tệp. Đây là lối tắt của Bash để nhanh chóng chuyển hướng cả hai luồng đến cùng một đích.

Đây là cách bảng mô tả tệp trông giống như sau khi Bash đã chuyển hướng cả hai luồng:

Nhập mô tả hình ảnh ở đây

Như bạn có thể thấy, cả stdout và stderr đều trỏ đến file. Vì vậy, bất cứ điều gì được viết cho thiết bị xuất chuẩn và thiết bị xuất chuẩn sẽ được ghi vào file.

Có một số cách để chuyển hướng cả hai luồng đến cùng một đích. Bạn có thể chuyển hướng từng luồng lần lượt:

$ lệnh> tệp 2> & 1

Đây là một cách phổ biến hơn nhiều để chuyển hướng cả hai luồng vào một tệp. Thiết bị xuất chuẩn đầu tiên được chuyển hướng đến tệp và sau đó thiết bị xuất chuẩn được sao chép giống như thiết bị xuất chuẩn. Vì vậy, cả hai dòng cuối cùng chỉ vào file.

Khi Bash thấy một số chuyển hướng, nó xử lý chúng từ trái sang phải. Chúng ta hãy đi qua các bước và xem điều đó xảy ra như thế nào. Trước khi chạy bất kỳ lệnh nào, bảng mô tả tệp của Bash trông như thế này:

Nhập mô tả hình ảnh ở đây

Bây giờ Bash xử lý tệp chuyển hướng> đầu tiên. Chúng tôi đã thấy điều này trước đây và nó làm cho điểm xuất sắc đến tập tin:

Nhập mô tả hình ảnh ở đây

Bash tiếp theo thấy chuyển hướng thứ hai 2> & 1. Chúng tôi chưa từng thấy sự chuyển hướng này trước đây. Cái này sao chép bộ mô tả tệp 2 thành bản sao của bộ mô tả tệp 1 và chúng tôi nhận được:

Nhập mô tả hình ảnh ở đây

Cả hai luồng đã được chuyển hướng đến tập tin.

Tuy nhiên hãy cẩn thận ở đây! Viết

lệnh> tệp 2> & 1

không giống như viết:

$ lệnh 2> & 1> tệp

Thứ tự chuyển hướng các vấn đề trong Bash! Lệnh này chỉ chuyển hướng đầu ra tiêu chuẩn vào tệp. Stderr vẫn sẽ in ra thiết bị đầu cuối. Để hiểu tại sao điều đó xảy ra, chúng ta hãy thực hiện lại các bước. Vì vậy, trước khi chạy lệnh, bảng mô tả tệp trông như thế này:

Nhập mô tả hình ảnh ở đây

Bây giờ Bash xử lý chuyển hướng từ trái sang phải. Đầu tiên nó nhìn thấy 2> & 1 vì vậy nó sao chép stderr thành stdout. Bảng mô tả tệp trở thành:

Nhập mô tả hình ảnh ở đây

Bây giờ Bash thấy chuyển hướng thứ hai >filevà nó chuyển hướng thiết bị xuất chuẩn sang tệp:

Nhập mô tả hình ảnh ở đây

Bạn có thấy những gì xảy ra ở đây? Stdout bây giờ trỏ đến tập tin, nhưng stderr vẫn trỏ đến thiết bị đầu cuối! Tất cả mọi thứ được ghi vào stderr vẫn được in ra màn hình! Vì vậy, rất, rất cẩn thận với thứ tự chuyển hướng!

Cũng lưu ý rằng trong Bash, viết

$ lệnh &> tập tin

hoàn toàn giống như:

$ lệnh> & tập tin


3
Hai cuối cùng là khác nhau nếu "lệnh" kết thúc bằng một số, khi đó được lấy làm mô tả tệp tùy chọn cho>&
MM

Bản vẽ và giải thích rất hay! Bạn có thể giải thích "trùng lặp" thực sự có nghĩa là gì? Bạn đã đề cập, "Cái này [2> & 1] sao chép bộ mô tả tệp 2 thành bản sao của bộ mô tả tệp 1". Nghe có vẻ như stderr được nhân đôi thành thiết bị xuất chuẩn. Nhưng nếu đó là trường hợp, tôi cũng nên nhìn thấy lỗi /dev/tty0?
HCSF

87

Các số tham chiếu đến các mô tả tập tin (fd).

  • Không là stdin
  • Một là stdout
  • Hai là stderr

2>&1 chuyển hướng fd 2 đến 1.

Điều này hoạt động cho bất kỳ số lượng mô tả tập tin nếu chương trình sử dụng chúng.

Bạn có thể nhìn vào /usr/include/unistd.hnếu bạn quên chúng:

/* Standard file descriptors.  */
#define STDIN_FILENO    0   /* Standard input.  */
#define STDOUT_FILENO   1   /* Standard output.  */
#define STDERR_FILENO   2   /* Standard error output.  */

Điều đó nói rằng tôi đã viết các công cụ C sử dụng các mô tả tệp không chuẩn để ghi nhật ký tùy chỉnh để bạn không nhìn thấy nó trừ khi bạn chuyển hướng nó đến một tệp hoặc một cái gì đó.


58

Cấu trúc đó gửi luồng lỗi tiêu chuẩn ( stderr) đến vị trí hiện tại của đầu ra tiêu chuẩn ( stdout) - vấn đề tiền tệ này dường như đã bị bỏ qua bởi các câu trả lời khác.

Bạn có thể chuyển hướng bất kỳ xử lý đầu ra nào sang phương thức khác bằng cách sử dụng phương pháp này nhưng nó thường được sử dụng để chuyển kênh stdoutvà truyền stderrphát thành một luồng duy nhất để xử lý.

Một số ví dụ:

# Look for ERROR string in both stdout and stderr.
foo 2>&1 | grep ERROR

# Run the less pager without stderr screwing up the output.
foo 2>&1 | less

# Send stdout/err to file (with append) and terminal.
foo 2>&1 |tee /dev/tty >>outfile

# Send stderr to normal location and stdout to file.
foo >outfile1 2>&1 >outfile2

Lưu ý rằng cái cuối cùng sẽ không trực tiếp stderrđến outfile2- nó chuyển hướng nó đến cái stdoutđã xảy ra khi đối số gặp phải ( outfile1) và sau đó chuyển hướng stdoutđến outfile2.

Điều này cho phép một số mánh khóe khá tinh vi.


5
Mặc dù ví dụ cuối cùng đó sẽ rõ ràng hơn nhiều như: foo> outfile2 2> outfile1
Michael Cramer

3
Rõ ràng hơn, vâng, nhưng điều đó sẽ không thể hiện bản chất "vị trí" của chuyển hướng. Ví dụ được đặt ra vì thường không hữu ích khi thực hiện điều này trong một dòng duy nhất - phương pháp trở nên thực sự hữu ích khi các bên khác nhau chịu trách nhiệm cho các phần khác nhau của chuyển hướng. Ví dụ, khi một tập lệnh thực hiện một bit chuyển hướng và bạn chạy nó với một bit khác.
paxdiablo

5
Tôi chỉ nhận ra rằng ví dụ cuối cùng cũng giải quyết được một sự nhầm lẫn lâu dài mà tôi có về lý do tại sao điều này: some_program 2>&1 > /dev/nullkhông hoạt động như thế này : some_program > /dev/null 2>&1.
snapfractalpop

Nhận xét của bạn về ví dụ cuối cùng đáng giá bằng các chữ cái bằng vàng :-) Tôi chưa bao giờ nghĩ rằng những lập luận chuyển hướng này là vị trí ... Tôi nghĩ rằng điều này khá quan trọng để biết.
Nils-o-mat

20

2>&1là một cấu trúc vỏ POSIX. Đây là một sự cố, mã thông báo bằng mã thông báo:


2: " Lỗi tiêu chuẩn " mô tả tập tin đầu ra.

>&: Sao chép toán tử Mô tả tệp đầu ra (một biến thể của toán tử Chuyển hướng đầu ra> ). Cho trước [x]>&[y], bộ mô tả tệp được biểu thị bởi xđược tạo thành một bản sao của bộ mô tả tệp đầu ra y.

1" Chuẩn đầu ra " tập tin đầu ra mô tả.

Biểu thức 2>&1sao chép mô tả tệp 1vào vị trí 2, do đó, bất kỳ đầu ra nào được ghi vào 2("lỗi tiêu chuẩn") trong môi trường thực thi sẽ chuyển đến cùng một tệp được mô tả ban đầu bởi 1("đầu ra tiêu chuẩn").


Giải thích thêm:

Bộ mô tả tệp : "Một số nguyên duy nhất, không âm cho mỗi quá trình được sử dụng để xác định một tệp đang mở cho mục đích truy cập tệp."

Đầu ra / lỗi tiêu chuẩn : Tham khảo ghi chú sau trong phần Chuyển hướng của tài liệu shell:

Các tệp đang mở được biểu thị bằng số thập phân bắt đầu bằng 0. Giá trị lớn nhất có thể được xác định theo thực hiện; tuy nhiên, tất cả các triển khai sẽ hỗ trợ ít nhất 0 đến 9, bao gồm, để ứng dụng sử dụng. Những con số này được gọi là "mô tả tập tin". Các giá trị 0, 1 và 2 có ý nghĩa đặc biệt và cách sử dụng thông thường và được ngụ ý bởi các hoạt động chuyển hướng nhất định; chúng được gọi là đầu vào tiêu chuẩn, đầu ra tiêu chuẩn và lỗi tiêu chuẩn, tương ứng. Các chương trình thường lấy đầu vào của chúng từ đầu vào tiêu chuẩn và viết đầu ra trên đầu ra tiêu chuẩn. Thông báo lỗi thường được viết trên lỗi tiêu chuẩn. Các toán tử chuyển hướng có thể được đi trước bởi một hoặc nhiều chữ số (không cho phép các ký tự can thiệp) để chỉ định số mô tả tệp.


19

2 là lỗi tiêu chuẩn giao diện điều khiển.

1 là đầu ra tiêu chuẩn giao diện điều khiển.

Đây là Unix tiêu chuẩn và Windows cũng tuân theo POSIX.

Ví dụ khi bạn chạy

perl test.pl 2>&1

lỗi tiêu chuẩn được chuyển hướng đến đầu ra tiêu chuẩn, do đó bạn có thể thấy cả hai đầu ra cùng nhau:

perl test.pl > debug.log 2>&1

Sau khi thực hiện, bạn có thể thấy tất cả đầu ra, bao gồm cả lỗi, trong debug.log.

perl test.pl 1>out.log 2>err.log

Sau đó, đầu ra tiêu chuẩn đi ra out.log và lỗi tiêu chuẩn thành err.log.

Tôi đề nghị bạn cố gắng để hiểu những điều này.


Mẫu thứ hai sai: vì ưu tiên thứ tự STDERR được chuyển hướng đến STDOUT , chỉ STDOUT mặc định sẽ được ghi vào debug.log (không phải STDERR ) xem câu trả lời của tôi (đoạn # 2)! Để đảm bảo cả hai được chuyển hướng đến cùng một tệp, bạn phải đảo ngược các chỉ thị chuyển hướng:perl test.pl > debug.log 2>&1
F. Hauri

16

Để trả lời câu hỏi của bạn: Phải mất bất kỳ đầu ra lỗi nào (thường được gửi đến stderr) và ghi nó vào đầu ra tiêu chuẩn (stdout).

Điều này hữu ích với, ví dụ 'thêm' khi bạn cần phân trang cho tất cả đầu ra. Một số chương trình như in thông tin sử dụng vào stderr.

Để giúp bạn nhớ

  • 1 = đầu ra tiêu chuẩn (nơi các chương trình in đầu ra bình thường)
  • 2 = lỗi tiêu chuẩn (lỗi in chương trình)

"2> & 1" chỉ đơn giản là chỉ mọi thứ được gửi tới thiết bị xuất chuẩn, thay vào đó là thiết bị xuất chuẩn.

Tôi cũng khuyên bạn nên đọc bài viết này về chuyển hướng lỗi trong đó chủ đề này được đề cập đầy đủ chi tiết.


11

Từ quan điểm của một lập trình viên, nó có nghĩa chính xác như sau:

dup2(1, 2);

Xem trang người đàn ông .

Hiểu rằng đó 2>&1là một bản sao cũng giải thích tại sao ...

command >file 2>&1

... không giống như ...

command 2>&1 >file

Đầu tiên sẽ gửi cả hai luồng đến file, trong khi luồng thứ hai sẽ gửi lỗi đến stdoutvà đầu ra thông thường vào file.


9

Tôi thấy điều này rất hữu ích nếu bạn là người mới bắt đầu đọc

Cập nhật:
Trong Hệ thống Linux hoặc Unix, có hai vị trí chương trình gửi đầu ra tới: Đầu ra tiêu chuẩn (thiết bị xuất chuẩn) và Lỗi tiêu chuẩn (stderr) . Bạn có thể chuyển hướng các đầu ra này sang bất kỳ tệp nào.

Giống như nếu bạn làm điều này

ls -a > output.txt

Không có gì sẽ được in trong bảng điều khiển, tất cả đầu ra (thiết bị xuất chuẩn) được chuyển hướng đến tệp đầu ra.

Và nếu bạn thử in nội dung của bất kỳ tệp nào không thoát có nghĩa là đầu ra sẽ là một lỗi như nếu bạn in test.txt không có trong thư mục hiện tại

cat test.txt > error.txt

Đầu ra sẽ là

cat: test.txt :No such file or directory

Nhưng tệp error.txt sẽ trống vì chúng tôi chuyển hướng thiết bị xuất chuẩn sang tệp không phải thiết bị lỗi chuẩn.

vì vậy chúng ta cần bộ mô tả tệp (Bộ mô tả tệp không phải là số nguyên dương đại diện cho tệp đang mở. Bạn có thể nói bộ mô tả là id duy nhất của tệp) để báo cho shell biết loại đầu ra nào chúng ta đang gửi tới tệp. Trong hệ thống Unix / Linux 1 là cho thiết bị xuất chuẩn và 2 cho thiết bị xuất chuẩn .

vì vậy bây giờ nếu bạn làm điều này

ls -a 1> output.txtcó nghĩa là bạn đang gửi đầu ra tiêu chuẩn (thiết bị xuất chuẩn) đến output.txt.

và nếu bạn làm điều này

cat test.txt 2> error.txtcó nghĩa là bạn đang gửi Lỗi tiêu chuẩn (stderr) đến error.txt.

&1được sử dụng để tham chiếu giá trị của bộ mô tả tệp 1 (stdout).

Bây giờ đến thời điểm đó 2>&1có nghĩa là Chuyển hướng stderr đến cùng địa điểm mà chúng ta đang chuyển hướng stdout

Bây giờ bạn có thể làm điều này

cat maybefile.txt > output.txt 2>&1

cả đầu ra tiêu chuẩn (thiết bị xuất chuẩn) và Lỗi tiêu chuẩn (thiết bị xuất chuẩn) sẽ được chuyển hướng đến output.txt.

Cảm ơn Ondrej K. đã chỉ ra


1
Liên kết chỉ có câu trả lời là có vấn đề. Liên kết có thể trở thành không còn tồn tại khiến câu trả lời vô dụng. Bạn phải luôn luôn bao gồm đủ chi tiết trong câu trả lời.
Ondrej K.

7

Mọi người, luôn nhớ gợi ý của paxdiablo về vị trí hiện tại của mục tiêu chuyển hướng ... Điều đó rất quan trọng.

Bản ghi nhớ cá nhân của tôi cho 2>&1nhà điều hành là thế này:

  • Hãy nghĩ về &ý nghĩa 'and'hoặc 'add'(nhân vật là một ampers - , phải không?)
  • Vì vậy, nó trở thành: 'redirect 2(stderr) đến nơi 1(stdout) đã / hiện tại và thêm cả hai luồng' .

Cũng hoạt động ghi nhớ tương tự cho chuyển hướng thường được sử dụng khác , 1>&2:

  • Hãy nghĩ về &ý nghĩa andhoặc add... (bạn hiểu ý tưởng về ký hiệu, vâng?)
  • Vì vậy, nó trở thành: 'redirect 1(stdout) đến nơi 2(stderr) đã / hiện tại và thêm cả hai luồng' .

Và luôn luôn nhớ: bạn phải đọc các chuỗi chuyển hướng 'từ cuối', từ phải sang trái ( không phải từ trái sang phải).


7

Chuyển hướng đầu vào

Chuyển hướng đầu vào làm cho tệp có kết quả tên từ việc mở rộng từ được mở để đọc trên mô tả tệp n hoặc đầu vào tiêu chuẩn (mô tả tệp 0) nếu n không được chỉ định.

Định dạng chung để chuyển hướng đầu vào là:

[n]<word

Chuyển hướng đầu ra

Chuyển hướng đầu ra làm cho tệp có kết quả tên từ việc mở rộng từ được mở để ghi trên mô tả tệp n hoặc đầu ra tiêu chuẩn (mô tả tệp 1) nếu n không được chỉ định. Nếu tập tin không tồn tại, nó được tạo ra; nếu nó tồn tại, nó bị cắt cụt về kích thước không.

Định dạng chung để chuyển hướng đầu ra là:

[n]>word

Di chuyển mô tả tập tin

Toán tử chuyển hướng,

[n]<&digit-

di chuyển chữ số mô tả tệp sang mô tả tệp n hoặc đầu vào tiêu chuẩn (mô tả tệp 0) nếu n không được chỉ định. chữ số được đóng lại sau khi được nhân đôi thành n.

Tương tự, toán tử chuyển hướng

[n]>&digit-

di chuyển chữ số mô tả tệp sang mô tả tệp n hoặc đầu ra tiêu chuẩn (mô tả tệp 1) nếu n không được chỉ định.

Tham chiếu:

man bash

Nhập /^REDIRECTđể xác định vị trí redirectionvà tìm hiểu thêm ...

Một phiên bản trực tuyến có tại đây: 3.6 Chuyển hướng

Tái bút

Rất nhiều thời gian, manlà công cụ mạnh mẽ để học Linux.


6

Với điều kiện là /fookhông tồn tại trên hệ thống của bạn và /tmpkhông

$ ls -l /tmp /foo

sẽ in nội dung /tmpvà in thông báo lỗi cho/foo

$ ls -l /tmp /foo > /dev/null

sẽ gửi nội dung /tmpđến /dev/nullvà in thông báo lỗi cho/foo

$ ls -l /tmp /foo 1> /dev/null

sẽ làm chính xác như vậy (lưu ý 1 )

$ ls -l /tmp /foo 2> /dev/null

sẽ in nội dung /tmpvà gửi thông báo lỗi tới/dev/null

$ ls -l /tmp /foo 1> /dev/null 2> /dev/null

sẽ gửi cả danh sách cũng như thông báo lỗi tới /dev/null

$ ls -l /tmp /foo > /dev/null 2> &1

là tốc ký


5

Điều này giống như chuyển lỗi đến thiết bị xuất chuẩn hoặc thiết bị đầu cuối.

Đó là, cmdkhông phải là một lệnh:

$cmd 2>filename
cat filename

command not found

Lỗi được gửi đến tập tin như thế này:

2>&1

Lỗi tiêu chuẩn được gửi đến thiết bị đầu cuối.


1

0 cho đầu vào, 1 cho thiết bị xuất chuẩn và 2 cho thiết bị xuất chuẩn.

Một lời khuyên : somecmd >1.txt 2>&1là chính xác, trong khi somecmd 2>&1 >1.txthoàn toàn sai mà không có hiệu lực!


1

unix_commands 2>&1

Điều này được sử dụng để in lỗi đến thiết bị đầu cuối.

Dưới đây minh họa quá trình

  • Khi lỗi được tạo ra, chúng được ghi vào &2"bộ đệm" địa chỉ bộ nhớ lỗi tiêu chuẩn , từ đó 2tham chiếu luồng lỗi tiêu chuẩn .
  • Khi đầu ra được tạo ra, nó được ghi vào &1"bộ đệm" địa chỉ bộ nhớ đầu ra tiêu chuẩn , từ đó 1tham chiếu luồng đầu ra tiêu chuẩn .

Vì vậy, lấy unix_commandsluồng lỗi tiêu chuẩn 2và chuyển hướng >luồng (lỗi) đến địa chỉ bộ nhớ đầu ra tiêu chuẩn &1, để chúng sẽ được truyền đến thiết bị đầu cuối và được in.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.