Pipes и редиректы
Соединяй команды в цепочки, отправляй вывод в файл, лови stderr вместе со stdout.
Потоки: stdin, stdout, stderr
У каждого процесса есть три стандартных потока:
- stdin (0) — откуда читает ввод,
- stdout (1) — куда пишет нормальный вывод,
- stderr (2) — куда пишет ошибки и диагностику.
Ключевая идея Unix: команды маленькие и делают одно дело, а ты соединяешь их потоки в цепочки. Отсюда вся мощь командной строки.
Pipe: соединяем команды
Pipe | берёт stdout левой команды и подаёт его на stdin
правой:
cat access.log | grep 500 | wc -l
Читается слева направо: вывели файл -> оставили строки с 500 ->
посчитали их. Каждое звено не знает про соседей, просто читает stdin и
пишет stdout.
Частые соседи в цепочках:
grep— оставить строки по шаблону,sort— отсортировать,uniq -c— схлопнуть дубли со счётчиком,head/tail— первые/последние N строк,awk '{print $1}'— выдрать колонку,wc -l— посчитать строки.
Классика — топ 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
Чек-лист
- Понимаете разницу stdout (1) и stderr (2).
- Знаете, что
>перезаписывает,>>дописывает. - Помните идиому
> out.log 2>&1и почему порядок важен. - Знаете
/dev/nullдля глушения иteeдля "экран + файл". - Включаете
set -o pipefailв скриптах, чтобы ошибка в середине цепочки не терялась.
Ниже — три задания: впишите команду. Дальше дрилл по теме, и трек Linux закрывается финальным квизом.
После квиза есть куда копнуть глубже: треки «Linux: загрузка», «Linux: процессы вглубь» и «Linux: файловая система вглубь».
Самопроверка
Впишите команду / ключевую строку. Регистр и пробелы не важны.
Дрилл · вопросы как на собесе
Проверь себя без подсказок
Сформулируй ответ вслух или письменно, потом раскрой и честно отметь: знал или нет.
Как одновременно перенаправить stdout и stderr?
LIN-033Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс