Порядок виводу із заміною процесу


11

Це те, що я зазвичай роблю для запуску grepта wcфайлу, не потребуючи його двічі сканувати

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

Однак це дає

EXEC LITERAL
32

іноді і

32
EXEC LITERAL

в інший час. (Вихід з grepпередує виходу з wcпершої інстанції і навпаки у другому.)

З іншого боку, з перенаправленнями та дескрипторами файлів

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

Я, здається, завжди отримую

EXEC LITERAL
32

Я вважаю за краще, щоб вихідний порядок був передбачуваним, але це гарантується другим підходом?

Відповіді:


4

В обох

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

І:

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

Усі tee, grepі wcпочинаються одночасно. Важливо тоді, що відбувається в кінці.

wcбуде друкувати результат лише тоді, коли він побачить кінець файлу на своєму стандартному вході. У першому випадку це коли teeзакінчується, тому що тоді teeвін закриє його fdна іншому кінці труби, з wcякої читається (починається з заміни процесу). До того часу немає жодної гарантії, що grepпрочитала б усі його дані, не кажучи вже про те, що вони написали свої дані (враховуючи, що труби можуть містити досить великий об'єм даних, і це wc, швидше за все, буде швидше grep)

У другому випадку wcпобачиться кінець файлу, коли всі письменники, які він читає, закрили свій кінець труби. Однак у цьому випадку є кілька авторів. tee(через його fd open on /dev/fd/3і через fd 3) і grepякий також має fd3 відкритих до труби wc(хоча він не використовує жодного використання, не кажучи вже про це). Внутрішня {, швидше за все, спричинить додатковий процес підключення, який також матиме fd3 відкритих і буде чекати як teeі, і grep.

Це означає, що wcномер його рядка grepбуде записаний лише після виходу з нього.

Якби ви написали це належним чином, тобто закривши fds, який не потребував відкриття:

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

Тоді замовлення не було б гарантоване в оболонках, які оптимізують процес передплати. Однак, єдиною оболонкою, яку я знаю, є, ksh93але вона ksh93використовує пари сокетів для труб, тож /dev/fd/3там не буде працювати принаймні на Linux.

Щоб побачити, які процеси запущені, ви можете замінити grepна 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

З bash, ви можете бачити цей додатковий процес оболонки, і ви також можете відкрити трубу на fd 3 за допомогою:

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

Спасибі. Що у вашому "власному прикладі", що grep LITERAL >&4 3>&- 4>&-означає, що fd 4 видається як використаним, так і закритим?
iruvar

@ 1_CR, після >&4, коротке значення 1>&4, grep'fd 1 і 4 вказують на один і той же ресурс (початкова верстка оболонки). grepне потрібно, щоб його fd 4 був відкритий ні до чого. З цим воно нічого не робить, тому ми закриваємо це4>&-
Стефан Шазелас

Останній командний рядок - магічна магія.

-1

Щоб отримати передбачуване замовлення, скористайтеся

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

Можливо, я був недостатньо зрозумілий. Я мав на увазі передбачуваний порядок з точки зору порядку командних виходів (тобто вихід з grep перед виведенням з wc). Мені не потрібно впорядкований комбінований вихід
iruvar

щойно знайшов gnu.org/software/bash/manual/bashref.html#Command-Grouping , він повідомляє мені, що з операторами {} ви переконайтеся, що (у цьому випадку), що ви вперше зробите <file.txt tee / dev / fd / 3 | grep LITERAL> & 4; і коли це зроблено, ви дзвоните на wc, тож, щоб відповісти на своє первісне запитання, так, це гарантовано моєму розумінню
Thorsten Staerk

1
@ThorstenStaerk ви могли б додати додаткову інформацію, яку ви знайшли у своїй відповіді?
terdon

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.