Bash ile standart hatayı başka bir sürece nasıl bağlayabilirim?


138

Bir işlemin standart çıkışının başka bir işlem standart girdisine nasıl bağlanacağı iyi bilinmektedir:

proc1 | proc2

Peki ya proc1'in standart hatasını proc2'ye göndermek ve standart çıkışı mevcut konumuna bırakmak istersem ne olur? Şunlar bashboyunca bir komuta sahip olacağını düşünürdünüz :

proc1 2| proc2

Ama ne yazık ki hayır. Bunu yapmanın bir yolu var mı?


rcBaşka bir kabuk olan böyle basit bir yönlendirme yapabilirsiniz . Ör: proc1 |[2] proc2. Hoş değil mi? bashGerçi değil .
— Rolf

Yanıtlar:


169

Ayrıca süreç ikamesi de vardır . Bu, bir işlemin bir dosya yerine geçmesini sağlar. Bir dosyaya aşağıdaki gibi
gönderebilirsiniz stderr:

process1 2> file

Ancak dosya için bir işlemi aşağıdaki gibi değiştirebilirsiniz:

process1 2> >(process2)

stderrHem ekrana hem de bir günlük dosyasına eklenen somut bir örnek

sh myscript 2> >(tee -a errlog)

23
Bu belirtilen soruya doğru cevap verir ve @paxdiablo tarafından kabul edilen cevap olmalıdır
— mmlb

Bunu denedim. İşe yaramadı ( weston --help 2> >(less)) ve kabuğumu kırdı, çıkmak ve tekrar giriş yapmak zorunda kaldım.
— Rolf

1
@ Her ikisinde de klavye varsa weston --helpve lessklavye etkileşimi bekliyorsanız ancak bunlardan sadece 1 tanesi bunu alıyorsa , o zaman garip bir durumda olabilirsiniz. grepBunun yerine böyle bir şeyle test yapmayı deneyin . Ayrıca her iki fare / klavye girişinin de weston yerine 2. komuta geçeceğini görebilirsiniz.
— BeowulfNode42

88

Sen Aşağıdaki hile kullanabilirsiniz takas stdout ve stderr. Sonra normal boru işlevselliğini kullanın.

( proc1 3>&1 1>&2- 2>&3- ) | proc2

Sağlanan stdoutve stderrher ikisi de başlangıçta aynı yere işaret ettiğinde, bu size ihtiyacınız olanı verecektir.

Ne x>ybit yapar dosya tanıtıcısı değiştirmektir xşimdi nerede dosya tanıtıcısı olan bilgi gönderir, böylece yşu anda puan. Özel durumumuz için:

  • 3>&1sadece aşağıdaki son madde işareti için bir yere kaydetmek üzere mevcut tutamağa (orijinal stdout) çıkış verecek yeni bir tutamaç oluşturur .31
  • 1>&2geçerli tanıtıcıya (orijinal stderr) 1çıktı almak için tanıtıcıyı (stdout) değiştirir .2
  • 2>&3-geçerli tutamağa (orijinal stdout) 2çıkış yapmak için tutamağı (stderr) değiştirir , ardından tutamacı kapatır ( sondaki aracılığıyla ).33-

Sıralama algoritmalarında gördüğünüz takas komutu etkili bir şekilde:

temp   = value1;
value1 = value2;
value2 = temp;

3
1>&2-Burada değil, burada kullanmanın değeri nedir 1>&2? 2Hemen yeniden açmak / yeniden atamak istiyorsak, fd'yi neden kapatmak istediğimizi anlamıyorum .
— dubiousjim

1
@dubiousjim, belirli bir durumda hiçbir avantajı yok, ben sadece tutarlı olmak için yaptım şüpheli - dosya tanıtıcısı 3 kapanması onu serbest bırakmak için iyi bir fikirdir.
— paxdiablo

İyi bir nokta, @ovgolovin, o düzenlemeyi yaptığımdan beri kimsenin yedi ay içinde bunu almadığına inanamıyorum. Öneri başına sabit.
— paxdiablo

gcc'nin (sistemimde renklendirilmiş) markasını bu "(3> & 1 1> & 2- 2> & 3-) | daha az -R" iken "(ls -al 3> & 1 1> & 2- 2> & 3-) | less -R "beklendiği gibi çalışır.
— senkronize olmayan

Görünüşe göre, açıklamalarınız ikinci iki yönlendirme için öne çıkıyor. 1> & 2- dosya tutamağı 2'yi (orijinal stderr) 1'e (orijinal stdout) ayarlar 2> & 3- dosya tutamağı 3'ü (kopyalanan stdout) 2'ye (orijinal stderr) ayarlar. Yanılıyorsam lütfen beni düzeltin. btw, 2'deki çizgi, stdout'tan gelen verilerle doldurulurken yeni stderr verilerinin bu arabelleğe gönderilmesini önlemek olduğunu tahmin ediyorum.
— aghsmith

70

Bash 4 şu özelliğe sahiptir:

`| & 'Kullanılırsa, komut1'in standart hatası, komut2'nin standart girişine boru yoluyla bağlanır; 2> & 1 | için kısaltmadır. Standart hatanın bu örtük yeniden yönlendirmesi, komut tarafından belirtilen yeniden yönlendirmelerden sonra gerçekleştirilir.

zsh da bu özelliğe sahiptir.

-

Diğer / eski mermilerle, bunu açıkça

FirstCommand 2> & 1 | OtherCommand


14
Docs okumasını, bu standart hatasını hem yapar ve sadece stderr'e aksine çıktı, ama onun güzel bilmek. Sanırım bash 4'e bakmaya başlama zamanı.
— paxdiablo

Şu anki bash kılavuzunda "| & kullanılıyorsa, komutun standart çıktısına ek olarak standart hatası, command2'nin standart girişine bağlanır" yazıyor. OP'nin istediği bu değil.
— Peter - Monica'yı

@ PeterA.Schneider: OP, "standart çıktıyı geçerli konumuna bırak" dedi ve belirsiz olabilir.
— sonraki duyuruya kadar duraklatıldı.

Herhangi bir belirsizlik göremiyorum. Öneriniz (1) iki akışı birleştirir . (2) birleştirilmiş verileri başka bir yere, muhtemelen başka bir yere OtherCommandyazar . Yani aynı veri değil ve potansiyel olarak başka bir yere gidiyor. Bu OP'nin dileğinin tam tersi değil, değil mi?
— Peter - Monica'yı

@ PeterA.Schneider: Standart çıktının mevcut konumu başka nerede? Eğer proc1Stdout'a ve stderr'e çıkışları ve stderr ait stdin'e gitmek istiyorum proc2(Proc1 en stdout'u nereye olan), daha sonra cevabım o yapar. Ben ne o OP verdi istedi diye belki de ne için, demek istemek için. Burada potansiyel belirsizlik yatıyor. OP cevabını kabul takasları olan stdout'a ve stderr değil diye ne istedi.
— sonraki duyuruya kadar duraklatıldı.

27

Takas sorunu çözdüğü için harika. Orijinal stdout'a bile ihtiyacınız yoksa, bunu şu şekilde yapabilirsiniz:

proc1 2>&1 1>/dev/null | proc2

Düzen hayati önem taşır; istemezsin:

proc1 >/dev/null 2>&1 | proc1

Bu her şeyi yönlendirecek gibi /dev/null!


0

Bunların hiçbiri gerçekten iyi çalışmadı. İstediğini yapmanın en iyi yolu:

(command < input > output) 2>&1 | less

Bu yalnızca commandklavye girişine ihtiyaç duyulmayan durumlarda çalışır . Örneğin:

(gzip -d < file.gz > file) 2>&1 | less

gzip hatalarını daha az

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.