Czy istnieje oficjalny POSIX, GNU lub inne wytyczne dotyczące tego, gdzie powinny być drukowane raporty z postępu i informacje o logowaniu (takie jak „Doing foo; foo done”)? Osobiście staram się pisać je do stderr, aby móc przekierować standardowe wyjście i uzyskać tylko rzeczywiste wyjście programu. Niedawno powiedziano mi, że nie jest to dobra praktyka, ponieważ raporty postępu nie są tak naprawdę błędami i tylko komunikaty o błędach powinny być drukowane na stderr.
Obie pozycje mają sens i oczywiście możesz wybrać jedną lub drugą w zależności od szczegółów tego, co robisz, ale chciałbym wiedzieć, czy istnieje powszechnie akceptowany standard. Nie byłem w stanie znaleźć żadnych konkretnych reguł w POSIX, standardach kodowania GNU ani żadnej innej tak szeroko akceptowanej listy najlepszych praktyk.
Mamy kilka podobnych pytań, ale nie dotyczą one dokładnie tego problemu:
Kiedy używać przekierowania do stderr w skryptach powłoki : Akceptowana odpowiedź sugeruje, co mam tendencję do robienia, trzymaj końcowe wyjście programu na stdout i cokolwiek innego do stderr. Jest to jednak przedstawione jako opinia użytkownika, choć poparte argumentami.
Czy komunikat o użyciu powinien być przekazywany do stderr czy stdout? : Jest to specyficzne dla wiadomości pomocniczych, ale przytacza standard kodowania GNU. Tego właśnie szukam, nie ograniczając się tylko do wiadomości pomocy.
Czy istnieją więc jakieś oficjalne zasady dotyczące tego, gdzie powinny być drukowane raporty postępu i inne komunikaty informacyjne (które nie są częścią rzeczywistych wyników programu)?
stdout
wraz z wynikami to bezpieczny sposób, aby wyniki były bezużyteczne. Jeśli kiedykolwiek będziesz potrzebować przesłać wyniki do innego programu, wspomniany program będzie musiał oddzielić wyniki od pokręteł. Ponadto, jeśli przekierujesz dane wyjściowe do pliku, nie zobaczysz błystek. MOIM ZDANIEM.stdout
jest w rzeczywistości bezpiecznym i właściwym sposobem, aby naciskać pokrętła i inne wiadomości informacyjne, ale jak wielu programistów mówi: „Cisza jest złotem. Nie wysyłaj nic, jeśli wszystko jest w porządku. więc w rzeczywistości zawsze używa się stderr ze względu na niejasną definicję, a także stdout może przerwać sekwencję rur. dla oficjalnego przewodnikastderr
do zgłaszania komunikatów o błędach, z wyjątkiem sytuacji, gdy--verbose
używana jest flaga, w której również uwzględniane są raporty postępu.Odpowiedzi:
Posix definiuje standardowe strumienie w ten sposób :
Biblioteki C GNU opisano standardowe strumienie podobne:
Zatem standardowe definicje mają niewiele wskazówek dotyczących wykorzystania strumienia poza „wyjściem konwencjonalnym / normalnym” i „wyjściem diagnostycznym / błędem”. W praktyce często przekierowuje się jeden lub oba strumienie do plików i potoków, w których wskaźniki postępu będą stanowić problem . Niektóre systemy nawet monitorują
stderr
wyjście i uważają to za oznakę problemów. Czysto pomocnicze informacje o postępach są zatem problematyczne w obu strumieniach.Zamiast bezwarunkowego wysyłania wskaźników postępu do któregokolwiek standardowego strumienia, ważne jest, aby uznać, że wyniki postępu są odpowiednie tylko dla strumieni interaktywnych . Mając to na uwadze, zalecam pisanie liczników postępu dopiero po sprawdzeniu, czy strumień jest interaktywny (np. Z
isatty()
) lub gdy jest wyraźnie włączony przez opcję wiersza poleceń. Jest to szczególnie ważne w przypadku sensorów postępu, które opierają się na zachowaniu aktualizacji terminala, takich jak słupki z procentem ukończenia.W przypadku niektórych bardzo prostych komunikatów o postępach („Uruchamianie X” ... „Gotowe z X”) bardziej rozsądne jest włączenie wyniku nawet dla strumieni nieinteraktywnych. W takim przypadku zastanów się, w jaki sposób użytkownicy mogą wchodzić w interakcje ze strumieniami, np. Wyszukiwanie,
grep
stronicowanieless
lub monitorowanie za pomocątail -f
. Jeśli zrozumienie komunikatów o postępach w tych kontekstach jest sensowne, łatwiej będzie je wykorzystaćstdout
.źródło
N% done
io rzeczach takich jakdoing foo
ifoo done
. Te ostatnie należy zawsze zachować, ponieważ są używane do debugowania po przekierowaniu do pliku. Twoja sugestia sprawdzenia, czy strumień jest interaktywny, nie ma zastosowania (choć ogólnie jest to bardzo dobry pomysł).curl
iyum
. W tym przypadku, chciałbym zastanowić się, czy i w jaki sposób użytkownik będzie chciał współdziałać z wyjściem poprzezgrep
lubless
lub podobnych narzędzi.POSIX definiuje błąd standardowy jako
Nie ogranicza się to wyłącznie do komunikatów o błędach. Informacje o postępach uważałbym za dane wyjściowe diagnostyczne, więc należy on do standardowego błędu.
źródło
stdout
jest domyślnie buforowane w linii, podczas gdy niestderr
jest buforowane , więcstderr
jest naturalnym wyborem do pisania tekstu postępu / pasków / spinnerów, które nie zawierają nowej linii. (Jeśli piszesz taki tekststdout
, musisz zaśmiecać swoje wywołania wyjściowe postępów,stdout.flush()
aby były widoczne).stdout
, trzeba opróżnić, nawet jeśli tekst nie zawiera nowej linii, jeśli chcesz, aby sprawozdania z postępów rzeczywiście pojawiają się w czasie rzeczywistym, kiedy przekierowany.POSIX jest nieco bardziej konkretny na temat „informacji diagnostycznych” w Shell i Utilities , 1.4: Domyślne opis narzędzia (wyróżnienie moje):
IANASL, ale interpretuję to jako oznaczające, że stderr będzie miał dane wyjściowe tylko wtedy, gdy narzędzie zwróci kod wyjścia błędu. Ponieważ nie powinno to być normalnym przebiegiem zdarzeń dla pomyślnego wykonania, narzędzie POSIX nie powinno drukować żadnych informacji o postępach, chyba że wystąpi błąd (chyba że oczywiście określono inaczej itp.).
źródło
Zgodnie z zasadą wykluczenia może on przejść tylko do stderr. Tak, wiem, że zapytałeś o oficjalną specyfikację, której nie mogę przedstawić poza linkiem do specyfikacji POSIX podanym przez Stephena Kitt'a, który stwierdza, że stderr służy do celów diagnostycznych.
Ważniejsze jest to, że stdin i stdout mają funkcję, która nie zezwala na drukowanie raportów postępu na stdout - one oczywiście tworzą sekwencję potoków, która w komendach powłoki Unixa jest nie tylko efektem ubocznym, ale sam rdzeń potężnego podejścia do potokowania .
Więc. Nic poza prawdziwym „ładunkiem” twojego programu nie należy do standardowego wyjścia. Jeśli twój program nie ma wyjścia, nic nie powinno przejść do standardowego wyjścia. To pozostawia stderr na wszystko inne , w tym raporty postępu.
To prawda, że pozostawia to dziurę - prawdopodobnie dobrze byłoby mieć „stdfluff” lub coś takiego, co nie służy ani do wyjścia, ani do błędów, ale do raportów postępu, debugowania i tak dalej. W rzeczywistości nic Cię nie powstrzymuje, tzn. Możesz wydrukować swoje postępy do deskryptora pliku 3. Przykład:
To nie wytwarza danych wyjściowych. (*)
Wypisuje to na fd-3, który jest przekierowywany na standardowe wyjście.
(*) Pierwszy przykład nie generuje danych wyjściowych, ale jest nieco przesadny;
open
zawiedzie i$!
będzie zawieraćno such file or directory
; po prostu weźmy to za przykład, oczywiście nie należy tego tak na serio używać. W prawdziwym programie, jeśli chciałbyś pójść tą drogą, możesz przetestować, czy/dev/fd/3
jest on użyteczny i wziąć to jako wskazówkę, czy aktywować raporty z postępu; musisz to zrobić dość wcześnie, aby nie pomylić własnychopen
plików dla prawdziwych plików i takie ...źródło
fd-3
? Trzecia dyskietka?Komunikat użycia powinien przejść do stdout, jeśli użytkownik go wywołał,
--help
i do stderr, jeśli popełnił błąd. Bezwarunkowe drukowanie na stderr jest nieznośne, ponieważ utrudnia przeglądanie go za pomocą pager / grep / etc.Mogę też zasugerować trzeci sposób: open / dev / tty dla raportów postępu / spinnerów / etc.
źródło
--help
ani nie pomagam. Przeczytaj ponownie pytanie.