Kiedy używać przekierowania do stderr w skryptach powłoki

15

Wiem, że dobrze zachowujące się narzędzia, takie jak grep, wysyłają „standardowe” komunikaty do standardowego wyjścia, a komunikaty o błędach do standardowego.

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

Kiedy sam piszę skrypty powłoki, często trudno mi zdecydować, jakie dane wyjściowe i jakie komunikaty powinienem przedstawić na stderr, czy też powinienem w ogóle się tym przejmować.

Chciałbym wiedzieć o dobrych praktykach: kiedy przekierowanie jakiejś wiadomości do stderr jest wymagane i uzasadnione, a kiedy nie?

„To zależy”, jasne, ale czy masz jakieś spostrzeżenia, które pomogłyby mi w podjęciu tych decyzji?

Aby dostosować to subiektywne pytanie do formatu, chciałbym zachęcić do odpowiedzi, które odnoszą się do „dlaczego”, i są informowane przez doświadczenie i, jeśli to możliwe, poparte faktami.

glts
źródło
@ rush wyjaśnia to doskonale. Zwykle drukuję raporty postępu do stderr dla długich skryptów.
terdon

Odpowiedzi:

12

Kiedy sam piszę skrypty powłoki, często trudno mi zdecydować, jakie dane wyjściowe i jakie komunikaty powinienem przedstawić na stderr, czy też powinienem w ogóle się tym przejmować.

Milczenie jest złotem. Nie wysyłaj nic, jeśli wszystko jest w porządku.

Chciałbym wiedzieć o dobrych praktykach: kiedy przekierowanie jakiejś wiadomości do stderr jest wymagane i uzasadnione, a kiedy nie?

Najłatwiejszy sposób na oddzielenie stderr od stdout: wyobraź sobie, że wszystkie dane wyjściowe skryptów zostaną przekierowane do innego polecenia za pomocą potoku. W takim przypadku powinieneś zachować wszystkie powiadomienia w stderr, ponieważ takie nieoczekiwane informacje w stdout mogą uszkodzić sekwencję potoku.

Czasami także w rurach takich jak ta:

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

musisz przekazać coś command2do danych wyjściowych użytkowników. Najłatwiejszym sposobem bez plików tymczasowych jest stderr.

wysypka
źródło
Dziękujemy za pomysł „wyobraź sobie fajkę”. Czasami wdrażam skrypty, które robią tylko „powiadomienie” ( echoniektóre zmienne, pokazują, co zostało zrobione, pokazują postęp). Waham się, aby umieścić wszystko na stderr, ponieważ te komunikaty logowania to wszystko, co skrypt kiedykolwiek wyświetli. Nie jestem pewien, jak zastosować pomysł rury w takich sytuacjach.
glts
1
Programy @glts są zawsze modyfikowane i ulepszane. Chociaż wspomniane skrypty nie generują teraz żadnych danych, mogą później lub wykorzystać je jako punkty wyjścia dla innych skryptów, które to robią. Jeśli zastosujesz się do konwencji, zaczniesz od niej o wiele mniej niespodzianek. OTOH, jeśli chcesz po prostu zapisać dane wyjściowe w pliku, musisz przekierować stderr, więc jest to kompromis, jak wszystko inne.
Joe
+1 Kolejna parafraza: upewnij się, że standardowe wyjście jest zawsze do odczytu maszynowego lub przynajmniej zawiera przydatne dane tekstowe w spójnym formacie.
tripleee
2

Ogólnie piszę wszystko, co dotyczy operacji aplikacji stderr , stdoutjest zarezerwowane dla danych.

Wyobraź sobie taką aplikację cat . Kiedy używasz go do odczytu danych wejściowych i przekazujesz do innej aplikacji (za pomocą potoku), nie chcesz, aby dane wyjściowe były zaśmiecone komunikatami o stanie.

Wszystko, co może być interesujące dla innej aplikacji lub postprocesora mojej aplikacji, będzie do stdoutwszystkiego, co będzie dotyczyło tylko wewnętrznej strony mojej aplikacji stderr.

Der Hochstapler
źródło
0

Moje osobiste preferencje to wysyłanie komunikatów o błędach i wyjątków stderroraz komunikatów informacyjnych na adres stdout. IMO stderrjest dla wyjątków i stąd moja konwencja.

unxnut
źródło