← Linux: основы
12 мин · просто · Урок 7 из 8

Pipes и редиректы

Соединяй команды в цепочки, отправляй вывод в файл, лови stderr вместе со stdout.

Потоки: stdin, stdout, stderr

У каждого процесса есть три стандартных потока:

Ключевая идея Unix: команды маленькие и делают одно дело, а ты соединяешь их потоки в цепочки. Отсюда вся мощь командной строки.

Pipe: соединяем команды

Pipe | берёт stdout левой команды и подаёт его на stdin правой:

cat access.log | grep 500 | wc -l

Читается слева направо: вывели файл -> оставили строки с 500 -> посчитали их. Каждое звено не знает про соседей, просто читает stdin и пишет stdout.

Частые соседи в цепочках:

Классика — топ IP по числу запросов в логе:

awk '{print $1}' access.log | sort | uniq -c | sort -rn | head

Редиректы: вывод в файл

Pipe соединяет процессы; редирект соединяет поток с файлом:

command > out.log      # перезаписать out.log выводом (stdout)
command >> out.log     # дописать в конец, не стирая
command < in.txt       # взять stdin из файла

> всегда обнуляет файл перед записью: легко затереть нужное. Когда надо копить (логи), используй >>.

stderr отдельно от stdout

Ошибки идут в stderr (поток 2), а не в stdout (1). Поэтому обычный > их не ловит:

command 2> errors.log        # только ошибки в файл
command > out.log 2>&1        # stdout в файл, И stderr туда же
command &> all.log            # краткая форма того же (bash)

Разбор 2>&1: "поток 2 (stderr) направь туда же, куда сейчас смотрит поток 1 (stdout)". Поэтому порядок важен:

command > out.log 2>&1    # верно: сначала stdout -> файл, потом stderr -> туда же
command 2>&1 > out.log    # НЕ то: stderr привязался к терминалу ДО того, как stdout ушёл в файл

Выкинуть вывод совсем можно в "чёрную дыру" /dev/null:

command > /dev/null 2>&1     # тишина: ни вывода, ни ошибок

tee: и на экран, и в файл

Иногда хочется видеть вывод вживую и сохранить его. tee (тройник) делает обе вещи:

./deploy.sh 2>&1 | tee deploy.log     # на экран И в deploy.log
./deploy.sh 2>&1 | tee -a deploy.log  # -a дописывает, не перезаписывает

Удобно для долгих команд: следишь за прогрессом и одновременно получаешь полный лог для разбора.

Ошибки внутри pipeline

Код возврата цепочки — это код её последней команды. Если упало звено в середине, а последняя команда отработала, shell считает весь pipeline успешным:

$ grep boom missing.log | wc -l
0
$ echo $?
0            # grep упал (файла нет), но wc отработал: pipeline "успешен"

Лечится опцией set -o pipefail: с ней цепочка возвращает код первой упавшей команды. В скриптах включай её сразу:

$ set -o pipefail
$ grep boom missing.log | wc -l; echo $?
0
2            # теперь виден код ошибки grep

Чек-лист

Ниже — три задания: впишите команду. Дальше дрилл по теме, и трек Linux закрывается финальным квизом.

После квиза есть куда копнуть глубже: треки «Linux: загрузка», «Linux: процессы вглубь» и «Linux: файловая система вглубь».

Самопроверка

Впишите команду / ключевую строку. Регистр и пробелы не важны.

1. Посчитайте, сколько строк со словом ERROR в файле app.log (одной командой через pipe).
2. Запустите ./deploy.sh так, чтобы и обычный вывод, и ошибки попали в один файл run.log.
3. Покажите содержимое access.log на экране и одновременно сохраните его в copy.log.

Дрилл · вопросы как на собесе

Проверь себя без подсказок

Сформулируй ответ вслух или письменно, потом раскрой и честно отметь: знал или нет.

01

Как одновременно перенаправить stdout и stderr?

LIN-033

Прошли материал до конца? Отметьте урок пройденным.