Với bash, làm thế nào tôi có thể chuyển lỗi tiêu chuẩn sang một quy trình khác?


137

Người ta đã biết làm thế nào để chuyển thông số tiêu chuẩn của một quy trình sang một quy trình đầu vào tiêu chuẩn khác:

proc1 | proc2

Nhưng nếu tôi muốn gửi lỗi tiêu chuẩn của Proc1 đến Proc2 và để đầu ra tiêu chuẩn đi đến vị trí hiện tại thì sao? Bạn sẽ nghĩ rằng bashsẽ có một lệnh dọc theo dòng:

proc1 2| proc2

Nhưng, than ôi, không. Có cách nào để làm điều này?


Bạn có thể thực hiện một chuyển hướng đơn giản như vậy rc, đó là một vỏ khác. Vd : proc1 |[2] proc2. Nó không đẹp sao? Không phải bashmặc dù.
Rolf

Câu trả lời:


168

Ngoài ra còn có quá trình thay thế . Mà làm cho một quá trình thay thế cho một tập tin.
Bạn có thể gửi stderrđến một tập tin như sau:

process1 2> file

Nhưng bạn có thể thay thế một quy trình cho tệp như sau:

process1 2> >(process2)

Dưới đây là một ví dụ cụ thể gửi stderrđến cả màn hình và nối vào logfile

sh myscript 2> >(tee -a errlog)

23
Điều này trả lời đúng câu hỏi đã nêu và phải là câu trả lời được chấp nhận bởi @paxdiablo
mmlb

Tôi đã thử điều này. Nó không hoạt động ( weston --help 2> >(less)) và nó đã phá vỡ vỏ của tôi, tôi phải thoát ra và đăng nhập lại.
Rolf

1
@Rolf nếu cả hai weston --helplessđang mong đợi có tương tác bàn phím nhưng chỉ có 1 trong số họ nhận được nó, thì bạn có thể rơi vào tình huống khó xử. Hãy thử làm thử nghiệm với một cái gì đó như grepthay thế. Ngoài ra, bạn có thể thấy rằng cả hai đầu vào chuột / bàn phím sẽ chuyển sang lệnh thứ 2 chứ không phải là về phía tây.
BeowulfNode42

88

Bạn có thể sử dụng thủ thuật sau để trao đổi stdoutstderr. Sau đó, bạn chỉ cần sử dụng các chức năng đường ống thông thường.

( proc1 3>&1 1>&2- 2>&3- ) | proc2

Được cung cấp stdoutstderrcả hai chỉ đến cùng một vị trí khi bắt đầu, điều này sẽ cung cấp cho bạn những gì bạn cần.

Những gì x>ybit làm là thay đổi xử lý tệp xđể bây giờ nó gửi thông tin của nó đến nơi xử lý tệp yhiện tại. Đối với trường hợp cụ thể của chúng tôi:

  • 3>&1tạo một tay cầm mới3 sẽ xuất ra tay cầm hiện tại1 (thiết bị xuất chuẩn gốc), chỉ để lưu nó ở đâu đó cho điểm đạn cuối cùng bên dưới.
  • 1>&2sửa đổi tay cầm 1(stdout) để xuất ra tay cầm hiện tại2 (stderr gốc).
  • 2>&3-sửa đổi tay cầm 2(stderr) để xuất ra tay cầm hiện tại3 (thiết bị xuất chuẩn gốc) sau đó đóng tay cầm 3(thông qua -ở cuối).

Đó thực sự là lệnh hoán đổi mà bạn thấy trong các thuật toán sắp xếp:

temp   = value1;
value1 = value2;
value2 = temp;

3
Giá trị của việc sử dụng 1>&2-ở đây thay vì chỉ là 1>&2gì? Tôi không hiểu tại sao chúng tôi muốn đóng fd 2, nếu chúng tôi sẽ mở lại / gán lại nó ngay lập tức.
dubiousjim

1
@dubiousjim, không có lợi thế trong trường hợp cụ thể đó, tôi nghi ngờ tôi đã làm điều đó chỉ để nhất quán - đóng tệp xử lý 3 là một ý tưởng tốt để giải phóng nó.
paxdiablo

Điểm hay, @ovgolovin, tôi không thể tin rằng không ai nhặt được nó trong bảy tháng kể từ khi tôi thực hiện chỉnh sửa đó. Đã sửa theo đề xuất của bạn.
paxdiablo

đang cố gắng để gcc's make (được tô màu trên hệ thống của tôi) để hoạt động với điều này "(tạo 3> & 1 1> & 2- 2> & 3-) | less -R" trong khi "(ls -al 3> & 1 1> & 2- 2> & 3-) | less -R "hoạt động như mong đợi.
không đồng bộ

Có vẻ như lời giải thích của bạn đã trở lại phía trước cho hai lần chuyển hướng thứ hai. 1> & 2- bộ xử lý tệp 2 (stderr gốc) để xử lý 1 (stdout gốc) 2> & 3- bộ xử lý tệp 3 (stdout sao chép) để xử lý 2 (stderr gốc). Xin hãy sửa tôi nếu tôi sai. btw, tôi đoán rằng dấu gạch ngang trên 2 là để ngăn dữ liệu stderr mới được gửi đến bộ đệm này trong khi nó đang được điền với dữ liệu từ thiết bị xuất chuẩn.
aghsmith

70

Bash 4 có tính năng này:

Nếu `| & 'được sử dụng, lỗi tiêu chuẩn của lệnh1 được kết nối với đầu vào tiêu chuẩn của lệnh2 thông qua đường ống; nó là viết tắt cho 2> & 1 |. Chuyển hướng ngầm định này của lỗi tiêu chuẩn được thực hiện sau bất kỳ chuyển hướng nào được chỉ định bởi lệnh.

zsh cũng có tính năng này.

-

Với các shell khác / cũ hơn, chỉ cần nhập rõ ràng như

Đầu tiên 2> & 1 | Khác


14
Từ việc đọc các tài liệu, đó là cả lỗi tiêu chuẩn đầu ra trái ngược với chỉ stderr, nhưng thật tuyệt khi biết điều đó. Thời gian để bắt đầu nhìn vào bash 4, tôi nghĩ.
paxdiablo

Hướng dẫn bash hiện tại ghi "Nếu | & được sử dụng, lỗi tiêu chuẩn của lệnh, ngoài đầu ra tiêu chuẩn của nó, được kết nối với đầu vào tiêu chuẩn của lệnh2". Đây rõ ràng không phải là những gì OP muốn.
Peter - Tái lập Monica

@ PeterA.Schneider: OP nói "để đầu ra tiêu chuẩn đi đến vị trí hiện tại" có thể không rõ ràng.
Tạm dừng cho đến khi có thông báo mới.

Tôi không thấy bất kỳ sự mơ hồ nào. Đề xuất của bạn (1) kết hợp hai luồng. (2) OtherCommandghi dữ liệu kết hợp ở đâu đó, có thể ở nơi khác. Vì vậy, nó không phải là cùng một dữ liệu và nó có khả năng đi đến một nơi khác. Điều đó trái ngược với mong muốn của OP, phải không?
Peter - Tái lập Monica

@ PeterA.Schneider: Nơi nào khác là vị trí hiện tại của đầu ra tiêu chuẩn? Nếu proc1kết quả đầu ra cho thiết bị xuất chuẩn và thiết bị xuất chuẩn và bạn muốn thiết bị xuất chuẩn đi đến stdin của proc2(đó là nơi thiết bị xuất chuẩn của Proc1), thì câu trả lời của tôi sẽ thực hiện được điều đó. Tôi đã đưa cho OP những gì anh ấy yêu cầu , có lẽ không phải là những gì anh ấy muốn hỏi. Trong đó nằm ở sự mơ hồ tiềm năng. OP đã chấp nhận câu trả lời trong đó hoán đổi thiết bị xuất chuẩn và thiết bị xuất chuẩn không phải là thứ anh ta yêu cầu.
Tạm dừng cho đến khi có thông báo mới.

27

Trao đổi là tuyệt vời vì nó giải quyết vấn đề. Chỉ trong trường hợp bạn thậm chí không cần thiết bị xuất chuẩn ban đầu, bạn có thể làm theo cách này:

proc1 2>&1 1>/dev/null | proc2

Trật tự là quan trọng; bạn sẽ không muốn:

proc1 >/dev/null 2>&1 | proc1

Vì điều này sẽ chuyển hướng mọi thứ đến /dev/null!


0

Không ai trong số này thực sự làm việc rất tốt. Cách tốt nhất tôi tìm thấy để làm những gì bạn muốn là:

(command < input > output) 2>&1 | less

Điều này chỉ hoạt động cho các trường hợp commandkhông cần nhập bàn phím. ví dụ:

(gzip -d < file.gz > file) 2>&1 | less

sẽ đưa lỗi gzip vào ít hơn

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.