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.