Потоки, конвейеры и перенаправление [103.4]

Рейтинг: 48.7% · 7 голосов
Полный курс LPIC-1 (экзамены 101-500 и 102-500): архитектура, загрузка, пакеты, команды и текст, ФС и права, шелл-скрипты, пользователи, сервисы, сеть, безопасность. Debian и RHEL.
Ответить
Аватара пользователя
Sergey_Sysadmin
Сообщения: 134
Зарегистрирован: 11 май 2026, 05:31

Потоки, конвейеры и перенаправление [103.4]

Сообщение Sergey_Sysadmin »

Оглавление курса (41)
  1. Введение в LPIC-1 и как устроен путь администратора
  2. Железо, устройства и модули ядра [101.1]
  3. Загрузка системы: от BIOS до systemd [101.2]
  4. systemd, цели и уровни выполнения [101.3]
  5. План разметки диска и swap [102.1]
  6. Загрузчик GRUB 2 [102.2]
  7. Разделяемые библиотеки [102.3]
  8. Управление пакетами в Debian: dpkg и apt [102.4]
  9. Управление пакетами RPM, DNF и Zypper [102.5]
  10. Linux как гость виртуализации [102.6]
  11. Командная строка Bash [103.1]
  12. Обработка текста фильтрами [103.2]
  13. Базовое управление файлами [103.3]
  14. Потоки, конвейеры и перенаправление [103.4] (вы здесь)
  15. Процессы: создание, мониторинг, сигналы [103.5]
  16. Приоритеты выполнения процессов [103.6]
  17. Регулярные выражения [103.7]
  18. Редактор vi и vim [103.8]
  19. Разделы и создание файловых систем [104.1]
  20. Целостность и обслуживание ФС [104.2]
  21. Монтирование файловых систем [104.3]
  22. Урок 21. Права доступа и владение: rwx, chmod, umask и специальные биты
  23. Жёсткие и символические ссылки
  24. FHS и поиск файлов в системе [104.7]
  25. Окружение и кастомизация оболочки [105.1]
  26. Урок 25. Написание простых bash-скриптов [105.2]
  27. Графика, рабочие столы и доступность
  28. Учётные записи пользователей и групп
  29. Автоматизация задач: cron, at, таймеры [107.2]
  30. Локализация и интернационализация [107.3]
  31. Системное время и синхронизация [108.1]
  32. Системное логирование [108.2]
  33. Основы почтового агента (MTA) [108.3]
  34. Печать и CUPS [108.4]
  35. Основы интернет-протоколов [109.1]
  36. Постоянная конфигурация сети [109.2]
  37. Диагностика сети [109.3]
  38. DNS на стороне клиента [109.4]
  39. Задачи администрирования безопасности [110.1]
  40. Настройка безопасности хоста [110.2]
  41. Шифрование данных: SSH и GnuPG [110.3]
Урок 13. Потоки, конвейеры и перенаправление [103.4]

Любая утилита в Linux - это коробка с тремя проводами: один на вход, два на выход. Понимание, куда эти провода воткнуты по умолчанию и как их перетыкать, превращает набор разрозненных команд в инструмент. Этот урок про то, как администратор собирает из мелких программ обработку логов, фильтрацию, ветвление вывода и пакетные операции - без единой строчки на скриптовом языке, только средствами shell.

Изображение

Как это работает

Когда ядро запускает процесс, оно открывает ему три файловых дескриптора. Дескриптор 0 - стандартный ввод (stdin), откуда программа читает. Дескриптор 1 - стандартный вывод (stdout), куда идет полезный результат. Дескриптор 2 - стандартный вывод ошибок (stderr), куда идут диагностика и предупреждения. По умолчанию все три привязаны к терминалу, поэтому ошибки и результат смешиваются на экране. Номера тут не случайность, а реальные числа в таблице открытых файлов процесса - именно поэтому в синтаксисе перенаправления мы пишем 2> и 1>&2.

Ключевая идея: stdout и stderr разделены намеренно. stdout несет данные, которые можно скормить дальше по конвейеру, а stderr несет сообщения для человека. Если бы они шли в один поток, любая ошибка попадала бы в данные и ломала следующую команду. Поэтому grep, find и прочие пишут результат в 1, а жалобы вроде "permission denied" в 2.

Перенаправление - это подмена того, куда указывает дескриптор, до запуска программы. Сам процесс этого не замечает: он как писал в дескриптор 1, так и пишет, просто за дескриптором теперь стоит файл, а не терминал. Конвейер (pipe) - это безымянный буфер в памяти ядра: stdout левой команды соединяется со stdin правой. Команды в конвейере запускаются параллельно, данные текут потоком, а не "сначала одна закончила, потом вторая начала".

Команды и примеры

Базовые перенаправления вывода. Один знак больше перезаписывает файл, два - дописывают в конец.

Код: Выделить всё

ls /etc > files.txt        # stdout в файл (перезапись)
date >> files.txt          # дописать в конец
sort < files.txt           # stdin из файла
Раздельная работа с потоками. Это сердце темы - отделить ошибки от данных.

Код: Выделить всё

find /etc -name '*.conf' > found.txt 2> errors.txt   # данные и ошибки в разные файлы
find /etc -name '*.conf' 2> /dev/null                # ошибки выбросить, оставить только результат
make 2>&1 | less                                     # объединить stderr со stdout и листать
make &> build.log                                    # и stdout, и stderr в один файл (bash)
Важна последовательность. Запись 2>&1 значит "дескриптор 2 теперь указывает туда же, куда сейчас указывает 1". Поэтому такой вариант НЕ сработает как ожидается:

Код: Выделить всё

command 2>&1 > file   # сначала 2 направили на терминал (туда, где был 1), потом 1 ушел в файл
command > file 2>&1   # правильно: сперва 1 в файл, потом 2 туда же, куда 1
Конвейеры и tee. Команда tee читает stdin и пишет одновременно в файл и в свой stdout - это тройник, ветвление потока.

Код: Выделить всё

dmesg | grep -i error | tee errors.log | wc -l   # и в файл, и счетчик на экран
echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-fwd.conf   # запись в файл от root через sudo
journalctl -p err | tee -a audit.log              # -a дописать, не перезаписать
Запись через tee с sudo - классический прием: перенаправление > выполняется текущим shell без прав root, поэтому sudo command > /root/file падает с отказом, а sudo tee решает проблему, так как уже сам tee работает от root.

xargs строит команду из потока. Многие утилиты (rm, chmod, kill) принимают аргументы, а не stdin. xargs превращает строки ввода в аргументы.

Код: Выделить всё

find . -name '*.tmp' -print0 | xargs -0 rm -v        # -print0/-0 защита от пробелов в именах
echo 'a b c' | xargs -n1 echo                        # -n1 по одному аргументу на запуск
cat hosts.txt | xargs -I{} -P4 ping -c1 {}           # -I{} подстановка, -P4 четыре параллельно
here-document и here-string. here-doc подает блок текста на stdin, here-string - одну строку. Это замена временным файлам.

Код: Выделить всё

cat <<'EOF' > /etc/motd
Доступ только для своих.
Все действия пишутся в журнал.
EOF

bc <<< '3 * (4 + 5)'          # here-string: одна строка на stdin
grep root <<< "$(getent passwd)"
Кавычки у метки важны. Запись <<EOF подставляет переменные и $(...) внутри блока, а <<'EOF' (метка в кавычках) выдает текст буквально - удобно, когда в тексте есть знаки доллара или backslash, которые не надо трогать. Отступ табами съедает форма <<-EOF.

В Debian/Ubuntu и в RHEL/Fedora синтаксис shell одинаков (это bash), различий нет - перенаправление часть оболочки, а не дистрибутива.

Частые грабли
  • Порядок 2>&1 и > перепутан. Запомните правило: сначала направляем stdout в файл, потом stderr дублируем за ним - только > file 2>&1.
  • command > file читает И пишет в один файл (a > a) - shell обнуляет файл ДО запуска команды, данные теряются. Для in-place используйте sponge из пакета moreutils или временный файл.
  • echo text | sudo command > /root/f - перенаправление делает ваш shell без root, отказ в доступе. Решение - sudo tee.
  • xargs без -0 ломается на именах с пробелами и переводами строк. Связка find -print0 | xargs -0 обязательна для произвольных имен.
  • Пустой ввод все равно запускает команду один раз. Добавляйте xargs --no-run-if-empty (в GNU это поведение по умолчанию у -r), иначе rm без аргументов может удалить не то.
  • &> и >& - синтаксис bash, в POSIX sh их нет. В скриптах с #!/bin/sh пишите > file 2>&1.
  • Конвейер прячет код возврата. Статус всего pipe - это статус ПОСЛЕДНЕЙ команды. Для проверки ошибок в середине нужен set -o pipefail.
Мини-лаба
  • Запустите find /etc -name '*.conf' и убедитесь, что ошибки доступа смешаны с результатом на экране.
  • Повторите, разделив потоки: результат в conf.txt, ошибки в err.txt. Проверьте оба файла.
  • Соберите конвейер: journalctl -p warning | grep -i fail | tee fails.log | wc -l. Сверьте число строк с содержимым файла.
  • Через sudo tee запишите строку в /etc/sysctl.d/99-lab.conf, затем убедитесь, что прямой sudo echo > туда падает с отказом.
  • Командой find /tmp -type f -print0 | xargs -0 -I{} ls -l {} выведите детали файлов, корректно обработав пробелы в именах.
  • Создайте here-doc с двумя строками текста в файл report.txt, один раз с подстановкой $(date), один раз с буквальной меткой 'EOF' - сравните результат.
Контрольные вопросы
  • Какие номера дескрипторов у stdin, stdout и stderr и почему stderr отделен от stdout?
  • Чем отличается результат command 2>&1 > log от command > log 2>&1 и почему?
  • Зачем нужен tee и как с его помощью записать файл, требующий прав root?
  • В каком случае обязательна связка find -print0 | xargs -0 и что произойдет без нее?
  • Чем here-document отличается от here-string и что меняет кавычки вокруг метки (<<EOF против <<'EOF')?
  • Почему конвейер a | b может вернуть код успеха, даже если a завершилась с ошибкой, и как это исправить?
👍7 ❤️2 🔥2 😄 🤔1
Аватара пользователя
idleheap
Сообщения: 1
Зарегистрирован: 18 май 2026, 07:55

Re: Потоки, конвейеры и перенаправление [103.4]

Сообщение idleheap »

А зачем вообще 2>/dev/null, если можно просто глазами пропустить ошибки? Понял на find по /etc - там столько permission denied, что реальный результат тонет. Теперь всегда отделяю.
👍1 ❤️ 🔥 😄 🤔
Аватара пользователя
bdover
Сообщения: 1
Зарегистрирован: 13 май 2026, 21:49

Re: Потоки, конвейеры и перенаправление [103.4]

Сообщение bdover »

Споткнулся на sudo echo foo > /etc/файл - отказ в доступе, хотя я под sudo. Дошло, что перенаправление делает мой шелл, а не команда. tee спас.
👍 ❤️ 🔥 😄 🤔
Ответить
← Предыдущая глава
Базовое управление файлами [103.3]
Следующая глава →
Процессы: создание, мониторинг, сигналы [103.5]

Все главы курса «LPIC-1: администратор Linux (101 + 102)»

Поделиться темой: ✈ Telegram VK

Вернуться в «LPIC-1: администратор Linux»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость