Bir komut veya kabuk betiğinin çıktısının stdout veya stderr olup olmadığı nasıl anlaşılır


32

Bir komut veya kabuk betiği çalıştırdığımı söyleyeyim ve bu bana çıktı veriyor. Çıkış oldu ise bu komutun veya kabuk komut dosyası iç elemanların bilmeden, nasıl bir belirliyor stderrya stdout?

Örneğin,

$ ls -ld /
drwxrwxr-t  35 root  admin  1258 Dec 11 19:16 /

vs

ls -ld /test
ls: /test: No such file or directory

İlk komutun stdout, ikincisinin de basıldığını nasıl anlarım stderr?


1
Burada hangi sorunu çözmeye çalışıyorsun?
Kenster

3
Birinin bunu soracağından korktum; hiçbiri gerçekten, çoğunlukla meraklı ve yönlendirme anlayışımı geliştirmeyi umuyor.
KM.

7
Sen koyabilirsiniz stderredKabuk ortamı en içinde LD_PRELOADalmak stdoutve stderrfarklı renklerde. İşte o damardaki ilgili bir soru.
Anko

Yanıtlar:


18

Çıktı zaten yazdırıldığında bir kere söylemenin yolu yok. Bu durumda, her iki stdoutve stderrterminal bağlı akışı zaten metin terminal gösterilme tarafından kaybedildi için yazıldığı hakkında bilgi yüzden; terminale gitmeden önce program tarafından birleştirildiler.

Yukarıdaki gibi bir durumda yapabileceğiniz şey, komutu çalıştırmak stdoutve stderrfarklı yerlere yönlendirmek ve ne olacağını görmek olacaktır. Veya bir kez, iki kez çalıştırmak stdoutyönlendirildi /dev/nullve bir kez stderryönlendirilir /dev/null, ve metinde bu durumlar sonuçların hangi gösterilmesini bkz.

Sen yönlendirebilirsiniz stdoutiçin /dev/nulltacking tarafından >/dev/nullkomut satırının sonuna üzerine ve yönlendirebilirsiniz stderriçin /dev/nullilave ederek 2>/dev/null.


9

Stdout komutunu kullanarak > fileyönlendirebilirsiniz ve stderr komutunu kullanarak yeniden yönlendirebilirsiniz 2> file. Birçok modern kabuk, komutlara yönlendirmeyi destekler, böylece sedhangi çıkışın hangi akıştan geldiğini vurgulamak için kullanabilirsiniz :

$ ls 2> >(sed 's/^/2: /') > >(sed 's/^/1: /')
1: unity_support_test.0
1: vmwareDnD

$ ls foo 2> >(sed 's/^/2: /') > >(sed 's/^/1: /')
2: ls: cannot access foo: No such file or directory

Çok hoş! Çizgileri önek yerine renklerle vurgulamak harika olurdu.
dotancohen

3
@dotancohen: Bir olabilir! Örneğin,(echo "this is stdout"; echo "this is stderr" >&2) > >(sed 's/.*/\x1b[32m&\x1b[0m/') 2> >(sed 's/.*/\x1b[31m&\x1b[0m/')
PM 2Ring

Stdout ve stderr'den karışık çıktılar varsa, önce stdout'un ardından stderr'nin yazdırılacağını unutmayın.
nyuszika7h

5

annotate-outputDebian en dan komut devscriptsseçerek bunu sağlar:

$ annotate-output ls -ld /test
14:54:22 -: Started ls -ld /test
14:54:22 E: ls: cannot access /test: No such file or directory
14:54:22 -: Finished with exitcode 2

İkinci sütun stdout'u ve stderr'yi ile gösterir Ove Esırasıyla.

Bazı cevaplar var, ana cevap diğer cevaplarda da belirtildiği gibi: Bunu yaptıktan sonra yapamazsınız. Ne kabuk ne de terminal, rasgele bir programın dosya tanımlayıcılarını nasıl kullandığının farkında değildir, ancak kabuk başlangıçta bunları ayarlamaktan sorumludur.

Bu yöntem fifos kullanır, beşe yazmak, bir yazıya yazmaktan farklı davranabilir ve iki farklı beşe yazmak da kesinlikle farklıdır (potansiyel zamanlama / araya sokma sorunları). Ayrıca, etkileşimli kullanım için uygun değildir, örneğin annotate-output bashharika bir plan değildir, ancak diğer birçok amaç için kullanışlıdır. Stdin / stdout / stderr'ı renklendirmeyle ilgili soruların cevaplarında birçok ve çok sayıda komut dosyası ve kabuk işlevi vardır, en sağlam olanı stderr'e yazılan verileri değiştirmek için (çoğu) programların çalışma zamanı modifikasyonunu kullanan stderrd'dir .

Anko'nun bağladığı bu soru, bu konuyla ilgili iyi cevaplar veriyor: stdout / stderr çıktısının renklendirilmesi: Kabuğumu STDERR ve STDOUT'u farklı renklerde basacak şekilde yapılandırabilir miyim?


1
Döngüleri bashkullanan while readve dateher stdout veya stderr satırı için bir komut çalıştıran bir komut dosyası olduğunu unutmayın, bu nedenle cmd > >(ts '%T O:') 2> >(ts '%T E:')eşdeğerden çok daha az verimli olur .
Stéphane Chazelas 15:17

1

Diğer cevapların yanı sıra /proc/$PID/fd(soruyu cevaplamamasına rağmen) işaret etmek içgüdüseldir :

$ cat > /dev/null 2> /tmp/blablah &
[1] 3073

[1]+  Stopped                 cat > /dev/null 2> /tmp/blablah
$ ls -l /proc/3073/fd
total 0
lrwx------ 1 kampde kampde 64 Feb 24 11:43 0 -> /dev/pts/33
l-wx------ 1 kampde kampde 64 Feb 24 11:43 1 -> /dev/null
l-wx------ 1 kampde kampde 64 Feb 24 11:43 2 -> /tmp/blablah

Gördüğünüz gibi, burada bir işlem için açılan dosya tanımlayıcılarını görebilirsiniz. 0olduğu STDIN, 1olduğu STDOUTve 2olduğu STDERR. STDOUT veya STDERR'ye yeniden yönlendirmediyseniz, /dev/pts/33terminali işaret edeceklerinden (en azından bu örnekte) göreceksiniz .

Notlar : /proc/$PIDsadece çalışan işlemler için vardır. Bu durumda catargümanlar olmadan kullandım , bu yüzden kapanana kadar bitmiyor STDIN. Ayrıca arka planda da çalıştım, bu yüzden bu örnek için hemen PID'im var.


0

Ne sorduğun belli değil ama bu yardımcı olabilir.

ls -ld /
echo $?    # Exit status 0 returned because command executed successfully.

ls -ld /test
echo $?    # Non-zero exit status returned -- command failed to execute

Kaynak

Eğer çıkış kodu 0 ise, komutun doğru bir şekilde yürütüldüğü anlamına gelir (stdout), burada çıkış kodunun 0'dan farklı olması durumunda anlamlar bulabilirsiniz (stderr)


Çok ilginç! Çıkış durumlarını hiçbir zaman yeniden yönlendirme ile bağlamazdım. Sıfır, sıfır stdoutolmayan anlamına gelir stderrmi?
KM.

7
@ KM, hayır. Güçlü bir şekilde ilişkili olduğunu söyleyebilirim, ancak bir programın yazmasını stderrve iyi bir hata kodunu stdoutgeri göndermesini ya da kötü bir hata kodunu yazmasını ve döndürmesini engelleyen hiçbir şey yok . Aslında, deneyin find /root- root olarak çalışmadığınızı varsayalım, 2 satır yazdırılmalıdır - "/ root" basılır stdoutve "find: / root: İzin reddedildi" yazılır stderr. Ve bulmak kötü bir dönüş kodu döndürür.
godlygeek

op'un sorunu, hangisinin stdout veya stderr olduğunu nasıl söyleyeceğidir.
it_is_a_literature

0

Genellikle STDERR programın isminde iki nokta üst üste işaretlenmiş olarak bulunur.

Örnek:

rpm -zq some_utils 
rpm: -zq: unknown option

Vs

rpm -ql some_utils 
package some_utils is not installed

-1

Hata çıktısını yakalamak ve test etmek için:

ls -l test 2>errors
if [ -s errors ]; then echo "There were errors:" && cat errors; fi
rm errors
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.