Stdout ve stderr'yi Bash ile bir dosyaya nasıl yönlendirebilir ve ekleyebilirim?


1533

Stdout'u Bash'ta kesilmiş bir dosyaya yönlendirmek için şunu kullanmayı biliyorum:

cmd > file.txt

Bir dosyaya ekleyerek Bash'deki stdout'u yeniden yönlendirmek için şunu kullanmayı biliyorum:

cmd >> file.txt

Her iki yönlendirmek için stdout'u ve stderr'yi bir kesilmiş dosyaya, ben kullanımına biliyorum:

cmd &> file.txt

Nasıl hem yönlendiririm stdout ve stderr bir dosyaya ekleme? cmd &>> file.txtbenim için çalışmadı.


37
&> Outfile Bash (ve diğerleri) belirli bir kod olduğunu ve taşınabilir değil not etmek istiyorum. (Ekleme cevapları benzer) taşınabilir gitmek için yol her zaman ve hala> ÇıkışDosyası 2> & 1
TheBonsai

Yanıtlar:


1997
cmd >>file.txt 2>&1

Bash yönlendirmeleri soldan sağa aşağıdaki gibi yürütür:

  1. >>file.txt: file.txtEkleme modunda açın ve stdoutoraya yönlendirin .
  2. 2>&1: Yönlendirme stderriçin "nereye stdoutanda oluyor" . Bu durumda, ekleme modunda açılan bir dosyadır. Başka bir deyişle, şu anda kullanılan &1dosya tanımlayıcısını yeniden stdoutkullanır.

33
harika çalışıyor! ama bunu anlamanın bir yolu var mı yoksa buna atomik bash yapısı gibi davranmalı mıyım?
flybywire

181
Basit yönlendirme, yönlendirme ifadeleri her zaman olduğu gibi soldan sağa doğru değerlendirilir. >> dosya: Kırmızı. Dosyaya STDOUT (ekleme modu) (1 >> dosyası kısaltması) 2> & 1: Kırmızı. STDERR - "stdout nereye gider" - "STDERR'ı STDOUT'a yönlendir" yorumunun yanlış olduğunu unutmayın.
TheBonsai

31
"Çıktıyı (stdout, dosya tanımlayıcı 1) file.txt dosyasına ekle ve stderr'i (dosya tanımlayıcı 2) fd1 ile aynı yere gönder" der.
sonraki duyuruya kadar duraklatıldı.

2
@TheBonsai Peki ya STDERR başka bir dosyaya yönlendirmek gerekir ama ekleme? Mümkün mü?
arod

41
eğer bunu yaparsanız cmd >>file1 2>>file2istediğinizi başarmalısınız.
Woodrow Douglass

367

Bash sürümünüze bağlı olarak bunu yapmanın iki yolu vardır.

Klasik ve taşınabilir ( Bash pre-4 ) yolu:

cmd >> outfile 2>&1

Bir taşınabilir olmayan bir şekilde, ile başlayarak Bash 4 olduğu

cmd &>> outfile

(analog olarak &> outfile)

İyi kodlama stili için,

  • taşınabilirliğin bir sorun olup olmadığına karar verin (klasik yolu kullanın)
  • Bash pre-4 için bile taşınabilirliğin bir endişe olup olmadığına karar verin (klasik yolu kullanın)
  • hangi sözdizimini kullanırsanız kullanın, aynı komut dosyasında değiştirmeyin (karışıklık!)

Betiğiniz zaten başlıyorsa #!/bin/sh(amaçlanmış olsun ya da olmasın), Bash 4 çözümü ve genel olarak Bash'a özgü herhangi bir kod gitmek için bir yol değildir.

Ayrıca Bash 4'ün &>>sadece daha kısa bir sözdizimi olduğunu unutmayın - yeni bir işlevsellik veya bunun gibi bir şey sunmaz.

Sözdizimi (diğer yönlendirme sözdiziminin yanında): http://bash-hackers.org/wiki/doku.php/syntax/redirection#appending_redirected_output_and_error_output


8
& >> ve >> ile tutarlı olduğundan & >> tercih ediyorum. 'Çıktı ve hataları bu dosyaya ekle' ifadesini 'çıktıya hata gönder, bu dosyaya çıktı ekle' den daha kolaydır. Linux genellikle Bash güncel versiyonunu sahipken Not OS X, bu yazının yazıldığı, yine de el yüklü aracılığıyla homebrewleri vb bash 4 gerektirir
mikemaccana

Daha kısa ve satır başına sadece iki alan olduğu için daha çok seviyorum, bu yüzden örneğin zsh "& >>" 'den ne yapar?
Phillipp

Ayrıca, bir cron işinde, sisteminizde Bash 4 olsa bile 4 öncesi sözdizimini kullanmanız gerektiğini unutmayın.
hyperknot

5
@zsero cron bash'ı hiç kullanmaz ... kullanır sh. Sen prepending varsayılan kabuk değiştirebilir SHELL=/bin/bashiçin crontab -edosyanın.
Ray Foss

89

Bash'te farklı dosyalara yönlendirmelerinizi açıkça belirtebilirsiniz:

cmd >log.out 2>log_error.out

Ekleme:

cmd >>log.out 2>>log_error.out

6
İlk seçeneği kullanarak iki akışı aynı dosyaya yeniden yönlendirmek, ilk seçeneğin ikincinin üstüne "yazmasına, içeriğin bir kısmının veya tamamının üzerine yazmasına neden olur. Kullanım log.out 2> log.out >> cmd yerine.
Orestis P.

3
Yakaladığınız için teşekkürler; haklısın, biri diğerini tıkayacak. Ancak, komutunuz da çalışmaz. Aynı dosyaya yazmanın tek yolunun daha önce verilmiş olduğunu düşünüyorum cmd >log.out 2>&1. İlk örneği kaldırmak için cevabımı düzenliyorum.
Aaron R.

65

Bash 4'te (ve ZSH 4.3.11'de):

cmd &>>outfile

kutunun dışında


2
@all: bu iyi bir cevap, çünkü bash ile çalışıyor ve kısadır, bu yüzden açıkça bash'dan bahsettiğinden emin olmak için düzenledim.
mikemaccana

10
@mikemaccana: TheBonsai'nin cevabı 2009'dan beri bash 4 çözümünü gösteriyor
jfs

52

Bu iyi çalışmalıdır:

your_command 2>&1 | tee -a file.txt

Tüm günlükleri file.txt dosyasında saklayacak ve onları terminale dökecektir .


Çıkışı terminalde de görmek istiyorsanız, doğru cevap budur. Ancak, bu aslında sorulan soru değildi.
Mikko Rantalainen

25

Bunu dene

You_command 1>output.log  2>&1

&> X.file kullanımınız bash4'te çalışır. bunun için özür dilerim : (

İşte bazı ek ipuçları.

0, 1, 2 ... 9 bash dosya tanımlayıcılarıdır.

0 duruyor stdin, 1 duruyor stdout, 2 duruyor stderror. Diğer geçici kullanımlar için 3 ~ 9 yedektir.

Herhangi bir dosya tanımlayıcı, operatör >veya >>(append) kullanılarak başka bir dosya tanımlayıcıya veya dosyaya yeniden yönlendirilebilir .

Kullanım: < file_descriptor > > < dosyaadı | & file_descriptor >

Lütfen http://www.tldp.org/LDP/abs/html/io-redirection.html adresine bakın


Örneğiniz OP'nin istediği işlemden farklı bir şey yapacaktır: stderr dosyasını You_commandstdout'a ve stdout'u You_commanddosyaya yönlendirecektir output.log. Ayrıca, dosyaya eklenmeyecek ancak üzerine yazacak.
pabouk

Doğru: Dosya tanımlayıcı , diğer tüm dosyalar için 3'ten fazla olan herhangi bir değer olabilir.
Itachi

5
Yanıtınız en yaygın çıktı yeniden yönlendirme hatasını gösterir: STDERR'ı şu anda STDOUT'un işaret ettiği yere ve yalnızca STDOUT'u dosyaya yönlendirdikten sonra yeniden yönlendirmek. Bu, STDERR'ın aynı dosyaya yeniden yönlendirilmesine neden olmaz. Yönlendirmelerin sırası önemlidir.
Jan Wikholm

1
Bu, önce STDERROR'u STDOUT'a, ardından STDOUT'u bir dosyaya yönlendirmesi gerektiği anlamına gelir. 1 > output.log 2>&1
Quintus.Zhou

1
@ Quintus.Zhou Yup. Sürümünüz, hata ayıklama ve aynı zamanda dosyalama yönlendirir.
Alex Yaroshevich

11

Neredeyse on yıl içinde hiç kimsenin bu yaklaşımı henüz yayınlamamasına şaşırdım:

Kullanılamayan yerlerde bash'ın eski sürümlerini kullanıyorsanız &>>şunları da yapabilirsiniz:

(cmd 2>&1) >> file.txt

Bu yumurtlar bir alt kabuk, bu geleneksel yaklaşımından daha az verimli yüzden cmd >> file.txt 2>&1ve bundan ötürü olacak ihtiyaç anki kabuğu değiştirmek için bu komutlar için değil iş (örneğin cd, pushd), ancak bu yaklaşım bana daha doğal ve anlaşılır hisseder:

  1. Stderr'ı stdout'a yönlendirin.
  2. Bir dosyaya ekleyerek yeni stdout'u yeniden yönlendirin.

Ayrıca, parantezler, özellikle stdout ve stderr'i başka bir komuta bağlamak istiyorsanız, sipariş belirsizliğini kaldırır.


Bu uygulama, sistemin çalışması için fazladan bir işleme neden olur. Sözdizimini kullanmak cmd >> file 2>&1tüm kabuklarda çalışır ve çalıştırmak için fazladan bir işlem gerekmez.
Mikko Rantalainen

@MikkoRantalainen Zaten bir subshell ürettiğini ve daha az verimli olduğunu açıkladım. Bu yaklaşımın amacı, eğer verimlilik çok önemli değilse (ve nadiren de olsa), bu yolun hatırlanması daha kolay ve yanlış yapılması daha zordur.
jamesdlin
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.