Последовательности команд и конвейеры

LinuxBeginner
Практиковаться сейчас

Введение

Небольшие команды Linux становятся гораздо полезнее, когда оболочка координирует их работу. Команда сообщает об успехе или ошибке с помощью кода завершения; операторы последовательного выполнения определяют, какая команда запустится следующей; конвейер передаёт стандартный вывод одной команды на стандартный ввод другой.

Вы будете изучать эти возможности постепенно, а затем с помощью grep, cut, wc, sort и uniq преобразуете небольшой набор данных о событиях службы. В следующих практических занятиях фильтры обработки текста будут рассмотрены подробнее, поэтому здесь основное внимание уделяется передаче данных и управлению выполнением команд.

Просмотр кода завершения команды

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

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

cd /home/labex/project/pipeline-lab
test -f events.csv
echo $?

В выводе появится 0. Теперь проверьте отсутствующий файл:

test -f missing.csv
echo $?

Код завершения будет ненулевым. Читайте значение $? сразу после нужной команды, потому что каждая следующая команда заменяет его.

Создайте удобный для проверки результат с помощью конструкции if. Полные сценарии оболочки вы изучите позже; здесь конструкция лишь преобразует код завершения в текст:

if test -f events.csv; then echo "events.csv is ready"; else echo "events.csv is missing"; fi > status-result.txt
cat status-result.txt

Управление следующей выполняемой командой

На этом шаге вы сравните безусловные и условные операторы команд.

Точка с запятой запускает следующую команду независимо от результата предыдущей:

false; echo "semicolon continues"

&& запускает правую команду только после успешного выполнения левой:

test -f events.csv && echo "input found"
test -f missing.csv && echo "you should not see this"

|| запускает правую команду только после ошибки левой:

test -f missing.csv || echo "input missing"

С помощью этих операторов можно выразить простое решение об успехе или ошибке. Скопируйте набор данных только при наличии исходного файла; в противном случае выведите сообщение об ошибке:

test -f events.csv && cp events.csv working.csv || echo "Copy failed"

Проверьте, что защищённая условием копия совпадает с исходным файлом:

cmp events.csv working.csv && echo "guarded copy matches" > sequence-result.txt
cat sequence-result.txt

Для сложной логики используйте понятную конструкцию if: длинные цепочки && и || могут стать неоднозначными.

Передача вывода через конвейер

На этом шаге вы соедините команды с помощью | и увидите, как каждый этап сужает поток данных.

Левая команда записывает стандартный вывод в конвейер, а правая читает эти данные как стандартный ввод. Выберите только записи ERROR:

cd /home/labex/project/pipeline-lab
cat events.csv | grep ',ERROR,'

grep умеет читать файл напрямую, поэтому следующая сокращённая форма даёт тот же результат:

grep ',ERROR,' events.csv

Добавьте wc -l, чтобы подсчитать совпавшие строки:

grep ',ERROR,' events.csv | wc -l

Сохраните и отфильтрованный поток, и его количество. tee дублирует стандартный ввод: одну копию он записывает в error-events.csv, а другую передаёт дальше через стандартный вывод. Поэтому последний wc -l подсчитывает ровно те строки, которые были сохранены:

grep ',ERROR,' events.csv | tee error-events.csv | wc -l > error-count.txt
cat error-events.csv
cat error-count.txt

После выполнения конвейера просмотрите оба файла. error-events.csv содержит совпавшие записи, а error-count.txt — их количество.

Извлечение полей с помощью cut

На этом шаге вы будете рассматривать каждую строку CSV как набор полей, разделённых разделителем.

cut -d, -f1 использует запятую как разделитель и выводит поле 1 — имя службы:

cd /home/labex/project/pipeline-lab
cut -d, -f1 events.csv

Выведите вместе поля службы и уровня важности:

cut -d, -f1,2 events.csv

Объедините фильтрацию и извлечение, чтобы получить список только тех служб, которые создали предупреждения:

grep ',WARN,' events.csv | cut -d, -f1

Сохраните этот промежуточный результат:

grep ',WARN,' events.csv | cut -d, -f1 > warning-services.txt
cat warning-services.txt

cut хорошо подходит для простых записей, в которых разделитель не встречается внутри поля. Для более сложных форматов могут потребоваться awk или инструмент, учитывающий структуру конкретного формата.

Сортировка и подсчёт повторяющихся значений

На этом шаге вы создадите полный конвейер подсчёта частот и поймёте, почему перед uniq нужна сортировка.

uniq объединяет только соседние одинаковые строки. Сначала извлеките имена служб, затем отсортируйте их, чтобы одинаковые значения оказались рядом:

cd /home/labex/project/pipeline-lab
cut -d, -f1 events.csv | sort

Добавьте uniq -c, чтобы подсчитать каждую последовательность одинаковых имён:

cut -d, -f1 events.csv | sort | uniq -c

Отсортируйте количества по числовому значению в порядке убывания. sort -k1,1nr использует первое поле как ключ с числовой сортировкой в обратном порядке:

cut -d, -f1 events.csv | sort | uniq -c | sort -k1,1nr

Сохраните итоговый отчёт:

cut -d, -f1 events.csv | sort | uniq -c | sort -k1,1nr > service-frequency.txt
cat service-frequency.txt

Читайте этот конвейер слева направо: извлечь → отсортировать → подсчитать соседние дубликаты → упорядочить количества.

Итоги

Вы использовали код завершения как сигнал успеха оболочки, управляли выполнением с помощью ;, && и ||, а также создавали конвейеры с понятными этапами. Затем вы фильтровали записи, извлекали поля, подсчитывали строки, сортировали значения и подсчитывали дубликаты — это именно те базовые приёмы, которые понадобятся в следующем Challenge по конвейерам обработки данных.