Что такое пайп в терминале — и почему бесконечная команда завершается за миг

Команда yes печатает букву y бесконечно. Сама она не остановится никогда. А теперь набери:
$ yes | head -1
y
Ответ приходит за сотые доли секунды. Куда делась бесконечность? Смотри, вся разгадка — в палочке между командами.
Что такое пайп
Пайп (pipe, «труба») — это символ |. Он соединяет выход одной программы со входом другой. Что левая печатает, то правая читает.
Без него пришлось бы сохранить результат в файл, а потом открыть его второй командой. Пайп убирает этот файл. Поэтому маленькие программы складываются в большие:
$ grep ERROR app.log | sort | uniq -c | sort -rn | head -5
2 ERROR a
1 ERROR b
Это топ самых частых ошибок в логе. grep отбирает строки, sort их группирует, uniq -c считает, второй sort ставит самые частые наверх, head обрезает. Ни одна из этих программ не знает про остальные.
Важная деталь: в трубу попадает только обычный вывод — stdout. Ошибки летят мимо, прямо на экран. Если npm run build | grep error ничего не нашёл, ошибка могла уйти в stderr. Тогда пиши npm run build 2>&1 | grep error.
Как это работает на самом деле
Легко подумать, что команды идут по очереди: левая закончила, правая начала. Нет. Они стартуют одновременно. Проверь:
$ (sleep 1; echo left-done) | (echo right-start; cat)
right-start
left-done
Правая успела напечатать своё, пока левая ещё спала.
Между ними лежит маленький буфер в памяти. На Linux это 64 КБ. Представь двух работников и столик между ними: первый кладёт детали, второй забирает.
- Столик заполнился — первого усыпляют, пока второй не заберёт деталь.
- Столик пуст — засыпает второй, пока первый не положит новую.
Поэтому yes не съедает всю память. Он пишет ровно с той скоростью, с какой читают.
А теперь загадка из начала. head -1 прочитал одну строку и вышел. Второй работник ушёл домой. yes пробует положить деталь, а система отвечает сигналом SIGPIPE: «читать некому». По умолчанию этот сигнал просто завершает программу. Так бесконечность и заканчивается.
Это видно по кодам выхода:
$ yes | head -1
y
$ echo ${PIPESTATUS[@]}
141 0
141 — это 128 плюс 13, номер сигнала SIGPIPE. Так умирают нормально, а не от ошибки.
Где это укусит новичка
Сам по себе механизм простой, но у него есть четыре неприятных следствия.
Broken pipe в Python. Запусти python3 script.py | head -1 — и получишь трейсбек BrokenPipeError. Твой код тут ни при чём, просто читатель ушёл раньше. Python сам отключает SIGPIPE и превращает ошибку записи в исключение. В Node.js то же самое называется EPIPE, но вывод в трубу может завершиться и без ошибки. Для утилит на Python хватает одной строки в начале: signal.signal(signal.SIGPIPE, signal.SIG_DFL).
Зелёная сборка с упавшими тестами. Итог цепочки — это код выхода последней команды. В npm test | tee log.txt последняя всегда успешна, и CI не заметит падения. Лечится через set -o pipefail.
Ловушка самого pipefail. С этой настройкой yes | head -1 возвращает 141, то есть считается провалом. Если в скрипте стоит set -eo pipefail, строка вида generate | head -1 завершит скрипт без единого сообщения об ошибке.
Пропавшая переменная. Каждая сторона трубы живёт в отдельном процессе. Поэтому счётчик внутри цикла справа пропадает вместе с циклом:
n=0
cat list.txt | while read x; do n=$((n+1)); done
echo $n # 0
Убери трубу, и всё заработает: while read x; do n=$((n+1)); done < list.txt.
Зачем это тебе сейчас: логи в ИИ
Самая полезная новость: консольный ИИ-агент — такая же программа, которая читает из трубы. Значит, модель можно поставить прямо в цепочку:
$ git diff | claude -p "найди баги в этом диффе, только реальные"
$ tail -200 app.log | claude -p "что падает чаще всего? дай топ-3"
Но есть правило, которое экономит деньги. Сначала сожми, потом спрашивай. Лог на 50 МБ — это миллионы токенов, а за них платишь ты, и в модель они всё равно не влезут. Один grep перед claude -p убирает 99% мусора бесплатно.
Шаблон на каждый день: отфильтруй → посчитай → спроси.
$ grep ERROR app.log | sort | uniq -c | sort -rn | head -20 | claude -p "с чего начать?"
В модель уходит двадцать строк вместо миллиона. Ответ приходит быстрее и стоит копейки.
Запомни одну картинку: столик между работниками. Команды идут вместе, столик маленький, а когда правый уходит, левого отправляют домой.
Чем пайп отличается от знака >?
> пишет вывод в файл, а | отдаёт его другой программе. После > справа стоит имя файла, после | — команда.
Пайп работает в Windows?
Да, и в cmd, и в PowerShell. Но PowerShell передаёт по трубе объекты, а не текст, поэтому там иначе фильтруют: через Where-Object, а не grep.
Сколько команд можно соединить?
Сколько нужно. Каждая станет отдельным процессом, и все запустятся одновременно.
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.





