урок 5 из 10

Конвейер и перенаправление

Понимать три потока команды, перенаправлять выход и ошибки в файл, дописывать и прятать ненужное в /dev/null, собирать конвейеры из sort, uniq, cut, head и wc, записывать в системные файлы через sudo tee и обходить ловушки «файл сам в себя» и «скачать и сразу выполнить».

8 мин чтения · 4 главы ·5 заданий ·домашняя работа

Три потока

До сих пор каждая команда жила сама по себе: вы её запускали, она писала результат в окно. Но настоящая сила терминала — в том, что результат можно направить куда угодно: в файл, в другую команду, в никуда. Чтобы понять, как это устроено, нужно одно понятие — потоки.

Вход (0):клавиатураили файлКомандаВыход (1):результатОшибки (2):сообщения
Команда читает вход, пишет результат в выход, а сообщения об ошибках — в отдельный поток ошибок. По умолчанию вход — клавиатура, а оба выхода — окно терминала. Перенаправление меняет, куда они ведут.

У каждой команды три потока:

  • вход (номер 0) — откуда она читает данные, если ей не дали файл. По умолчанию — клавиатура;
  • выход (номер 1) — куда пишет результат. По умолчанию — окно терминала;
  • ошибки (номер 2) — куда пишет сообщения о проблемах. По умолчанию — тоже окно.

Разделение выхода и ошибок кажется лишним, пока не понадобится сохранить результат в файл: тогда удобно, что в файл идёт только полезное, а ошибки остаются видны на экране. И наоборот — можно собрать только ошибки, чтобы понять, что пошло не так.

Номера потоков — 0, 1 и 2 — понадобятся в следующей главе: по ним оболочке говорят, какой именно поток куда направить.

Перенаправление

Перенаправление меняет, куда пишет или откуда читает команда. Знаков немного, и каждый стоит запомнить точно.

ЗаписьЧто делает
команда > файлвыход в файл; файл перезаписывается
команда >> файлвыход в конец файла, старое сохраняется
команда 2> файлтолько ошибки в файл
команда > файл 2>&1и выход, и ошибки в один файл
команда < файлвзять вход из файла
ls -l > list.txt                 # список в файл (старое содержимое пропадёт)
date >> journal.txt              # дописать строку в конец
find / -name "*.conf" 2> /dev/null   # ошибки «нет доступа» — в никуда

/dev/null — особый файл-«чёрная дыра»: всё, что в него пишется, исчезает. Туда направляют то, что не нужно видеть, — чаще всего сообщения об ошибках, которые заранее ожидаемы. Например, find по всему диску засыпает экран строками «нет доступа», а 2> /dev/null убирает их и оставляет только найденное.

Запись 2>&1 читается как «поток 2 направить туда же, куда сейчас направлен поток 1». Порядок важен: сначала указывают, куда идёт выход, потом приклеивают к нему ошибки.

Конвейер

Конвейер — вертикальная черта | между командами. Выход левой становится входом правой. Так из маленьких команд собирается решение.

ls -l | less                      # длинный список — постранично
grep error app.log | wc -l        # сколько строк с ошибками
history | grep ssh                # какие команды ssh я набирал

Несколько команд, которые почти всегда живут внутри конвейеров:

КомандаЧто делает
sortупорядочивает строки; -n — как числа, -r — наоборот
uniq -cсклеивает одинаковые соседние строки и считает их
cut -d' ' -f1вырезает первый столбец по разделителю «пробел»
head / tailпервые или последние строки результата
wc -lсколько строк получилось
grepнужныестрокиcutнужныйстолбецsort | uniq -cпосчитатьповторыsort -rn |headпервые
Каждая команда делает одно маленькое дело. Соединённые вертикальной чертой, они отвечают на вопрос, для которого никто не писал отдельной программы: кто чаще всех заходил на сайт.

Вот знаменитый пример: кто чаще всех обращался к сайту. В журнале веб-сервера первый столбец — адрес посетителя.

cut -d' ' -f1 access.log | sort | uniq -c | sort -rn | head -5
   1843 203.0.113.7
    912 198.51.100.4
    402 192.0.2.15
    ...

Читается слева направо: вырезать адреса, упорядочить, посчитать повторы, упорядочить по числу от большего, оставить пять первых. Пять простых команд — и ответ, для которого пришлось бы писать программу.

Приёмы и ловушки

Три приёма, которые часто нужны вместе с конвейерами, и одна ловушка.

tee — записать в файл и одновременно показать на экране. Удобно, когда длинную работу хочется и видеть, и сохранить:

./build.sh | tee build.log

Записать в системный файл. sudo echo "..." > /etc/файл не сработает: sudo получает только echo, а перенаправление выполняет ваша обычная оболочка без прав. Правильно — отдать запись команде tee, запущенной с правами:

echo "192.168.1.10 nas" | sudo tee -a /etc/hosts

Ловушка: файл сам в себя. Команда sort names.txt > names.txt оставит пустой файл. Перенаправление обнуляет names.txt раньше, чем sort успеет его прочитать. Результат записывают в новый файл, а потом, проверив, переименовывают.

Конвейеры — лучшее место, чтобы почувствовать философию Linux: маленькие инструменты, каждый делает одно, а вместе — что угодно. Когда задача кажется требующей отдельной программы, сначала стоит спросить: из каких простых шагов она складывается?

Задания урока

Первые задание решается прямо здесь — без регистрации. Щёлкните по ответу.

  1. 1. Как дописать строку в системный файл /etc/hosts?

Остальные задания урока — в курсе, с сохранением прогресса и разбором ошибок.

  1. Заполните пропуски.средне
  2. Сопоставьте запись и действие.легко
  3. Расставьте конвейер «кто чаще заходил на сайт».средне
  4. Команда sort names.txt > names.txt аккуратно упорядочит файл.средне

Практика и материалы по теме курса

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