Используйте конвейеры Linux, чтобы настроить взаимодействие утилит командной строки. Упростите сложные процессы и повысьте производительность, используя набор отдельных команд и превратив их в единую команду. Мы покажем вам, как это сделать.
Оглавление
Трубы везде
Каналы — одна из самых полезных функций командной строки, которые есть в операционных системах Linux и Unix. Трубы используются бесчисленным количеством способов. Посмотрите любую статью о командной строке Linux — на любом веб-сайте, не только на нашем, — и вы увидите, что конвейеры появляются чаще, чем нет. Я просмотрел некоторые статьи toadmin.ru по Linux, и во всех них так или иначе используются каналы.
Каналы Linux позволяют выполнять действия, которые изначально не поддерживаются оболочка. Но поскольку философия дизайна Linux заключается в том, чтобы иметь много небольших утилит, выполняющих свои выделенная функция очень хорошо, и без лишних функций — мантры «делай одно и делай это хорошо» — можно соединить строки команд вместе с конвейерами, так что выходные данные одной команды становятся входными данными другой. Каждая команда, которую вы выполняете, привносит в команду свой уникальный талант, и вскоре вы обнаруживаете, что собрали команду победителей.
Простой пример
Предположим, у нас есть каталог, полный файлов разных типов. Мы хотим знать, сколько файлов определенного типа находится в этом каталоге. Есть и другие способы сделать это, но цель этого упражнения — представить каналы, поэтому мы собираемся сделать это с помощью каналов.
Мы можем легко получить список файлов с помощью ls:
ls
Чтобы выделить интересующий тип файла, мы будем использовать grep. Мы хотим найти файлы, в имени или расширении которых есть слово «страница».
Мы будем использовать специальный символ оболочки «|» передать вывод ls в grep.
ls | grep "page"
grep печатает строки, которые соответствовать его шаблону поиска. Это дает нам список, содержащий только файлы «.page».
Даже этот тривиальный пример показывает функциональность каналов. Вывод ls не отправлялся в окно терминала. Он был отправлен в grep как данные для работы с командой grep. Результат, который мы видим, исходит от grep, последней команды в этой цепочке.
Расширение нашей сети
Давайте начнем расширять нашу цепочку конвейерных команд. Мы можем посчитайте файлы «.page» добавив команду wc. Мы будем использовать параметр -l (количество строк) с wc. Обратите внимание, что мы также добавили параметр -l (длинный формат) в ls. Мы скоро воспользуемся этим.
ls - | grep "page" | wc -l
grep больше не последняя команда в цепочке, поэтому мы не видим ее вывода. Вывод команды grep передается в команду wc. В окне терминала мы видим вывод из wc. wc сообщает, что в каталоге 69 файлов «.page».
Давайте продолжим снова. Мы уберем команду wc из командной строки и заменим ее на awk. В выводе ls есть девять столбцов с параметром -l (длинный формат). Мы будем использовать awk для столбцы печати пять, три и девять. Это размер, владелец и имя файла.
ls -l | grep "page" | awk '{print $5 " " $3 " " $9}'
Мы получаем список этих столбцов для каждого из совпадающих файлов.
Теперь мы передадим этот вывод через команду sort. Мы будем использовать параметр -n (числовой), чтобы сортировка знала, что первый столбец должен быть рассматривать как числа.
ls -l | grep "page" | awk '{print $5 " " $3 " " $9}' | sort -n
Теперь вывод отсортирован по размеру файла с нашим индивидуальным выбором из трех столбцов.
Добавление другой команды
Мы закончим добавлением хвостовой команды. Скажем, чтобы он перечислил последние пять строк вывода только.
ls -l | grep "page" | awk '{print $5 " " $3 " " $9}' | sort -n | tail -5
Это означает, что наша команда переводится как «покажите мне пять самых больших файлов« .page »в этом каталоге, отсортированных по размеру». Конечно, для этого нет команды, но, используя каналы, мы создали свою собственную. Мы могли бы добавить эту — или любую другую длинную команду — в качестве псевдонима или функции оболочки, чтобы сохранить весь ввод.
Вот результат:
Мы могли бы изменить порядок размеров, добавив параметр -r (обратный) к команде сортировки и используя голову вместо хвоста для выбора строк. из верхней части вывода.
На этот раз пять самых больших файлов с расширением .page перечислены в порядке убывания размера:
Некоторые недавние примеры
Вот два интересных примера из недавних статей для компьютерных фанатов How-To.
Некоторые команды, такие как xargscommand, разработаны чтобы вводить их по трубопроводу. Вот способ, которым мы можем подсчитать слова, символы и строки в нескольких файлах, передав ls в xargs, который затем передает список имен файлов в wc, как если бы они были переданы в wc в качестве параметров командной строки.
ls *.page | xargs wc
Общее количество слов, символов и строк указано в нижней части окна терминала.
Вот способ получить отсортированный список уникальных расширений файлов в текущем каталоге со счетчиком каждого типа.
ls | rev | cut -d'.' -f1 | rev | sort | uniq -c
Здесь много чего происходит.
ls: перечисляет файлы в каталоге
rev: Переворачивает текст в именах файлов.
порез: Режет веревку при первом появлении указанного разделителя «.». Текст после этого отбрасывается.
rev: переворачивает оставшийся текст, который является расширением имени файла.
sort: сортирует список по алфавиту.
uniq: подсчитывает количество каждого уникальная запись в списке.
На выходе отображается список расширений файлов, отсортированный в алфавитном порядке с подсчетом каждого уникального типа.
Именованные каналы
Нам доступен еще один тип каналов — именованные каналы. Каналы в предыдущих примерах создаются оболочкой «на лету», когда она обрабатывает командную строку. Трубы создаются, используются, а затем выбрасываются. Они преходящи и не оставляют после себя никаких следов. Они существуют только до тех пор, пока выполняется команда, их использующая.
Именованные каналы отображаются в файловой системе как постоянные объекты, поэтому вы можете увидеть их с помощью ls. Они устойчивы, потому что переживут перезагрузку компьютера, хотя любые непрочитанные данные в них в это время будут отброшены.
Именованные каналы использовались одновременно много раз, чтобы позволить различным процессам отправлять и получать данные, но я давно не видел, чтобы они использовались таким образом. Без сомнения, есть люди, которые все еще используют их с большим эффектом, но в последнее время я не встречал ни одного. Но для полноты картины или просто для удовлетворения вашего любопытства вот как вы можете их использовать.
Именованные каналы создаются с помощью команды mkfifo. Эта команда создаст именованный канал называется «geek-pipe» в текущем каталоге.
mkfifo geek-pipe
Мы можем увидеть детали именованного канала, если воспользуемся командой ls с параметром -l (длинный формат):
ls -l geek-pipe
Первый символ в списке — это «p», что означает вертикальную черту. Если бы это было «d», это означало бы, что объект файловой системы является каталогом, а тире «-» означало бы, что это обычный файл.
Использование именованного канала
Воспользуемся нашей трубкой. Безымянные каналы, которые мы использовали в наших предыдущих примерах, передавали данные немедленно от отправляющей команды к принимающей. Данные, отправленные через именованный канал, останутся в канале до тех пор, пока не будут прочитаны. Данные фактически хранятся в памяти, поэтому размер именованного канала не будет изменяться в листингах ls, независимо от того, есть в нем данные или нет.
В этом примере мы будем использовать два окна терминала. Я использую метку:
# Terminal-1
в одном окне терминала и
# Terminal-2
в другом, так что вы можете различать их. Хэш «#» сообщает оболочке, что далее следует комментарий, и игнорировать его.
Давайте возьмем весь наш предыдущий пример и перенаправим его в именованный канал. Итак, мы используем как безымянные, так и именованные каналы в одной команде:
ls | rev | cut -d'.' -f1 | rev | sort | uniq -c > geek-pipe
Мы перенаправляем содержимое именованного канала в cat, чтобы cat отображал это содержимое во втором окне терминала. Вот результат:
И вы увидите, что вы вернулись в командную строку в первом окне терминала.
Итак, что только что произошло.
Мы перенаправили некоторый вывод в именованный канал.
Первое окно терминала не вернулось в командную строку.
Данные оставались в конвейере до тех пор, пока не были прочитаны из канала на втором терминале.
Нас вернули в командную строку в первом окне терминала.
Вы можете подумать, что можете запустить команду в первом окне терминала в качестве фоновой задачи, добавив & в конец команды. И ты был бы прав. В этом случае мы немедленно вернулись бы в командную строку.
Смысл отказа от фоновой обработки заключался в том, чтобы подчеркнуть, что именованный канал является блокирующим процессом. Помещение чего-либо в именованный канал открывает только один конец канала. Другой конец не открывается, пока программа чтения не извлечет данные. Ядро приостанавливает процесс в первом окне терминала до тех пор, пока данные не будут считаны с другого конца канала.
Сила труб
В настоящее время именованные трубы стали чем-то вроде новинки.
С другой стороны, простые старые конвейеры Linux - один из самых полезных инструментов, которые вы можете иметь в своем наборе инструментов окна терминала. Командная строка Linux начинает оживать для вас, и вы получаете совершенно новые возможности, когда можете организовать набор команд для достижения единого представления.
Заключительный совет: лучше всего писать передаваемые по конвейеру команды, добавляя по одной команде за раз и заставляя эту часть работать, а затем вставляя следующую команду по конвейеру.