Как да използвате Pipes в Linux

Използвайте Linux pipe, за да нарисувате как си сътрудничат помощните програми от командния ред. Опростете сложните процеси и увеличете производителността си, като използвате колекция от самостоятелни команди и ги превърнете в един целеустремен екип. Ние ви показваме как.

Тръбите са навсякъде

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

Linux pipes ви позволяват да извършвате действия, които не се поддържат извън кутията от черупка. Но тъй като философията на дизайна на Linux е да има много малки помощни програми, които изпълняват своето специална функция много добреи без ненужна функционалност — мантрата „направи едно нещо и го направи добре“ — можете да сглобявате низове от команди заедно с тръби, така че изходът на една команда да стане вход на друга. Всяка команда, която изпълнявате, носи своя уникален талант в екипа и скоро ще откриете, че сте събрали печеливш отбор.

Един прост пример

Да предположим, че имаме директория, пълна с много различни типове файлове. Искаме да знаем колко файла от определен тип има в тази директория. Има и други начини да направите това, но целта на това упражнение е да въведем тръби, така че ще го направим с тръби.

Можем лесно да получим списък с файловете, използвайки ls:

ls

За да отделим типа файл, който ни интересува, ще използваме grep. Искаме да намерим файлове, които имат думата „страница“ в името на файла или разширението на файла.

Ще използваме специалния символ на обвивката „|” за да прехвърлите изхода от ls в grep.

ls | grep "page"

ls -l |  grep

grep отпечатва редове, които съответства на неговия модел на търсене. Така че това ни дава списък, съдържащ само „.page“ файлове.

Дори този тривиален пример показва функционалността на тръбите. Резултатът от ls не беше изпратен до прозореца на терминала. Той беше изпратен на grep като данни, с които да работи командата grep. Резултатът, който виждаме, идва от grep, която е последната команда в тази верига.

  Как да играете игри Nintendo 64 на Linux

Удължаване на нашата верига

Нека започнем да разширяваме нашата верига от команди. Ние можем пребройте файловете „.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

Общият брой думи, знаци и редове са изброени в долната част на прозореца на терминала.

  Как да инсталирате най-новите AMDGPU-PRO драйвери на Linux

Ето начин да получите сортиран списък с уникалните разширения на файлове в текущата директория, с брой на всеки тип.

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

Първият знак в списъка е „p“, което означава, че е тръба. Ако беше „d“, това би означавало, че обектът на файловата система е директория, а тире „-“ би означавало, че е обикновен файл.

Използване на Named Pipe

Нека използваме нашата тръба. Неименуваните тръби, които използвахме в предишните ни примери, предаваха данните незабавно от командата за изпращане към командата за получаване. Данните, изпратени през наименувана тръба, ще останат в тръбата, докато не бъдат прочетени. Данните всъщност се съхраняват в паметта, така че размерът на наречената тръба няма да варира в списъците на ls, независимо дали има данни в нея или не.

  Как да настроите Firejail на Linux

Ще използваме два терминални прозореца за този пример. Ще използвам етикета:

# 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 започва да оживява за вас и вие получавате изцяло ново захранване, когато можете да организирате колекция от команди, за да създадете едно сплотено изпълнение.

Съвет за раздяла: Най-добре е да напишете командите си с канали, като добавяте една по една команда и накарате тази част да работи, след което въведете следващата команда.