Hur man använder Pipes på Linux

Använd Linux-pipes för att koreografera hur kommandoradsverktyg samarbetar. Förenkla komplexa processer och höj din produktivitet genom att utnyttja en samling fristående kommandon och förvandla dem till ett målmedvetet team. Vi visar dig hur.

Rör finns överallt

Pipes är en av de mest användbara kommandoradsfunktionerna som Linux och Unix-liknande operativsystem har. Rör används på otaliga sätt. Titta på vilken Linux-kommandoradsartikel som helst – på vilken webbplats som helst, inte bara vår – och du kommer att se att pipes dyker upp oftare än inte. Jag granskade några av How-To Geeks Linux-artiklar, och pipes används i dem alla, på ett eller annat sätt.

Linux-pipes låter dig utföra åtgärder som inte stöds direkt av skal. Men eftersom Linux designfilosofi är att ha många små verktyg som utför sina dedikerad funktion mycket bra, och utan onödig funktionalitet – ”gör en sak och gör det bra”-mantrat – kan du plumba strängar av kommandon tillsammans med rör så att utdata från ett kommando blir indata från ett annat. Varje kommando du skickar in tar med sig sin unika talang till laget, och snart upptäcker du att du har satt ihop en vinnande trupp.

Ett enkelt exempel

Anta att vi har en katalog full av många olika typer av filer. Vi vill veta hur många filer av en viss typ som finns i den katalogen. Det finns andra sätt att göra detta på, men syftet med den här övningen är att introducera rör, så vi ska göra det med rör.

Vi kan enkelt få en lista över filerna med ls:

ls

För att skilja ut filtypen av intresse använder vi grep. Vi vill hitta filer som har ordet ”sida” i sitt filnamn eller filtillägg.

Vi kommer att använda skalets specialtecken ”|” för att skicka utdata från ls till grep.

ls | grep "page"

ls -l |  grep

grep skriver ut rader som matcha dess sökmönster. Så detta ger oss en lista som endast innehåller ”.page”-filer.

Även detta triviala exempel visar rörens funktionalitet. Utdata från ls skickades inte till terminalfönstret. Det skickades till grep som data för kommandot grep att arbeta med. Utdatan vi ser kommer från grep, som är det sista kommandot i denna kedja.

Förlänger vår kedja

Låt oss börja utöka vår kedja av kommandon. Vi kan räkna ”.page”-filerna genom att lägga till kommandot wc. Vi kommer att använda alternativet -l (radantal) med wc. Observera att vi också har lagt till alternativet -l (långt format) till ls . Vi kommer att använda detta inom kort.

ls - | grep "page" | wc -l

ls - |  grep

grep är inte längre det sista kommandot i kedjan, så vi ser inte dess utdata. Utdata från grep matas in i wc-kommandot. Utgången vi ser i terminalfönstret är från wc. wc rapporterar att det finns 69 ”.page”-filer i katalogen.

Låt oss utöka saker igen. Vi tar bort kommandot wc från kommandoraden och ersätter det med awk. Det finns nio kolumner i utdata från ls med alternativet -l (långt format). Vi kommer att använda awk till skriva ut kolumner fem, tre och nio. Dessa är storleken, ägaren och namnet på filen.

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

Vi får en lista över dessa kolumner, för var och en av de matchande filerna.

Vi skickar nu den utmatningen genom sorteringskommandot. Vi använder alternativet -n (numeriskt) för att låta sorteringen veta att den första kolumnen ska vara behandlas som siffror.

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

Utdata är nu sorterade i filstorleksordning, med vårt anpassade urval av tre kolumner.

Lägger till ytterligare ett kommando

Vi avslutar med att lägga till svanskommandot. Vi kommer att berätta för den att lista sista fem raderna av utdata endast.

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

Det betyder att vårt kommando översätts till något som ”visa mig de fem största ”.page”-filerna i den här katalogen, sorterade efter storlek.” Naturligtvis finns det inget kommando för att åstadkomma det, men genom att använda rör har vi skapat våra egna. Vi skulle kunna lägga till detta – eller vilket annat långt kommando som helst – som ett alias eller skalfunktion för att spara all skrivning.

Här är utgången:

Vi kan vända storleksordningen genom att lägga till alternativet -r (omvänd) till sorteringskommandot och använda huvud istället för svans för att välja linjerna från toppen av utgången.

Den här gången listas de fem största ”.page”-filerna från största till minsta:

Några senaste exempel

Här är två intressanta exempel från de senaste How-To-nördartiklarna.

Vissa kommandon, som xargskommandot, är designade att få inmatning till dem. Här är ett sätt vi kan få wc att räkna ord, tecken och rader i flera filer, genom att skicka ls till xargs som sedan matar listan med filnamn till wc som om de hade skickats till wc som kommandoradsparametrar.

ls *.page | xargs wc

Det totala antalet ord, tecken och rader listas längst ner i terminalfönstret.

Här är ett sätt att få en sorterad lista över de unika filtilläggen i den aktuella katalogen, med ett antal av varje typ.

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

Det händer mycket här.

ls: Listar filerna i katalogen
varv: Vänder om texten i filnamnen.
skära: Klipper av snöret vid den första förekomsten av den angivna avgränsaren ””. Text efter detta kasseras.
rev: Vänder om den återstående texten, som är filnamnstillägget.
sortera: Sorterar listan i alfabetisk ordning.
uniq: Räknar antalet av varje unik post i listan.

Utdata visar listan över filtillägg, sorterade i alfabetisk ordning med ett antal av varje unik typ.

Namngivna Pipes

Det finns en annan typ av rör tillgänglig för oss, som kallas namngivna rör. Pipen i de tidigare exemplen skapas direkt av skalet när det bearbetar kommandoraden. Rören skapas, används och kasseras sedan. De är övergående och lämnar inga spår av sig själva. De existerar bara så länge som kommandot som använder dem körs.

Namngivna rör visas som beständiga objekt i filsystemet, så du kan se dem med ls. De är ihållande eftersom de kommer att överleva en omstart av datorn – även om all oläst data i dem vid den tiden kommer att kasseras.

Namngivna rör användes mycket på en gång för att tillåta olika processer att skicka och ta emot data, men jag har inte sett dem användas på det sättet på länge. Det finns ingen tvekan om att det finns människor där ute som fortfarande använder dem med stor effekt, men jag har inte stött på några nyligen. Men för fullständighetens skull, eller bara för att stilla din nyfikenhet, så här kan du använda dem.

Namngivna rör skapas med kommandot mkfifo. Detta kommando kommer att skapa ett namngivet rör kallas ”geek-pipe” i den aktuella katalogen.

mkfifo geek-pipe

Vi kan se detaljerna för det namngivna röret om vi använder kommandot ls med alternativet -l (långt format):

ls -l geek-pipe

Det första tecknet i listan är ett ”p”, vilket betyder att det är ett rör. Om det var ett ”d” skulle det betyda att filsystemobjektet är en katalog, och ett bindestreck ”-” skulle betyda att det är en vanlig fil.

Använder det namngivna röret

Låt oss använda vår pipa. De namnlösa rören som vi använde i våra tidigare exempel skickade data omedelbart från det sändande kommandot till det mottagande kommandot. Data som skickas genom ett namngivet rör kommer att stanna i röret tills det läses. Data lagras faktiskt i minnet, så storleken på det namngivna röret kommer inte att variera i ls-listorna om det finns data i det eller inte.

Vi kommer att använda två terminalfönster för detta exempel. Jag använder etiketten:

# Terminal-1

i ett terminalfönster och

# Terminal-2

i den andra, så att du kan skilja på dem. Hashen ”#” talar om för skalet att det som följer är en kommentar och att ignorera den.

Låt oss ta hela vårt tidigare exempel och dirigera om det till det namngivna röret. Så vi använder både namnlösa och namngivna rör i ett kommando:

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

ls |  rev |  klippa -d'.'  -f1 |  rev |  sortera |  uniq -c > geek-pipe i ett terminalfönster” width=”646″ height=”97″ onload=”pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);”  onerror=”this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);”></p>
<p>Inget mycket kommer att tyckas hända.  Du kanske märker att du inte kommer tillbaka till kommandotolken, så något är på gång.</p>
<p>I det andra terminalfönstret, utfärda följande kommando:</p>
<pre>cat < geek- pipe</pre>
<p><img loading=

Vi omdirigerar innehållet i det namngivna röret till cat, så att katten kommer att visa innehållet i det andra terminalfönstret. Här är utgången:

Och du kommer att se att du har återvänt till kommandotolken i det första terminalfönstret.

Så, vad hände just.

Vi omdirigerade en del utdata till det namngivna röret.
Det första terminalfönstret återgick inte till kommandotolken.
Data fanns kvar i röret tills det lästes från röret i den andra terminalen.
Vi återvände till kommandotolken i det första terminalfönstret.

Du kanske tänker att du kan köra kommandot i det första terminalfönstret som en bakgrundsuppgift genom att lägga till en & i slutet av kommandot. Och du skulle ha rätt. I så fall skulle vi ha återvänt till kommandotolken omedelbart.

Poängen med att inte använda bakgrundsbearbetning var att markera att ett namngivet rör är en blockeringsprocess. Att stoppa in något i ett namngivet rör öppnar bara ena änden av röret. Den andra änden öppnas inte förrän läsprogrammet extraherar data. Kärnan avbryter processen i det första terminalfönstret tills data läses från den andra änden av röret.

Kraften i rör

Nuförtiden är namngivna pipor något av en nyhet.

Vanliga gamla Linux-rör, å andra sidan, är ett av de mest användbara verktygen du kan ha i din terminalfönsterverktygslåda. Linux-kommandoraden börjar bli levande för dig, och du får en helt ny kraft när du kan orkestrera en samling kommandon för att producera en sammanhängande föreställning.

Avskedstips: Det är bäst att skriva dina kommandon genom att lägga till ett kommando i taget och få den delen att fungera, och sedan lägga in nästa kommando.