Proses ikameli çıktı sırası


11

Bu genellikle çalıştırmak için ne olduğunu grepve wciki kez taramak zorunda kalmadan bir dosya üzerinde

<file.txt  tee >(grep LITERAL) >(wc -l) >/dev/null

Ancak, bu

EXEC LITERAL
32

bazen ve

32
EXEC LITERAL

Diğer zamanlarda. ( grepKaynağından gelen çıktı wcilk örnekte çıktıdan önce , ikinci durumda ise tersi olur.)

Öte yandan, yönlendirmeler ve dosya tanımlayıcıları ile

{ { <file.txt tee /dev/fd/3 | grep LITERAL >&4; } 3>&1 | wc -l ;} 4>&1 

Hep alıyorum

EXEC LITERAL
32

Çıktı sırasının öngörülebilir olmasını tercih ediyorum, ancak ikinci yaklaşımla garanti ediliyor mu?

Yanıtlar:


4

Hem de

<file.txt  tee >(grep LITERAL) >(wc -l) >/dev/null

Ve:

{ { <file.txt tee /dev/fd/3 | grep LITERAL >&4; } 3>&1 | wc -l ;} 4>&1

Tüm tee, grepve wceş zamanlı olarak başlatılır. O zaman önemli olan sonunda ne olacağı.

wcsonucu yalnızca standart girdisinde dosya sonu gördüğünde yazdırır. İlk durumda, o zaman teeçıkışlar, çünkü o teezaman okunan fdborunun diğer ucunda kapatacaktır wc(işlem ikamesi ile başlar). grepÇıktısını yazılı olarak bırakın, o zamana kadar tüm girdilerini okuyacak bir garanti yoktur (boruların oldukça fazla miktarda veri tutabileceği ve wcmuhtemelen daha hızlı olacağı göz önüne alındığında grep)

İkinci durumda, wcokuduğu boruya giden tüm yazarlar borunun ucunu kapattıklarında dosya sonu görecektir. Bu durumda yine de birkaç yazar var. tee( /dev/fd/3fd 3 üzerinden ve fd 3 üzerinden) ve grepaynı zamanda fd3'ü boruya açık olan wc(herhangi bir şekilde kullanılmasa da, yazmama izin verin). İç kısım {muhtemelen fd3 açık olacak teeve hem de hem de bekleyecek ekstra bir alt kabuk işlemine neden olacaktır grep.

Bu wc, satır numarasını ancak grepçıktıktan sonra yazacağı anlamına gelir .

Doğru şekilde yazmış olsaydınız, yani açık olması gerekmeyen fds'leri kapatarak:

{ { <file.txt tee /dev/fd/3 4>&- | 
   grep LITERAL >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1

O zaman sipariş, alt kabuk sürecini optimize eden mermilerde garanti edilmezdi. Ancak, bildiğim tek kabuk borular için soket çiftlerini kullanıyor , ksh93ancak en azından orada Linux'ta çalışmayacak.ksh93/dev/fd/3

, Değiştirmek ne süreçleri çalıştıran görmek için grepile ps:

$ { { <file.txt tee /dev/fd/3 4>&- | ps -H >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1
  PID TTY          TIME CMD
 8727 pts/5    00:00:00 bash
 8815 pts/5    00:00:00   bash
 8817 pts/5    00:00:00     tee
 8818 pts/5    00:00:00     ps
 8816 pts/5    00:00:00   wc

İle bash, ekstra kabuk işlemini görebilir ve fd 3'te borunun da açıldığını görebilirsiniz:

$ (p=$BASHPID; { { <file.txt tee /dev/fd/3 4>&- | lsof -ag "$p" -d3 >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1)
COMMAND  PID PGID     USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
bash    9843 9842 chazelas    3w  FIFO    0,8      0t0 153304 pipe
tee     9845 9842 chazelas    3w  FIFO    0,8      0t0 153304 pipe
lsof    9846 9842 chazelas    3r   DIR    0,3        0      1 /proc

Teşekkürler. "Uygun örneğinizde" ne grep LITERAL >&4 3>&- 4>&-demek, fd 4 hem kullanılmış hem de kapalı görünüyor?
iruvar

@ 1_CR, sonra >&4, kısaltması 1>&4, grepfd 1 ve 4 aynı kaynağı (kabuğun ilk stdout'u) gösterir. grepfd 4'ünün hiçbir şeye açık olması gerekmez. Onunla hiçbir şey yapmaz, bu yüzden onu kapatıyoruz4>&-
Stéphane Chazelas

Bu son komut satırı şifreli bir sihirdir.

-1

Öngörülebilir bir sipariş almak için

(<file.txt  tee >(grep LITERAL) >(wc -l) >/dev/null)|sort

Belki yeterince açık değildim. Komut çıktılarının sırası açısından tahmin edilebilir sıralama (yani wc'den çıktıdan önce grep çıktısı) demek istedim.
Sıralı

az önce gnu.org/software/bash/manual/bashref.html#Command-Grouping buldum , {} operatörleri ile (bu örnekte) ilk önce <file.txt tee / dev / fd yaptığınızdan emin olun. / 3 | grep LITERAL> & 4; ve bu yapıldığında wc diyorsunuz, bu yüzden orijinal sorunuzu cevaplamak için evet anlayışım garanti ediliyor
Thorsten Staerk

1
@ThorstenStaerk, bulduğunuz ekstra bilgiyi cevabınıza ekleyebilir misiniz?
terdon

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.