Khi nào nên sử dụng chuyển hướng để stderr trong shell script


15

Tôi biết rằng các tiện ích hoạt động tốt như grep xuất các thông báo "bình thường" sang thiết bị xuất chuẩn và thông báo lỗi cho thiết bị lỗi chuẩn.

$ grep '^foo' file1 file2
file1:foo
grep: file2: No such file or directory

Khi tôi tự viết kịch bản shell, tôi thường khó quyết định đầu ra nào và thông điệp nào tôi nên trình bày trên stderr, hoặc liệu tôi có nên bận tâm gì không.

Tôi muốn biết về thực hành tốt: Khi nào chuyển hướng một số tin nhắn đến stderr được gọi là hợp lý và khi nào thì không?

"Nó phụ thuộc", chắc chắn, nhưng bạn có một số hiểu biết sẽ giúp tôi đưa ra những quyết định này?

Để làm cho câu hỏi chủ quan này phù hợp với định dạng, tôi muốn khuyến khích các câu trả lời giải quyết "lý do" và được thông báo bằng kinh nghiệm và nếu có thể được hỗ trợ bởi các sự kiện.


@rush giải thích một cách hoàn hảo. Tôi thường in các báo cáo tiến độ lên stderr cho các tập lệnh dài.
terdon

Câu trả lời:


12

Khi tôi tự viết kịch bản shell, tôi thường khó quyết định đầu ra nào và thông điệp nào tôi nên trình bày trên stderr, hoặc liệu tôi có nên bận tâm gì không.

Im lặng là vàng. Đầu ra không có gì nếu mọi thứ đều ổn.

Tôi muốn biết về thực hành tốt: Khi nào chuyển hướng một số tin nhắn đến stderr được gọi là hợp lý và khi nào thì không?

Cách dễ nhất để tách stderr khỏi thiết bị xuất chuẩn: chỉ cần tưởng tượng tất cả đầu ra tập lệnh của bạn sẽ được chuyển hướng đến một lệnh khác thông qua đường ống. Trong trường hợp đó, bạn nên giữ tất cả các thông báo trong thiết bị xuất chuẩn, vì thông tin không mong muốn như vậy trong thiết bị xuất chuẩn có thể phá vỡ chuỗi ống.

Ngoài ra đôi khi trong các ống như thế này:

command1 | while read line ; do command2 ; done | command3

bạn cần vượt qua một cái gì đó từ command2đầu ra của người dùng. Cách dễ nhất mà không có tập tin tạm thời là stderr.


Cảm ơn bạn cho ý tưởng "tưởng tượng một đường ống". Đôi khi tôi đã triển khai các tập lệnh không làm gì ngoài "thông báo" ( echomột số biến, hiển thị những gì đã được thực hiện, hiển thị tiến trình). Tôi ngần ngại đặt mọi thứ lên stderr vì các thông điệp đăng nhập này là tất cả các tập lệnh sẽ xuất ra. Tôi không chắc làm thế nào để áp dụng ý tưởng đường ống trong những tình huống này.
chiếu vào

1
Các chương trình @glts luôn được sửa đổi và cải thiện. Mặc dù các tập lệnh mà bạn đề cập hiện không xuất bất kỳ dữ liệu nào, chúng có thể sau này hoặc bạn có thể sử dụng chúng làm điểm bắt đầu cho các tập lệnh khác. Nếu bạn tuân theo quy ước để bắt đầu, bạn sẽ nhận được ít nhiều bất ngờ hơn về sau. OTOH, nếu bạn chỉ muốn lưu kết quả đầu ra vào một tệp, thì bạn phải chuyển hướng stderr, vì vậy đó là một sự đánh đổi như mọi thứ khác.
Joe

+1 Một cách diễn giải khác: đảm bảo thiết bị xuất chuẩn luôn có thể đọc được bằng máy hoặc ít nhất chứa dữ liệu văn bản hữu ích ở định dạng nhất quán.
tripleee

2

Tôi thường viết mọi thứ liên quan đến hoạt động của ứng dụng stderr, stdoutđược dành riêng cho dữ liệu.

Hãy tưởng tượng một ứng dụng như thế nào cat. Khi bạn sử dụng nó để đọc đầu vào và chuyển nó sang một ứng dụng khác (thông qua một đường ống), bạn không muốn đầu ra bị vấy bẩn với các thông báo trạng thái.

Mọi thứ có thể thú vị đối với một ứng dụng khác hoặc một bộ xử lý hậu kỳ cho ứng dụng của tôi sẽ diễn ra stdout, mọi thứ chỉ liên quan đến quốc tế của ứng dụng của tôi sẽ diễn ra stderr.


0

Sở thích cá nhân của tôi là gửi thông báo lỗi và ngoại lệ đến stderrvà thông báo thông tin tới stdout. IMO, stderrlà cho bất kỳ trường hợp ngoại lệ và do đó, quy ước của tôi.

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.