Çıktı bir dosyaya ve stdout'a nasıl yeniden yönlendirilir


988

Bash'da, arama foostdout'ta bu komuttan herhangi bir çıktı görüntüler.

Çağrı, foo > outputbu komuttaki çıktıları belirtilen dosyaya yönlendirir (bu durumda 'çıktı').

Çıktıyı bir dosyaya yönlendirmenin ve stdout'ta görüntülenmesini sağlamanın bir yolu var mı?


3
Birisi buraya dosya çıktısı almak için buraya gelmişse
Murphy

2
Terminoloji ilgili bir not: Eğer yürütüldüğünde foo > outputveri edilir Stdout'a ve Stdout'a yazılı olduğu adlı dosya output. Olduğunu, dosyaya yazma edilir Stdout'a yazma. Hem stdout'a hem de terminale yazmanın mümkün olup olmadığını soruyorsunuz.
William Pursell

2
@WilliamPursell Emin senin açıklama şeyler geliştirir değilim :-) nasıl bu konuda: o yönlendirmek mümkün olup olmadığını OP soruyor denilen programın bir dosyaya hem stdout çağıran programın (ikincisi stdout'u olmak Stdout'a denilen bir program olur o özel bir şey yapılmadıysa devralın, yani çağrı programı etkileşimli bir bash oturumuysa terminal). Ve belki de çağrılan programın stderr'ını benzer şekilde yönlendirmek isterler ("bu komuttan herhangi bir çıktı" stderr dahil olmak üzere makul olarak yorumlanabilir).
Don Hatch

Yanıtlar:


1379

İstediğiniz komutun adı tee:

foo | tee output.file

Örneğin, yalnızca stdout'u önemsiyorsanız:

ls -a | tee output.file

Stderr'yi dahil etmek istiyorsanız, şunları yapın:

program [arguments...] 2>&1 | tee outfile

2>&1kanal 2'yi (stderr / standart hata) kanal 1'e (stdout / standart çıkış) yönlendirir, böylece her ikisi de stdout olarak yazılır. teeKomut olarak verilen çıktı dosyasına da yönlendirilir .

Ayrıca, günlük dosyasına eklemek istiyorsanız şu şekilde kullanın tee -a:

program [arguments...] 2>&1 | tee -a outfile

173
OP yönlendirilmek "Tüm çıktıyı" istiyorsa, ayrıca kapmak stderr'e gerekir: "ls -lR / 2> & 1 | tee output.file"
James Brady

45
@evanmcdonnal Cevap yanlış değil, gereksinimlerinize bağlı olarak yeterince spesifik veya tam olmayabilir. Çıktının bir dosyaya kaydedilmesinin bir parçası olarak stderr'i istemeyeceğiniz durumlar kesinlikle vardır. Bunu 5 yıl önce cevapladığımda, görevin konusundaki stdout'tan bahsettiği için OP'nin sadece stdout istediğini varsaydım.
Zoredache

3
Üzgünüm, biraz kafam karışmış olabilir. Denediğimde hiç çıktı almadım, belki de hepsi stderr olacaktı.
evanmcdonnal

38
-aÜzerine teeiçerik output.fileyazmak yerine içerik eklemek için argümanı kullanın :ls -lR / | tee -a output.file
kazy

16
Daha $?sonra kullanıyorsanız tee, muhtemelen istediğiniz gibi olmayan durum kodunu döndürür . Bunun yerine kullanabilirsiniz ${PIPESTATUS[0]}.
LaGoutte

501
$ program [arguments...] 2>&1 | tee outfile

2>&1stderr ve stdout akışlarını atar. tee outfilealdığı akışı alıp ekrana ve "outfile" dosyasına yazar.

Muhtemelen çoğu insan budur. Muhtemel durum, bazı programların veya senaryoların uzun süre çok çalışıp çok fazla çıktı üretmesidir. Kullanıcı ilerleme için periyodik olarak kontrol etmek ister, aynı zamanda çıktı bir dosyaya yazılmasını ister.

Sorun (özellikle stdout ve stderr akışlarını karıştırırken) program tarafından akan akışlara güvenilmesidir. Örneğin, Stdout'a tüm yazma edilir ise değil kızardı, ama stderr'e tüm yazıyor olan kızardı, sonra da çıkış dosyasında ve ekrandaki kronolojik sırayla dışarı bitireceğiz.

Program ilerleme durumunu bildirmek için her birkaç dakikada bir yalnızca 1 veya 2 satır çıkarıyorsa kötüdür. Böyle bir durumda, çıktı program tarafından temizlenmezse, kullanıcı saatlerce ekranda herhangi bir çıktı görmez, çünkü hiçbiri saatlerce borudan itilmez.

Güncelleme: Paketin bir unbufferparçası olan program , expectarabelleğe alma sorununu çözecektir. Bu, stdout ve stderr'in ekrana ve dosyaya hemen yazmasına ve birleştirilip yönlendirildiklerinde senkronize kalmasına neden olur tee. Örneğin:

$ unbuffer program [arguments...] 2>&1 | tee outfile

7
Herkes osx için bir 'tamponunu' biliyor mu?
John Mee

7
Tamponlamayı kullanamıyorsanız, GNU coreutils, çıktı arabelleğe almayı önlemek için kullanılabilecek stdbuff adlı bir araç içerir$ stdbuf -o 0 program [arguments...] 2>&1 | tee outfile
Peter

1
OS X kullanıyorsanız, çalıştırdığınız komuta sinyalleri iletmek istemeseniz de, çoğu durumda arabelleksiz kullanımı marjinal olarak daha kolaydır. Benim yorumum daha çok çekirdeğin varsayılan olarak yüklendiği Linux'taki kullanıcılara yönelikti. @Ethan, stdbuf sözdizimi hakkında kafanız karıştıysa bu cevaba bakın: stackoverflow.com/a/25548995/942781
Peter

3
Çıktı arabelleklerini kapatan pythonyerleşik bir seçenek -uolduğunu unutmayın .
fabian789

1
Ekstra kod olmadan oturum açmak istediğim ML modellerinin eğitimi için mutlak cankurtaran, aynı zamanda çalıştırmak için saat / gün boyunca çıktıyı görmek istiyorum, teşekkür ederim!
rokoko

126

Benim için çalışan başka bir yol,

<command> |& tee  <outputFile>

gnu bash kılavuzunda gösterildiği gibi

Misal:

ls |& tee files.txt

'| &' Kullanılırsa, komutun standart çıkışına ek olarak komut1'in standart hatası , komut2'nin standart girişine boru yoluyla bağlanır; o olduğu 2> & 1 için steno |. Standart hatanın standart çıktıya bu örtülü olarak yönlendirilmesi, komut tarafından belirtilen herhangi bir yeniden yönlendirmeden sonra gerçekleştirilir.

Daha fazla bilgi için yeniden yönlendirmeye bakın


10
Daha $?sonra kullanıyorsanız tee, muhtemelen istediğiniz gibi olmayan durum kodunu döndürür . Bunun yerine kullanabilirsiniz ${PIPESTATUS[0]}.
LaGoutte

1
Bu yöntem renkli konsol çıktısını atar, herhangi bir fikir?
shakram02

Deneyin: arabelleğe alma ls -l --color = auto | tee files.txt
Luciano Andress Martini

17

Öncelikle Zoredache çözümünü kullanabilirsiniz , ancak çıktı dosyasının üzerine yazmak istemiyorsanız -a seçeneği ile tee'yi aşağıdaki gibi yazmalısınız:

ls -lR / | tee -a output.file

11

Eklenecek bir şey ...

Paket arabellek öğesinin fedora altındaki bazı paketlerle ilgili sorunları var ve unix sürümlerini redhat ediyorlar.

Sorunları bir kenara koymak

Takip etmek benim için çalıştı

bash myscript.sh 2>&1 | tee output.log

ScDF & matthew teşekkürler teşekkür ederim bana çok zaman kazandırdı ..



3

Bu kullanım senaryosunun beni buraya getirmesinden bu yana bonus cevap:

Bunu başka bir kullanıcı olarak yapmanız gerektiğinde

echo "some output" | sudo -u some_user tee /some/path/some_file

Not yankı senin kadar olacağını ve dosya yazma ne "some_user" olarak gerçekleşecek DEĞİL sen >> "some_file" "some_user" olarak yankı çalıştırın ve sahip çıktı yönlendirmek olsaydı iş dosyası yönlendirme olur çünkü senin gibi.

İpucu: tee ayrıca -a bayrağına eklenmeyi de destekler, eğer dosyadaki bir satırı başka bir kullanıcı olarak değiştirmeniz gerekiyorsa sed'i istediğiniz kullanıcı olarak yürütebilirsiniz.


2

< command > |& tee filename # Bu, içerik olarak komut durumuna sahip bir "dosyaadı" dosyası oluşturur, Bir dosya zaten mevcutsa içeriği kaldırır ve komut durumunu yazar.

< command > | tee >> filename # Bu, dosyaya durum ekler, ancak standart_ çıkış (ekran) üzerinde komut durumunu yazdırmaz.

Ekranda "echo" kullanarak bir şeyler yazdırmak ve bu yankılanan verileri bir dosyaya eklemek istiyorum

echo "hi there, Have to print this on screen and append to a file" 

1

Komut dosyanızın başında böyle bir şey kullanarak bunu tüm komut dosyanız için yapabilirsiniz:

#!/usr/bin/env bash

test x$1 = x$'\x00' && shift || { set -o pipefail ; ( exec 2>&1 ; $0 $'\x00' "$@" ) | tee mylogfile ; exit $? ; }

# do whaetever you want

Bu, stderr ve stdout çıktılarını çağrılan dosyaya yönlendirir mylogfile ve her şeyin aynı anda stdout'a gitmesine izin verir .

Bazı aptal numaralar kullanılır:

  • execyönlendirmeleri ayarlamak için komut kullanmadan kullanın ,
  • teeçıktıları çoğaltmak için kullanın ,
  • komut dosyasını istenen yönlendirmelerle yeniden başlatın,
  • komut dosyasının yeniden başlatılacağını belirtmek için özel bir ilk parametre ( özel bash gösterimi NULtarafından belirtilen basit bir karakter $'string') kullanın (orijinal çalışmanız tarafından eşdeğer bir parametre kullanılamaz),
  • pipefailseçeneği kullanarak komut dosyasını yeniden başlatırken orijinal çıkış durumunu korumaya çalışın .

Çirkin ama bazı durumlarda benim için yararlı.


-13

tee bunun için mükemmel, ama bu da işi yapacak

ls -lr / > output | cat output

10
Bu çıktı zaten mevcut değilse bir hata ve eğer istersen yapmıyorsa, genel olarak saçma. Belki de ";" "|" yerine ?
Robert Gamble

6
A kullansanız bile ;, yavaş komut sırasında çıktı çok gecikecektir.
Brad Koch
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.