Процесс в Unix обычно имеет три стандартных дескриптора:
0 —
stdin, 1 — stdout, 2 — stderr.Shell не обрабатывает вывод — он до запуска команды переназначает, к каким объектам привязаны дескрипторы (терминал, файл, pipe). Поэтому процесс стартует уже с изменённой таблицей дескрипторов.
Базовый случай — перенаправление
stdout в файл:echo "test" > file.txt
Оператор
> открывает файл с перезаписью (truncate). Если нужно дописывать данные в конец, используется >>:echo "line" >> file.txt
Важно помнить, что
> по умолчанию влияет только на stdout (fd 1).Для
stderr используется дескриптор 2:command 2> error.log
Так можно разделить обычный вывод и ошибки в разные файлы:
command > out.log 2> error.log
Поскольку
stdout и stderr — независимые дескрипторы, их можно направить в один файл:command > all.log 2>&1
2>&1 означает: направить stderr туда же, куда в этот момент направлен stdout. Редиректы применяются слева направо, поэтому порядок критичен:
command > all.log 2>&1 # оба потока в файл
command 2>&1 > all.log # stderr останется в терминале
Это именно копирование назначения дескриптора, а не абстрактное объединение потоков.
stdin (fd 0) тоже можно переназначить:sort < input.txt
В этом случае файл становится источником данных для процесса.
Оператор
| создаёт pipe — канал между процессами: stdout левой команды подключается к stdin правой.grep 500 access.log | wc -l
Через
pipe передаётся только stdout. Если нужно передать и stderr, его сначала перенаправляют в stdout:make 2>&1 | tee build.log
Shell также позволяет работать с дополнительными дескрипторами, что удобно в скриптах:
exec 3> debug.log
echo "debug info" >&3
exec 3>&-
В этом контексте
exec изменяет дескрипторы текущего shell-процесса, позволяя организовать отдельные каналы вывода.🔥 Основные принципы просты: редиректы настраиваются до запуска, применяются слева направо;
2>&1 копирует stdout, pipe соединяет stdout одной команды со stdin другой.➡️ DevOps Ready | #практика