У zsh різниця між cat <(cat) vs cat | кішка проти кота = (кішка)?


18

Я очікував cat <(cat)і cat | catзробити те саме: копіювати рядки зі stdin у stdout. Моє розуміння полягало в тому, що обидва будуть виконувати a catв нижній оболонці, перенаправляти catstdout нижньої catоболонки на тимчасово названу трубу, а потім виконувати іншу в поточній оболонці, а її stdin буде перенаправлений на трубу.

Натомість cat <(cat)дозволяє мені вводити мій термінал, але жоден із вхідних рядків не копіюється та ^Dне дає сигналу EOF; cat | catпрацює, як очікувалося.

У подальшому експерименті я перевірив, чи cat =(cat)немає подібних труднощів cat <(cat), але це працює, як я і очікував: все stdin аж до ^Dкопіювання копіюється в stdout за один раз.

Хтось може допомогти мені зрозуміти, що zsh робить під кришкою?

Відповіді:


23
  1. a | bпідключається STDOUTвід aта STDINз bпросто за допомогою dup/dup2. Обидві команди виконуються паралельно.

  2. a =(b)замінює аргумент на aтимчасове ім'я файлу. bбуде виконуватися раніше, aоскільки тимчасовий файл повинен бути створений до того, як він може бути переданийa

  3. a <(b)замінює аргумент на aіменовану трубку. aі bбігати паралельно. Зараз це стає дещо складніше:

    bзнаходиться у фоновому режимі і не може читати з терміналу. Ви можете перевірити його самостійно, скориставшись strace -p $PIDприєднанням до другого процесу кішки, щоб побачити процес.

    aтим часом намагається прочитати з названої труби, але нічого не може прочитати, як bне може прочитати.

    • Це означає, що у вас в основному тупик, з якого aнамагаються читати, bале з bнього не можна читати STDINі не можете писатиa

Більше інформації про фоновий процес та термінал від man bash :

Щоб полегшити реалізацію користувальницького інтерфейсу для управління роботою, операційна система підтримує поняття поточного ідентифікатора групи процесових терміналів . Члени цієї групи процесів (процеси, ідентифікатор групи яких дорівнює поточному ідентифікатору групи процесових терміналів) отримують сигнали, створені клавіатурою, такі як SIGINT . Кажуть, що ці процеси стоять на першому плані . Фонпроцеси - це такі, чий ідентифікатор групи процесів відрізняється від термінального; такі процеси несприйнятливі до сигналів, створених клавіатурою. Лише процеси переднього плану дозволено читати з або, якщо користувач це вказує зі стихійною зупинкою, записувати в термінал. Фонові процеси, які намагаються прочитати з (записувати, коли діє stty tostop), терміналу надсилається сигнал SIGTTIN (SIGTTOU) термінальним драйвером ядра, який, якщо не буде спійманий, призупиняє процес.


Чудово, дякую - це багато прояснилось!
Алан О'Доннелл

1
Зауважте, коли не є інтерактивним, zsh переспрямовує стандартний вхід фонових команд (включаючи вхідні <(cmd)) на /dev/null, тому поведінка відрізняється ( zsh -c 'cat <(cat)'повертається негайно і нічого не видає).
Stéphane Chazelas
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.