Standart çıktıyı kesmeden bash -x çıktısını günlük dosyasına gönder


12

Komut dosyasını çalıştıran bir kullanıcının gördüğü standart çıktıyı değiştirmezken, -x seçeneğiyle bir bash komut dosyası çalıştırarak görüntülenen bilgileri göndermenin bir yolu var mı?

Bu sık sık kullandığımız bir bash betiğinde uygulamak istediğiniz bir hata ayıklama özelliğidir.

Çok takdir etmek.

Yanıtlar:


21

-X çıktısı stdout'a değil, stderr'a gider. Ancak bu bile bir sorun olabilir - bol miktarda komut dosyası stderr içeriğine ve bazı durumlarda hata ayıklama ve stderr akışlarının birbirine karışması için dağınıklığa bağlı olacak.

Bash sürümleri> 4.1 farklı bir çözüm sunar: BASH_XTRACEFD ortam değişkeni, hata ayıklama akışını göndermek için kullanılacak bir dosya tanımlayıcı belirtmenize olanak tanır. Bu bir dosya veya boru ya da istediğiniz başka bir unix-y iyiliği olabilir.

# Use FD 19 to capture the debug stream caused by "set -x":
exec 19>/tmp/my-script.log
# Tell bash about it  (there's nothing special about 19, its arbitrary)
export BASH_XTRACEFD=19

# turn on the debug stream:
set -x

# run some commands:
cd /etc
find 
echo "Well, that was fun."

# Close the output:
set +x
exec 19>&-

# See what we got:
cat /tmp/my-script.log

Biraz daha uğraşarak, stdout ve / veya stdin akışlarında bir 'tee' yapmak ve bunları hata ayıklama çıktısıyla serpiştirmek gibi başka şeyler yapabilirsiniz, böylece günlüğünüz daha eksiksiz olur. Bununla ilgili daha fazla ayrıntı için bkz. Https://stackoverflow.com/questions/3173131/redirect-copy-of-stdout-to-log-file-from-within-bash-script-itself .

Bu yaklaşımın alternatiflere göre en büyük avantajı, hata ayıklama çıktısını stdout veya stderr içine enjekte ederek komut dosyanızın davranışında değişiklik riskini almamanızdır.


Ayrıca , dosya için kullanılmayan bir dosya tanımlayıcısının nasıl bulunacağı ile ilgili olarak buraya bakın .
jarno

Dosya tanımlayıcıyı (yani satırı exec 19>&-) kapatmak gerekli mi? Benim durumumda, komut dosyası bittiğinde otomatik olarak kapanır.
jarno

1
Yukarıda gösterilen kod, bir komut dosyası çalıştırdığınızı veya komut dosyasının ne kadar uzun sürebileceğini varsaymaz. Bu parçacığın ne yaptığını yaparsanız ve bunu bir komut dosyasına koyarsanız, tüm kabuk betiğin sonunda kaybolduğu için kapatılmalıdır. Bu durumda, kolu kesinlikle kapatmanız gerekmez. Ancak genel olarak bir kaynağa kodlama yaparken, açtığınız şeyi kapatmak iyi bir uygulamadır, çünkü o zaman kodunuz temizlik işleminin önemli olduğu daha geniş bir bağlamda kullanılabilir.
Stabledog

Neden BASH_XTRACEFD'yi dışa aktarıyorsunuz? Neden bunun için değer ayarlamıyorsunuz?
jarno

Her neyse, dosya tanımlayıcıyı kapatmanın alternatif bir yolu, BASH_XTRACEFD için yeni bir değer (örn. Null) ayarlamak veya ayarını kaldırmaktır.
jarno

4

set -xstandart çıktıya hiçbir şey göndermez, bu yüzden sorun yoktur. Ne vermez yapmak varsayılan olarak konsola gider standart hata, yazma olduğunu.

Yapmak istediğiniz şey stdout'u şu şekilde başka bir dosyaya yönlendirmektir:

/bin/sh -x /my/script/file 2>/my/log/file

1

Bkz man tee.

Gibi çalıştırın tee commandname filenameve çıktı komutları görüntülemek stdoutve de içine yazacaktır filename.

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.