Nasıl başarabilirim
cmd >> file1 2>&1 1>>file2
Yani, stdout ve stderr bir dosyaya (dosya1) yönlendirmeli ve sadece stdout (dosya2) bir başkasına yönlendirmeli (her ikisi de ekleme modunda)?
Nasıl başarabilirim
cmd >> file1 2>&1 1>>file2
Yani, stdout ve stderr bir dosyaya (dosya1) yönlendirmeli ve sadece stdout (dosya2) bir başkasına yönlendirmeli (her ikisi de ekleme modunda)?
Yanıtlar:
Sorun, çıktınızı yeniden yönlendirdiğinizde, bir sonraki yönlendirme için artık kullanılamıyor olmasıdır. Şunları yapabilirsiniz için boru tee
bir altkabuk ikinci yönlendirme için çıkışını tutmak için:
( cmd | tee -a file2 ) >> file1 2>&1
veya çıkışı terminalde görmek isterseniz:
( cmd | tee -a file2 ) 2>&1 | tee -a file1
İlk komutun stderr'inin eklenmesini önlemek tee
için file1
, komutunuzun stderr'ini bazı dosya tanımlayıcılarına yönlendirmelisiniz (örneğin 3) ve daha sonra bunu tekrar stdout'a eklemelisiniz:
( 2>&3 cmd | tee -a file2 ) >> file1 3>&1
# or
( 2>&3 cmd | tee -a file2 ) 3>&1 | tee -a file1
(teşekkürler @ fra-san)
İle zsh
:
cmd >& out+err.log > out.log
Ekleme modunda:
cmd >>& out+err.log >> out.log
Içinde zsh
ve mult_ios
seçeneği devre dışı bırakılmadığı takdirde, bir dosya tanıtıcısı (burada 1) yazmak için birkaç kez yönlendirildiğinde, kabuk tee
çıktıyı tüm hedeflere çoğaltmak için bir yerleşik uygular .
cmd >& file1 > file2
Yapabilecekleriniz: stdout etiketi (UNBUFFERED sed, yani:) kullanarak sed -u ...
, stderr'nin de stdout'a (etiketli, bu etiketleme sed'inden geçmediği için etiketlenmemiş) gitmesi ve sonuçta ortaya çıkan logfile'deki 2'yi ayırt edebilmesi gerekir.
Aşağıdakiler yavaştır ( yavaştır (ciddiyetle optimize edilebilir, bir süre yerine perl betiği kullanarak); yapın ...; her biri için alt kabuklar ve komutlar ortaya çıkacak!), Garip bir ": vs. Ama bu (ben bir yeniden adlandırma stdout'ta ve daha sonra diğer birinde kendisine stderr'e "yoluyla falled" eklemek için 2 {} aşamaları ihtiyaç görünüyor) kavramının kanıtı ", yani tutmaya çalışacağız stdout ve stderr'den mümkün olduğu kadar çıktının siparişi:
#basic principle (some un-necessary "{}" to visually help see the layers):
# { { complex command ;} | sed -e "s/^/TAGstdout/" ;} 2>&1 | read_stdin_and_redispatch
#exemple:
# complex command = a (slowed) ls of several things (some existing, others not)
# to see if the order of stdout&stderr is kept
#preparation, not needed for the "proof of concept", but needed for our specific exemple setup:
\rm out.file out_AND_err.file unknown unknown2
touch existing existing2 existing3
#and the (slow, too many execs, etc) "proof of concept":
uniquetag="_stdout_" # change this to something unique, that will NOT appear in all the commands outputs...
# avoid regexp characters ("+" "?" "*" etc) to make it easy to remove with another sed later on.
{
{ for f in existing unknown existing2 unknown2 existing3 ; do ls -l "$f" ; sleep 1; done ;
} | sed -u -e "s/^/${uniquetag}/" ;
} 2>&1 | while IFS="" read -r line ; do
case "$line" in
${uniquetag}*) printf "%s\n" "$line" | tee -a out_AND_err.file | sed -e "s/^${uniquetag}//" >> out.file ;;
*) printf "%s\n" "$line" >> out_AND_err.file ;;
esac;
done;
# see the results:
grep "^" out.file out_AND_err.file
ls unknown
stderr üzerine bir şey yazdırmak için bu kadar karmaşık kullanım halini ( ) kullanıyorsunuz ? >&2 echo "error"
iyi olurdu. (2) tee
aynı anda birden fazla dosyaya ekleyebilir. (3) Neden sadece cat
değil grep "^"
? (4) stderr çıkışı başladığında betiğiniz başarısız olur _stdout_
. (5) Neden?
ls loop
hem stdout hem de stderr çıktısını (alternatif olarak) kontrollü bir düzende karıştırır, böylece stdout 2 etiketlemesine rağmen bu stderr / stdout sırasını tuttuğumuzu kontrol edebiliriz) düzenli kuyruk (örneğin, aix üzerinde). 3): grep "^", her iki dosya adını da gösterir. 4): bu değişken tarafından değiştirilebilir. 5): kıvrılmış örnek, test ettiğim eski hortumlarda (örneğin, eski aix) çalışır (perl mevcut değildir).
uniquetag="banaNa11F453355B28E1158D4E516A2D3EDF96B3450406
...)
Çıktı sırası şöyle olmalıdır: stdout, stderr ; sadece yeniden yönlendirmeyle ilgili bir çözüm yoktur.
Stderr geçici bir dosyaya kaydedilmelidir
cmd 2>>file-err | tee -a file1 >>file2
cat file-err >> file1
rm file-err
Açıklama:
Bir çıktıyı (stdout veya stderr gibi bir fd) iki dosyaya yeniden yönlendirmenin tek yolu onu yeniden oluşturmaktır . Komut tee
, bir dosya tanımlayıcı içeriğini yeniden oluşturmak için doğru araçtır. Bu nedenle, iki dosya üzerinde bir çıktının olması için ilk fikir kullanmak:
... | tee file1 file2
Bu, tee stdinini, tee çıktısını hala kullanılmayan bırakarak her iki dosyaya (1 ve 2) kopyalar. Ancak eklememiz (kullanmamız -a
) ve yalnızca bir kopyaya ihtiyacımız var. Bu her iki sorunu da çözer:
... | tee -a file1 >>file2
tee
Stdout'u (tekrarlanacak olanı) tedarik etmek için stderr'i doğrudan komutun dışında tüketmemiz gerekir. Bir yol, sipariş önemli değilse (çıktı sırası (muhtemelen)) oluşturulduğu gibi korunacak, hangisi önce çıktı saklanacaktır). Ya:
cmd 2>>file1 | tee -a file2 >>file1
cmd 2>>file1 > >( tee -a file2 >>file1 )
( cmd | tee -a file2 ) >> file1 2>&1
Seçenek 2 yalnızca bazı kabuklarda çalışır. Seçenek 3, ek bir alt kabuk kullanır (daha yavaş) ancak dosya adlarını yalnızca bir kez kullanır.
Ama eğer stdout'u gerekir ilk biz sonunda dosyaya eklemek için mağaza stderr'e gerek (hangisi sipariş çıkış üretilir) (birinci çözüm yayınlanmıştır).
sponge
(cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err
Çeşitlilik adına:
Sisteminiz destekliyorsa /dev/stderr
, o zaman
(cmd | tee -a /dev/stderr) 2>> file1 >> file2
çalışacak. 'Nın standart çıktısı cmd
hem boru hattının hem de stdout'una gönderilir. cmd
Baypasların standart hatası tee
boru hattının stderrini atlar ve çıkar.
Yani
cmd
, vecmd
, karıştırılan stdout ve stderr'dir .Bu, bu akışları doğru dosyalara göndermenin basit bir meselesidir.
Neredeyse böyle bir yaklaşımda olduğu gibi ( Stéphane'nin cevabı dahil )
file1
sıra dışı olabilir.
out+err
ve neout
anlama geldiğini bulamıyorum. Dosya isimleri? Yönlendirilecek akışlar?