Kolejność wyjściowa z podstawieniem procesu


11

To, co zwykle zrobić, aby uruchomić grepi wcna pliku bez konieczności skanowania dwukrotnie

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

Jednak to daje

EXEC LITERAL
32

czasami i

32
EXEC LITERAL

w innym czasie. (Wyjście z greppoprzedza wyjście z wcw pierwszej instancji i odwrotnie w drugiej.)

Z drugiej strony, z przekierowaniami i deskryptorami plików

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

Zawsze wydaje mi się, że rozumiem

EXEC LITERAL
32

Wolę, aby kolejność produkcji była przewidywalna, ale czy jest gwarantowana przy drugim podejściu?

Odpowiedzi:


4

Zarówno

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

I:

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

Wszystko tee, grepi wcsą uruchamiane jednocześnie. Liczy się to, co stanie się na końcu.

wcwypisze wynik tylko wtedy, gdy zobaczy koniec pliku na swoim standardowym wejściu. W pierwszym przypadku następuje teewyjście, ponieważ wtedy teezamknie fdsię na drugim końcu potoku, który wcczyta (rozpoczęte przez podstawienie procesu). Nie ma gwarancji, że do greptego czasu przeczyta wszystkie dane wejściowe, nie mówiąc już o zapisaniu danych wyjściowych (biorąc pod uwagę, że potoki mogą przechowywać dość dużą ilość danych, a to wcprawdopodobnie będzie szybsze niż grep)

W drugim przypadku, wczobaczysz koniec pliku, gdy wszyscy piszący do potoku, z którego on czyta, zamknęli swój koniec potoku. W takim przypadku jest jednak kilku pisarzy. tee(przez jego fd otwarty na /dev/fd/3i przez jego fd 3), grepktóry również ma swój fd3 otwarty na potok do wc(chociaż nie korzysta z niego, nie mówiąc już o napisaniu do niego). Wewnętrzny {prawdopodobnie spowoduje dodatkowy proces podpowłoki, który również będzie miał fd3 otwarte i będzie czekać na oba teei grep.

Oznacza to, że wczapisze numer linii dopiero po grepwyjściu.

Czy napisałeś to we właściwy sposób, to znaczy zamykając fds, które nie wymagały otwarcia:

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

Wtedy kolejność nie byłaby zagwarantowana w powłokach, które optymalizują proces podpowłoki. Jednak jedyną powłoką, którą znam, jest to, ksh93że ksh93korzysta z par gniazd dla potoków, więc /dev/fd/3nie będzie tam działać przynajmniej w systemie Linux.

Aby zobaczyć, jakie procesy są uruchomione, można wymienić grepz 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

Za pomocą bash, możesz zobaczyć ten dodatkowy proces powłoki, i możesz zobaczyć, że ma również otwartą rurkę na fd 3 z:

$ (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

Dzięki. Co w twoim „właściwym przykładzie” grep LITERAL >&4 3>&- 4>&-oznacza, że ​​fd 4 wydaje się być używany i zamknięty?
iruvar,

@ 1_CR po >&4, skrót 1>&4, grepjest fd 1 i 4 wskazują na ten sam zasób (w powłoce początkowy stdout). grepnie musi mieć otwartego fd 4 na nic. Nic z tym nie robi, więc zamykamy to4>&-
Stéphane Chazelas,

Ta ostatnia linia poleceń to tajemnicza magia.

-1

Aby uzyskać przewidywalne zamówienie, użyj

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

Być może nie byłem wystarczająco jasny. Miałem na myśli przewidywalną kolejność pod względem kolejności wyników poleceń (tj. Wyjście z grep przed wyjściem z wc). Nie potrzebuję sortować połączonych danych wyjściowych
iruvar,

właśnie znalazłem gnu.org/software/bash/manual/bashref.html#Command-Grouping , mówi mi, że za pomocą operatorów {} upewniasz się (w tym przypadku), że najpierw wykonujesz <file.txt tee / dev / fd / 3 | grep LITERAL> & 4; a kiedy to zrobisz, zadzwonisz do wc, więc aby odpowiedzieć na twoje pierwotne pytanie, tak, jest to dla mnie zrozumiałe
Thorsten Staerk

1
@ThorstenStaerk czy możesz dodać dodatkowe informacje, które znalazłeś do swojej odpowiedzi?
terdon

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.