2012-06-09 26 views
20

Ben stderr yerine stdout bir bash komut bir printf çıktısını yönlendirmek istiyoruz.Bir bash komut dosyasında 'printf' kullanarak 'stderr' dosyasına hata mesajı yazmak için hangi yöntemi kullanmalıyım?

Ben değil şu anda yönlendirilir hiç yerden stderr veya stdout ya yönlendirme konusunda soran duyuyorum. Sadece printf çıkışını stdout varsayılanı yerine stderr olarak gönderebilmek istiyorum.

Biraz deney yaptım ve 1>&2 ekinin printf'a aşağıdaki örnekte gösterildiği gibi, istediğimi yaptığım gibi görünmesini sağladım. Ancak, bash kullanarak deneyimim var. bash bunu yapmanın bir "iyi" yolu olup olmadığını Yani benim birincil soru nedir? By

"iyi" Ben daha yaygın daha geleneksel, ya da daha deyimsel kullanıldığı bunu yapmanın başka yolu yok? Daha tecrübeli bir bash programcısı bunu nasıl yapar?

#!/bin/bash 
printf "{%s} This should go to stderr.\n" "$(date)" 1>&2 
printf "[(%s)] This should go to stdout.\n" "$(date)" 

Ben de bir ikincil sorum var. Bunu çok fazla sormuyorum çünkü 'un bilmesi gereken, ama daha çok merak ediyorum çünkü neler olup bittiğini daha iyi anlamak istiyorum.

O bir kabuk içinde çalışır yalnızca çalışacaktır yukarıdaki gibi görünüyor. Bir komut satırından denediğimde işe yaramıyor. İşte

ne demek istediğimi bir örnektir.

[email protected]:~$ printf "{%s} Sent to stderr.\n" "$(date)" 1>&2 2> errors.txt 
{Sat Jun 9 14:08:46 EDT 2012} Sent to stderr. 
[email protected]:~$ ls -l errors.txt 
-rw-rw-r-- 1 irrational irrational 0 Jun 9 14:39 errors.txt 

Ben çıktı sırayla bir dosyaya gitmeli stderr, gitmeli çünkü hiçbir çıkışı için yukarıdaki printf komutu beklenebilir. Ama bu gerçekleşmez. Ha?

cevap

22

İlk:

printf "{%s} This should go to stderr.\n" "$(date)" >&2 
  • Bir sipariş-of-operasyonlar sorun var: kelimeyi olduğu gibi çalışacaktır, ancak ima ediyor - Hakikaten 1 gerekmez Evet, 1>&2 yapılacak en doğru şey.

    İkinci olarak, 1>&2 2>errors.txt örnek çalışmıyor sebebi yönlendirme yapar tam olarak ne ayrıntıları taşımaktadır.

    1>&2, "filehandle 2'nin şu anda bulunduğu yere 1 dosya noktası yapın" - yani, stdout'a yazılan şeyler şimdi stderr'e gider. Şimdi stderr yazılı errors.txt girer olurdu yani şeyler - 2>errors.txt "errors.txt bir dosya tanıtıcısından açmak ve ona dt 2 noktayı" anlamına gelir.Ama filehandle 1 hiç etkilenmez, bu yüzden stdout'a yazılan şeyler hala stderr'e gider. İlk operasyon "errors.txt açık ve buna stderr noktayı" olacaktır, çünkü yapmak

    doğru şey, her iki stderr'e yazma yapmak ve stdout'u errors.txt gidecek 2>errors.txt 1>&2, ve ikinci operasyon yapmak" olacak stderr'nin şimdi işaret ettiği noktaya nokta ".

  • +0

    Evet, aslında, '2> errors.txt 1> & 2' kullanmak istediğim şeydi. Geçmişte aptalca hissediyorum, ama bu, yapmanın doğru yolu benim için "bariz" hale gelene kadar yapmaya devam etmem gereken saçma sapan hatalardan biri gibi görünüyor. ;-) İçgörü için çok teşekkürler. –

    6
    1. Bu bana mantıklı geliyor. ,

      $ printf "{%s} Sent to stderr.\n" "$(date)" 2> errors.txt 1>&2 
      $ ls -l errors.txt 
      -rw-r--r-- 1 carl staff 47 Jun 9 11:51 errors.txt 
      $ cat errors.txt 
      {Sat Jun 9 11:51:48 PDT 2012} Sent to stderr. 
      
    +0

    +1. Daha fazla bilgi için http://www.gnu.org/software/bash/manual/bashref.html#Redirections sayfasına bakın. –

    +0

    Duygularım, 1> & 2'nin sadece> 2 ve 2'den biraz daha az belirsiz olması. Yok hayır? (Demek istediğim, betiğe bakan bir kişiye neler olduğunu daha net bir şekilde anlatır. Aman, açıkça umursamamaktadır.) –

    +0

    Elbette, buna sahip olmak yeterli - sadece ona ihtiyacınız yok. –

    1

    tipik deyimler şunlardır:

    echo foo >&2   # you don't need to specify file descriptor 1 
    echo foo > /dev/stderr # more explicit, but wordier and less portable 
    
    2

    soru bazı karışıklıklara işaret gibi görünüyor. Stdout'u yeniden yönlendirmek istemiyorsunuz, sadece çıktılarını stttr'ye göndermeniz gerekiyor ... Ama bunun için yeniden yönlendirmeyi kullanmalısınız.

    printf komutu her zaman stdout'una normal çıkış gönderir. Printf budur. İstediğinizi elde etmek için, kabuğun, çıktının nereye gitmesini istediğiniz yere geçici olarak işaret edeceği kabuğunu ayarlamanız gerekir. Geçici olarak söylüyorum dikkat edin. Eğer

    $ printf "Hello World!" >&2 
    

    gibi bir komut yazdığınızda kabuk printf ifadesinde yürütülmesi süresince stdout'u kolu değiştirir. Daha sonra kabuk, bir sonraki komutla devam etmeden önce stdout'un orijinal değerini geri yükler. kalıcı stdout'u yönlendirmek istiyorsanız kabuk bu, kabuk artık stdout'u sapın orijinal değerini hatırlar yürüttü sonra Aslında, özel komutunu

    $ exec >&2 
    

    kullanın.