İlerleme raporları / kayıt bilgileri stderr veya stdout'a mı ait?


75

İlerleme raporları ve kayıt bilgilerinin ("Foo yapmak; foo yapmak" gibi) basılacağı konusunda resmi bir POSIX, GNU veya başka bir kılavuz var mı? Şahsen ben onları stderr'e yazma eğilimindeyim, böylece stdout'u yönlendirebilir ve sadece programın gerçek çıktısını alabilirim. Son zamanlarda, ilerleme raporları aslında hata olmadığından ve sadece hata mesajlarının stderr'e basılması gerektiği için bunun iyi bir uygulama olmadığı söylendi.

Her iki pozisyon da anlamlıdır ve elbette yaptığınız işin detaylarına bağlı olarak birini veya diğerini seçebilirsiniz, ancak bunun için genel kabul görmüş bir standart olup olmadığını bilmek istiyorum. POSIX, GNU kodlama standartları veya bu tür yaygın kabul görmüş en iyi uygulama listelerinde herhangi bir özel kural bulamamıştım.

Birkaç benzer sorumuz var, ancak bu sorunu çözemiyorlar:

Öyleyse, ilerleme raporlarının ve diğer bilgilendirici mesajların (programın gerçek çıktısının bir parçası olmayan) basılması gerektiği konusunda resmi kurallar var mı?


26
İplikçiler ve benzerlerini stdoutsonuçlarla birlikte yazdırmak , sonuçları işe yaramaz hale getirmenin güvenli bir yoludur. Sonuçları başka bir programa aktarmanız gerekirse, söz konusu programın sonuçları iplikçilerden ayırmanız gerekir. Ayrıca, çıktıyı bir dosyaya yönlendirirseniz, eğiricileri göremezsiniz. BENİM NACİZANE FİKRİME GÖRE.
Satō Katsura

2
@SatoKatsura evet, bu da benim düşüncem ve bu yüzden stderr'e baskı yapıyorum. Ancak çalıştığım şirketin CTO'su, stderr'e yazdırmanın bir şeyin yanlış gittiğinin bir göstergesi olduğunu düşünüyor. Oldukça cesurca, POSIX Way®'in stderr'e yazdırdığını ve beni aradığını iddia ettim. Benim hakkımda 20 yıllık tuhaf deneyime sahip olduğu göz önüne alındığında, bir tür "resmi" kılavuz bulabilir miyim görmek istiyorum.
terdon

Sato Katsura'nın söylediği gibi, stdoutiplikçilere ve diğer bilgilendirici mesajlara zarar vermenin güvenli ve doğru bir yoludur, ancak birçok programcının söylediği gibi 'Sessizlik altındır. Her şey yolundaysa hiçbir şey çıktı. ' böylece aslında, stderr için sequence.for boruyu kırabilir stdout'u çünkü belirsiz tanım yapmak için kullanılan ve resmi kılavuz
ven Se

6
@Seven yanlış anladığını düşünüyorum; Sato, stdout kullanmanın güvenli olmadığını söylüyor ("sonuçları işe yaramaz hale getirmenin güvenli bir yolu").
Stephen Kitt

1
Olası tek bedene uyan bir çözüm, yalnızca stderrbir --verbosebayrak kullanıldığında, hangi noktada ilerleme raporlarının dahil edildiğinin haricinde, yalnızca hata mesajlarını bildirmek için kullanmak olacaktır .
Gaurav,

Yanıtlar:


27

Posix standart akışları şöyle tanımlar :

Program başlangıcında, üç akış önceden tanımlanacak ve açıkça açılması gerekmeyecektir: standart giriş (geleneksel girişi okumak için), standart çıkış (geleneksel çıkışı yazmak için) ve standart hata (teşhis çıkışını yazmak için). Açıldığında, standart hata akışı tam olarak arabelleğe alınmadı; standart giriş ve standart çıkış akışları, yalnızca akış etkileşimli bir cihaza atıfta bulunmayacak şekilde belirlenebiliyorsa tamamen tamponlanır.

Önceki XIV benzer standart akışları anlatılmaktadır:

Değişken: FILE * stdout
Programdan normal çıktı almak için kullanılan standart çıktı akışı.

Değişken: FILE * stderr
Program tarafından verilen hata mesajları ve teşhis için kullanılan standart hata akışı.

Bu nedenle, standart tanımların “geleneksel / normal çıktı” ve “tanı / hata çıktı” nın ötesinde akış kullanımı için çok az rehberliği var. . Bazı sistemler bile izlemek stderr çıkış için ve ona sorunların bir işareti düşünün. Tamamen yardımcı ilerleme bilgisi bu nedenle her iki akışta da sorunludur.

İlerleme göstergelerini koşulsuz olarak her iki standart akışa göndermek yerine, ilerleme çıktısının yalnızca etkileşimli akışlar için uygun olduğunu kabul etmek önemlidir . Bunu akılda tutarak, ilerleme sayaçlarını yalnızca akışın etkileşimli olup olmadığını (örn. İle isatty()) veya komut satırı seçeneği tarafından açıkça etkinleştirilip etkinleştirilmediğini kontrol ettikten sonra yazmanızı öneririm . Bu,% -complet bar'lar gibi anlam çıkarmak için terminal güncelleme davranışına dayanan ilerleme sayaçları için özellikle önemlidir.

Bazı çok basit ilerleme mesajları için (“X Başlatılıyor” ... “X ile Yapıldı”) etkileşimli olmayan akışlar için bile çıktı eklemek daha uygun olur. Bu durumda, kullanıcıların arama yapmak grepveya sayfalamak lessveya izlemek gibi akışlarla nasıl etkileşime girebileceklerini düşünün tail -f. İlerleme mesajlarını bu bağlamlarda görmek mantıklı olursa, tüketmeleri çok daha kolay olacaktır stdout.


Teşekkürler, GNU rehberi, peşinde olduğum türden bir şey. Ancak, sorumun biraz yanıltıcı olduğunu fark ettim. Bahsettiğim zaman hem gibi şeyler düşünüyordum "ilerleme raporları" N% donegibi ve şeyler doing foove foo done. Bir dosyaya yönlendirilirken hata ayıklamak için kullanıldığından sonuncusu daima tutulmalıdır. Bu nedenle, akışın etkileşimli olup olmadığını kontrol etme öneriniz uygulanabilir değil (genellikle çok iyi bir fikir).
terdon

Ah teşekkürler açıklama için, bu sizin gibi yazılımda bakın “% tamamlandı” ve karma işareti ilerleme çubuğu gibi sadece mal yüzünden biraz farklı curlve yum. Bu durumda, ben kullanıcı aracılığı çıkışı ile etkileşime isteyeyim olup olmadığı ve nasıl düşünürdüm grepveya lessbenzeri araçlar ya.
Bradd Szonye

Yukarıdaki açıklamaları içerecek şekilde cevap güncellendi.
Bradd Szonye

71

POSIX , standart hatayı şu şekilde tanımlar:

tanılama çıktılarını yazmak için

Bu, yalnızca hata mesajlarıyla kullanımını sınırlamaz. İlerleme bilgisini diyagnostik çıktı olarak kabul ediyorum, bu yüzden standart hataya ait.


8
Python'da FWIW stdoutöntanımlı stderrolarak arabelleğe alınır, oysa arabelleksizdir, yani stderryeni satır içermeyen ilerleme metni / çubuklar / eğiriciler yazmak için doğal seçimdir. (Böyle bir metin stdoutyazarsanız, ilerleme çıkış çağrılarınızı stdout.flush()görünür kılmak için karışıklığa ihtiyacınız vardır ).
PM 2Ring

12
Python'a özgü olmayan @ PM2Ring, POSIX, akışları bu şekilde tanımlar.
Stephen Kitt

4
@ PM2Ring: yazarken stdout, metin bile temizlemek gerekir yoktur Yönlendirildiyseniz zaman ilerleme raporları aslında gerçek zamanlı olarak gösterilmesini istiyorsanız bir yeni satır içerir.

@ Hurkyl Ah, iyi nokta. Yeniden yönlendirmeyi düşünmüyordum.
PM 2Ring

1
@Wtower, ha? Hayır. Çıkış durumu 0 ise, Ansible stderr metnini yutar. Bu iddia sadece yanlış.
Charles Duffy

10

POSIX, Shell and Utilities'teki "tanılama bilgileri" hakkında biraz daha somuttur , 1.4: Yardımcı Program Tanım Varsayılanları (benimkine önem verir):

STDERR

STDERR bölümü, yardımcı programın standart hata çıktısını açıklar. Sadece yardımcı program tarafından bilerek gönderilen mesajlar açıklanmaktadır. Standart hata için bir terminal kullanılması, arka planda kullanıldığında standart hata çıktısı yazan standart yardımcı programlardan herhangi birinin durmasına neden olabilir. Bu nedenle, uygulamalar arka planda yerleştirilecek komut dosyalarında etkileşimli özellikler kullanmamalıdır.

Çoğu yardımcı program için tanısal mesajların formatı belirtilmemiştir, ancak formatı POSIX.1-2008'in bu hacmi tarafından belirtilmeyen tanısal ve bilgilendirici mesajların dili ve kültürel kuralları, LC_MESSAGES ve [XSI] [Option Start] ayarlarından etkilenmelidir. ] NLSPATH. [Seçenek Sonu]

Standart hizmet programlarının belirtilen standart hata çıktısı, bu POSIX.1-2008 hacminin sağladığı durumlar haricinde, bu POSIX.1-2008 biriminde tanımlanan çevre değişkenlerinin varlığına veya değerine bağlı olmayacaktır.

Varsayılan Davranış : Bu bölüm "Standart hata yalnızca teşhis mesajları için kullanılacaktır" olarak listelendiğinde, aksi belirtilmediği sürece , tanılama mesajlarının yalnızca çıkış durumu bir hata olduğunu gösterdiğinde standart hataya gönderileceği anlamına gelir. ortaya çıktı ve yardımcı program bu POSIX.1-2008 biriminde açıklandığı şekilde kullanılır.

Bu bölüm "Kullanılmadı" olarak listelendiğinde, hizmet programı POSIX.1-2008'in bu cildinde açıklandığı gibi kullanıldığında standart hatanın kullanılmaması gerektiği anlamına gelir.

IANASL, ancak stderr'ın yalnızca yardımcı program bir hata çıkış kodu döndürürse çıktı alacağı anlamına geldiğini yorumluyorum. Başarılı bir yürütme için bu olayların normal seyri olmaması gerektiği için, bir hata oluşmadıkça (elbette, aksi belirtilmediği sürece) bir POSIX yardımcı programı tarafından ilerleme bilgileri yazdırılmamalıdır .


Bunu, standart hata kullanımı için genel bir tanım olarak değil, her POSIX yardımcı programının özelliklerinde verilen "STDERR" bölümünün anlamını açıklamak olarak anlıyorum. Terdon'un burada standart bir POSIX programı yazdığını sanmıyorum ;-).
Stephen Kitt

1
@StephenKitt de ben de yapmaz. Ama stderr çıktısının yanlış gittiğinin bir göstergesi olduğunu söyleyen CTO ile görüşüyor ve standart, varsayılan davranış olarak iddialarını destekliyor.
muru

1
Talebi yalnızca POSIX yardımcı programları için varsayılan davranış olarak ve sonra da yalnızca belirli durumlarda (belirtilen ifadeyi kullanan yardımcı programlar) destekler. POSIX'in bu kısmı normatif değil (AIUI), bir şablon: size yardımcı program özelliklerini nasıl okuyacağınızı, yardımcı programların davranışını belirtmediğini söyler. Özellikle, "Standart hata yalnızca tanılama mesajları için kullanılacaktır" ifadelerinin anlamlarını tanımlar. ve "Kullanılmamış." fayda şartnamelerinin "STDERR" bölümlerinde. Her yardımcı program davranışını belirtir ve bu ifadeleri steno olarak kullanabilir.
Stephen Kitt

@StephenKitt ki bu benim fikrimi değiştirmiyor. POSIX yardımcı programları a) stderr'ye çıktı vermez, b) yalnızca bir şey yanlış giderse tanısal mesajlar için kullanır, c) bir şey yanlış giderse bile yalnızca tanısal mesajlar için kullanır ve d) başka bir şey için kullanır. Aksi belirtilmedikçe (c, d) bir şey ters giderse, sadece teşhis mesajları için kullandıklarını söyledim. Şimdi, benim iddiam, bunun varsayılan olduğu, açıkça olduğu, çünkü şablon bu yüzden.
muru

2
Eh, "aksi belirtilmediği sürece" oldukça önemli bir uyarı olduğunu söyleyebilirim: bir POSIX yardımcı programı standart hatası hakkında ilerleme bilgisi verdiğini çok iyi belirleyebilir ve standartlara uygun olur. Haklısınız, ilginç olan "varsayılan davranış" ın (ilgili bölümde yine de belirli bir sözü gerektirir), yalnızca çıkış kodu da bir hata olduğunu gösteriyorsa standart hata kullanmaktır; ama sınırlayıcı değil.
Stephen Kitt

7

Dışlama ilkesiyle, sadece stderr'e gidebilir. Evet, stderr'in tanı amaçlı olduğunu belirten Stephen Kitt tarafından verilen POSIX şartnamesiyle bağlantının ötesinde size sunamayacağım resmi bir şartname sorduğunuzu biliyorum.

Daha önemli olan nokta stdin ve stdout'un baskı ilerleme raporlarını stdout'a izin vermeyen bir işleve sahip olması - elbette Unix kabuk komutlarında sadece bir yan etki değil, aynı zamanda güçlü boru hattı yaklaşımının özü olan bir boru dizisi oluştururlar. .

Yani. Programınızın gerçek "yükü" dışında hiçbir şey stdout'a ait değildir. Programınızın çıktısı yoksa, hiçbir şey stdout'a gitmemelidir. Bu , ilerleme raporları da dahil olmak üzere diğer her şey için stderr bırakır .

Verilmiş, bu bir delik bırakır - muhtemelen ne "çıktı" ne de hatalar için olan ama ilerleme raporları, hata ayıklama ve somesuch için olan bir "stdfluff" veya bunun gibi bir şey olması güzel olurdu. Aslında, hiçbir şey sizi bunu gerçekleştirmekten alıkoyamaz, yani ilerlemenizi dosya tanıtıcısına 3 yazdırabilirsiniz. Örnek:

$ perl -e 'open($fd, ">", "/dev/fd/3"); print $fd "hello\n"'

Bu hiçbir çıktı üretmez. (*)

$ perl -e 'open($fd, ">", "/dev/fd/3"); print $fd "hello\n"'  3>&1
hello

Bu, stdout'a yönlendirilen fd-3'e yazdırır.

(*) İlk örnek çıktı üretmiyor, ancak hala biraz getirildi; openbaşarısız olur ve $!içerecektir no such file or directory; sadece bunu örnek olarak alın, elbette bu şekilde kullanılması ciddi değildir. Gerçek bir programda, bu rotaya gitmek istiyorsanız /dev/fd/3, kullanılabilir olup olmadığını test edebilir ve bunu ilerleme raporlarınızı etkinleştirip etkinleştirmeyeceğinizin ipucu olarak alabilirsiniz; Bunu çok erken yapmak zorunda kalacaksın, böylece opengerçek dosyalar ve benzeri şeyler için kendi kafanla karıştı .


Nedir fd-3? Üçüncü disket mi?
Peter Mortensen,

dosya tanıtıcısı 3, @PeterMortensen
AnoE

-1

Kullanıcı onu başlattıysa kullanım mesajı stdout'a --helpve bir hata yaptıysa stderr'a gitmelidir . Koşulsuz olarak stderr'e yazdırmak iğrençtir çünkü çağrı cihazı / grep / etc ile görüntülenmesini zorlaştırır.

Ayrıca, üçüncü bir yol önerebilir miyim: İlerleme raporları / iplikçiler / vb. İçin açık / dev / tty.


6
Üzgünüm, ama bu soruya cevap vermiyor. Özellikle resmi kuralları istedim , görüşü değil. Her halükarda, sizden fikir istemiş olsam bile, farklı bir soruya cevap veriyorsunuz. --helpMesajlardan bahsetmiyorum ya da yardım etmiyorum . Lütfen soruyu tekrar okuyun.
terdon

"Kullanım mesajı" ndan bahsettiniz, sadece bağladığınız diğer başlığın başlığından ziyade, sorunuzun bir parçası olduğunu düşündüm. Bunun için neden "resmi kurallar" olduğunu düşündüğünüzü anlamıyorum. Onları yapma yetkisi kim olurdu?
Random832

3
Onların yaptığını bilmiyorum, bu yüzden soruyorum. Ve resmi olarak, POSIX standardı, bir programın nasıl davranması gerektiğine dair çeşitli dakika ayrıntıları için teknik özelliklere sahiptir. Stephen'ın cevabında belirttiği gibi, stderr'e neyin gitmesi gerektiğine dair belirsiz bir öneri. GNU kodlama standardı da benzer bir şeye sahip olabilir. Temel olarak, * nix ekosistemi için aktif olan ve kod üreten herhangi bir grubun ilgilenebileceğim bir standardı olabilir.
terdon

@ terdon, mevcut programların neler yaptığına dair örnekler verebilir misiniz? curl, wget ve pv, stderr kullanır, wget ve pv ise onu tty ve koşullu yapar.
Random832

4
Ayrıca, gibi sesler sizin CTO bir çağrı programı bir hata oluştu, yani ziyade çıkış durumuna bakarak olarak, standart hataya verilerin varlığına tepki gerektiğini düşünüyor. Bu kesinlikle kötü bir uygulamadır (ve aynı zamanda çıkış durumunu kontrol etmekten daha zor) ve onu ikna etmek için daha iyi bir açı olabilir.
Random832
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.