Як використовувати Pipes в Linux

Використовуйте канали Linux, щоб створити хореографію того, як утиліти командного рядка співпрацюють. Спростіть складні процеси та підвищте свою продуктивність, використовуючи набір окремих команд і перетворюючи їх у єдину команду. Ми покажемо вам, як.

Труби всюди

Канали є однією з найкорисніших функцій командного рядка, які мають операційні системи Linux і Unix. Труби використовуються незліченною кількістю способів. Подивіться будь-яку статтю командного рядка Linux — на будь-якому веб-сайті, не тільки на нашому — і ви побачите, що канали з’являються частіше, ніж ні. Я переглянув деякі статті How-To Geek про Linux, і в усіх використовуються канали, так чи інакше.

Канали Linux дозволяють виконувати дії, які не підтримуються в готовому вигляді оболонка. Але оскільки філософія розробки Linux полягає в тому, щоб мати багато невеликих утиліт, які виконують своє виділена функція дуже добре, і без непотрібної функціональності — мантри «роби одну справу і зроби це добре» — ви можете звести рядки команд разом з каналами, щоб вихід однієї команди став входом іншої. Кожна команда, яку ви виконуєте, приносить команді свій унікальний талант, і незабаром ви виявите, що зібрали команду-переможець.

Простий приклад

Припустимо, що у нас є каталог, наповнений багатьма різними типами файлів. Ми хочемо знати, скільки файлів певного типу знаходиться в цьому каталозі. Є й інші способи зробити це, але метою цієї вправи є введення труб, тому ми збираємося зробити це з трубами.

Ми можемо легко отримати список файлів, використовуючи ls:

ls

Щоб виділити цікавий тип файлу, ми будемо використовувати grep. Ми хочемо знайти файли, у назві чи розширенні файлу яких є слово «сторінка».

Ми будемо використовувати спеціальний символ оболонки «|» щоб передати вихід з ls в grep.

ls | grep "page"

ls -l |  grep

grep друкує рядки, які відповідати його шаблону пошуку. Таким чином, це дає нам список, що містить лише файли «.page».

Навіть цей тривіальний приклад демонструє функціональність труб. Висновок з ls не був надісланий у вікно терміналу. Він був надісланий до grep як дані для роботи з командою grep. Вихід, який ми бачимо, надходить від grep, яка є останньою командою в цьому ланцюжку.

Розширюємо наш ланцюг

Давайте почнемо розширювати наш ланцюжок команд із каналами. Ми можемо підрахувати файли «.page». додавши команду wc. Ми будемо використовувати параметр -l (кількість рядків) із wc. Зауважте, що ми також додали параметр -l (довгий формат) до ls . Незабаром ми скористаємося цим.

ls - | grep "page" | wc -l

ls - |  grep

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

Вихідні дані тепер відсортовано за розміром файлу з нашим індивідуальним вибором трьох стовпців.

Додавання іншої команди

Ми завершимо, додавши команду tail. Ми скажемо йому, щоб перерахувати останні п’ять рядків виводу тільки

ls -l | grep "page" | awk '{print $5 " " $3 " " $9}' | sort -n | tail -5

Це означає, що наша команда перекладається як «покажи мені п’ять найбільших файлів «.page» у цьому каталозі, упорядкованих за розміром». Звичайно, для цього немає команди, але за допомогою каналів ми створили свої власні. Ми могли б додати цю — або будь-яку іншу довгу команду — як псевдонім або функцію оболонки, щоб зберегти весь введений текст.

Ось вихід:

Ми могли б змінити порядок розмірів, додавши параметр -r (зворотний) до команди сортування та використавши голову замість хвоста для виділення рядків від верхньої частини виходу.

Цього разу п’ять найбільших файлів «.page» перераховані від найбільшого до найменшого:

Деякі останні приклади

Ось два цікавих приклади з останніх статей про технічних спеціалістів.

Деякі команди, такі як xargscommand, розроблені щоб вхідні дані були передані до них. Ось як ми можемо запропонувати wc підрахувати слова, символи та рядки у кількох файлах, передаючи ls у xargs, який потім передає список імен файлів у wc, як ніби вони були передані wc як параметри командного рядка.

ls *.page | xargs wc

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

Ось спосіб отримати відсортований список унікальних розширень файлів у поточному каталозі з кількістю кожного типу.

ls | rev | cut -d'.' -f1 | rev | sort | uniq -c

Тут багато чого відбувається.

ls: виводить список файлів у каталозі
обороти: Перевертає текст в іменах файлів.
вирізати: Обрізає струну при першому входженні вказаного роздільника «.». Текст після цього відкидається.
rev: повертає текст, що залишився, який є розширенням імені файлу.
сортування: сортує список за алфавітом.
uniq: підраховує кількість кожного унікальний запис у списку.

Результат показує список розширень файлів, відсортований за алфавітом із кількістю кожного унікального типу.

Іменовані труби

Нам доступний інший тип труб, які називаються трубами. Канали в попередніх прикладах створюються на льоту оболонкою, коли вона обробляє командний рядок. Труби створюються, використовуються, а потім викидаються. Вони швидкоплинні і не залишають слідів. Вони існують лише доти, доки виконується команда, яка їх використовує.

Іменовані канали відображаються як постійні об’єкти у файловій системі, тому ви можете побачити їх за допомогою ls. Вони стійкі, тому що витримають перезавантаження комп’ютера, хоча всі непрочитані дані в них на той момент будуть відкинуті.

Іменовані канали свого часу часто використовувалися, щоб дозволити різним процесам надсилати та отримувати дані, але я давно не бачив, щоб вони використовувалися таким чином. Безсумнівно, є люди, які все ще використовують їх з великим ефектом, але останнім часом я не стикався з ними. Але для повноти чи просто щоб задовольнити вашу цікавість, ось як їх можна використовувати.

Іменовані канали створюються за допомогою команди mkfifo. Ця команда створить іменований канал у поточному каталозі називається «geek-pipe».

mkfifo geek-pipe

Ми можемо побачити деталі названого каналу, якщо використаємо команду ls з параметром -l (довгий формат):

ls -l geek-pipe

Першим символом списку є «р», що означає канвелю. Якби це була «d», це означало б, що об’єкт файлової системи є каталогом, а тире «-» означало б, що це звичайний файл.

Використання Named Pipe

Скористаємося нашою трубою. Безіменні канали, які ми використовували в наших попередніх прикладах, передавали дані негайно від команди відправлення команді-отримувачу. Дані, надіслані через іменований канал, залишаться в каналі, доки не будуть прочитані. Дані фактично зберігаються в пам’яті, тому розмір названого каналу не буде змінюватися в списках ls незалежно від того, є в ньому дані чи ні.

Для цього прикладу ми будемо використовувати два вікна терміналу. Я буду використовувати етикетку:

# Terminal-1

в одному вікні терміналу і

# Terminal-2

в іншому, щоб ви могли розрізняти їх. Хеш «#» повідомляє оболонці, що далі є коментарем, і ігнорувати його.

Давайте розглянемо весь наш попередній приклад і перенаправимо його в названий канал. Отже, ми використовуємо і безіменний, і іменований канали в одній команді:

ls | rev | cut -d'.' -f1 | rev | sort | uniq -c > geek-pipe

ls |  rev |  скоротити -d'.  -f1 |  rev |  сортувати |  uniq -c > geek-pipe у вікні терміналу” width=”646″ height=”97″ onload=”pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);”  onerror=”this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);”></p>
<p>Здається, нічого особливого не станеться.  Ви можете помітити, що ви не повертаєтеся до командного рядка, отже, щось відбувається.</p>
<p>У іншому вікні терміналу введіть таку команду:</p>
<pre>cat < geek- труба</pre>
<p><img loading=

Ми перенаправляємо вміст іменованого каналу в cat, щоб кіт відображав цей вміст у другому вікні терміналу. Ось результат:

І ви побачите, що вас повернули до командного рядка в першому вікні терміналу.

Отже, що щойно сталося.

Ми перенаправили деякий вихід в названий канал.
Перше вікно терміналу не повернулося до командного рядка.
Дані залишалися в каналі, поки не були зчитовані з каналу в другому терміналі.
Ми повернулися до командного рядка у першому вікні терміналу.

Можливо, ви думаєте, що можна запустити команду в першому вікні терміналу як фонове завдання, додавши & до кінця команди. І ти був би правий. У цьому випадку ми негайно були б повернуті до командного рядка.

Суть не використання фонової обробки полягала в тому, щоб підкреслити, що іменований канал є блокуючим процесом. Поміщення чогось у названу трубу відкриває лише один кінець труби. Інший кінець не відкривається, доки програма читання не витягне дані. Ядро призупиняє процес у першому вікні терміналу, поки дані не будуть прочитані з іншого кінця каналу.

Сила труб

У наш час іменовані труби є чимось новинкою.

З іншого боку, звичайні старі канали Linux є одним із найкорисніших інструментів, які ви можете мати у своєму наборі інструментів вікна терміналу. Командний рядок Linux починає оживати для вас, і ви отримуєте абсолютно новий потенціал, коли можете організувати набір команд, щоб створити єдину цілісну роботу.

Підказка про розставання: найкраще писати свої команди, додаючи по одній команді, і запустити цю частину, а потім додавати наступну команду.