Làm thế nào để ống stderr mà không có thiết bị xuất chuẩn


24

Làm cách nào để tôi xử lý luồng lỗi tiêu chuẩn mà không dẫn luồng ra ngoài tiêu chuẩn?

Tôi biết lệnh này hoạt động, nhưng nó cũng viết tiêu chuẩn ra.

Command 2>&1 | tee -a $LOG

Làm thế nào để tôi chỉ nhận được lỗi tiêu chuẩn?

Lưu ý: Những gì tôi muốn từ điều này là chỉ cần viết luồng stderr vào một bản ghi và viết cả stderr và stdout vào bảng điều khiển.

Câu trả lời:


26

Để làm điều đó, hãy sử dụng một mô tả tệp bổ sung để chuyển stderr và stdout:

find /var/log 3>&1 1>&2 2>&3 | tee foo.file

Về cơ bản, nó hoạt động, hoặc ít nhất tôi nghĩ rằng nó hoạt động, như sau:
Các hướng dẫn lại được đánh giá từ trái sang phải.

3>&1 Tạo một bộ mô tả tệp mới, 3 bản sao (bản sao) của fd 1 (thiết bị xuất chuẩn).

1>&2 Biến stdout (1) thành bản sao của fd 2 (stderr)

2>&3 Tạo fd 2, một bản sao (bản sao) của 3, trước đây đã được tạo thành một bản sao của thiết bị xuất chuẩn.

Vì vậy, bây giờ stderr và stdout được chuyển đổi.

| tee foo.file tee trùng lặp mô tả tập tin 1 đã được thực hiện thành stderr.


Ồ, không được thử nghiệm với ksh, hoạt động với bash mặc dù ...
Kyle Brandt

Cảm ơn, làm việc trong ksh quá. Tôi nghĩ rằng hầu hết các thứ ống và luồng là tiêu chuẩn posix.
C. Ross

"Sao chép" không thực sự chính xác - Xem Câu trả lời của @ Guasqueño.
Kyle Brandt

Điều này cũng hoạt động trong Windows với tee.execài đặt :)
Acorn

13

Lệnh Unix / Linux của Kyle thực hiện công việc chuyển đổi STDERR bằng STDOUT; tuy nhiên lời giải thích không hoàn toàn đúng. Các toán tử chuyển hướng không thực hiện bất kỳ sao chép hoặc sao chép nào, chúng chỉ chuyển hướng luồng sang một hướng khác.

Viết lại lệnh của Kyle bằng cách tạm thời di chuyển 3> & 1 đến cuối, sẽ giúp dễ hiểu khái niệm hơn:

find /var/log  1>&2  2>&3  3>&1  

Được viết theo cách này, Linux sẽ hiển thị lỗi vì & 3 chưa tồn tại vì nó nằm trước 3> & 1. 3> một cái gì đó là một cách để tuyên bố (xác định) rằng chúng ta sẽ sử dụng một ống thứ ba, vì vậy nó phải được đặt trước khi chúng ta chảy nước vào ống đó, ví dụ như cách Kyle viết. Hãy thử cách này chỉ để cho vui:

((echo "STD1";  anyerror "bbbb"; echo "STD2" ) 3>&1 4>&2 1>&4 2>&3) > newSTDOUT 2> newSTDERR

Không có cách để làm bản sao là một sự xấu hổ. Bạn không thể thực hiện những việc như "3> & 1 3> & 2" trong cùng một lệnh, bởi vì Linux sẽ chỉ sử dụng cái đầu tiên được tìm thấy và loại bỏ cái thứ hai.

Tôi chưa (chưa) tìm ra cách gửi cả lỗi và đầu ra thông thường vào một tệp và cũng gửi một bản sao lỗi đến đầu ra độc lập bằng một lệnh. Đối với instace, tôi có một công việc định kỳ mà tôi muốn cả hai kết quả đầu ra (lỗi và tiêu chuẩn) đi đến một tệp nhật ký và để lỗi cũng xuất hiện để tạo một thông điệp email được gửi tới blackjack của tôi. Tôi có thể làm điều đó với hai lệnh bằng cách sử dụng "tee" nhưng lỗi không hiển thị theo đúng thứ tự giữa các dòng đầu ra thông thường trong tệp. Đây là cách xấu xí mà tôi đã giải quyết vấn đề:

((echo "STD1"; sdfr "bbbb"; echo "STD2" ) 3>&1 1>&2 2>&3 | tee -a log1 ) 2>> log1

Lưu ý rằng tôi phải sử dụng log1 hai lần và tôi phải nối thêm trong cả hai trường hợp, một trong số đó sử dụng tùy chọn "-a" cho lệnh "tee" và lần thứ hai sử dụng ">>".

Làm một con mèo log1 bạn nhận được như sau:

STD1
STD2
-bash: sdfr: command not found

Lưu ý rằng lỗi không hiển thị trong dòng thứ hai như bình thường.


Sửa chữa tuyệt vời !
Kyle Brandt

Kiểm tra zsh và mult_iostùy chọn (theo mặc định) để có thể chuyển hướng FD nhiều lần.
Tom Hale

2

Theo trang man cho ksh (pdksh), bạn chỉ có thể làm:

Lệnh 2> & 1> / dev / null | mèo -n

tức là dup stderr sang stdout, chuyển hướng stdout sang / dev / null, sau đó chuyển thành 'cat -n'

hoạt động trên pdksh trên hệ thống của tôi:

$ errorecho () {echo "$ @"> & 2;}

$ errorecho foo
foo

$ errorecho foo> / dev / null # vẫn sẽ hiển thị ngay cả khi chuyển hướng xuất chuẩn
foo

$ errorecho foo 2> & 1> / dev / null | mèo -n
     1 foo
$   

Hoạt động với BusyBox cũng vậy
Udo G

1

tôi đã nhận được nó chạy như bạn muốn vì tôi cũng cần nó và tinh chỉnh lệnh của bạn. Bây giờ đối với tôi nó hoạt động chính xác bằng cách sử dụng bash 3.2 trên debian bóp bằng cách này

(echo "foo" 3>&1 1>&2 2>&3 | tee -a log1 ) 2>> log1 >> log2

trong khi log1 log stdout và stderr và log2 chỉ ghi nhật ký stderr và không có gì khác được đưa vào màn hình.

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.