Använd Linux-pipes för att samordna interaktionen mellan kommandoradsverktyg. Förenkla komplexa arbetsflöden och öka din produktivitet genom att använda en samling av oberoende kommandon som samverkar mot ett specifikt mål. Vi förklarar hur det går till.
Rör finns överallt
Pipes är en av de mest grundläggande funktionerna i kommandoraden för Linux och Unix-liknande operativsystem. Rör används på otaliga sätt. I princip alla artiklar om Linux-kommandoraden – oavsett webbplats – så stöter man på rör. En snabb genomgång av How-To Geeks artiklar om Linux visar att rör förekommer i alla, på ett eller annat vis.
Linux-pipes gör det möjligt att utföra operationer som inte direkt stöds av skalet. Linux filosofi är att använda många små verktyg som utför sina specifika uppgifter mycket väl, utan onödiga funktioner. Genom att koppla ihop dessa kommandon med rör kan utdata från ett kommando bli indata för ett annat. Varje kommando bidrar med sin unika förmåga till helheten, och snart har du en kraftfull kedja av operationer.
Ett enkelt exempel
Låt säga att vi har en katalog full av 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 åstadkomma detta, men vårt syfte är att introducera rör, så vi använder dem.
Vi kan enkelt lista alla filer med kommandot `ls`:
ls
För att filtrera ut en specifik filtyp använder vi `grep`. Vi vill hitta alla filer som har ordet ”sida” i filnamnet eller tillägget.
Vi använder skalets specialtecken `|` för att skicka utdata från `ls` till `grep`:
ls | grep "page"
`grep` skriver ut alla rader som matchar sökmönstret. Resultatet är en lista som endast innehåller ”.page”-filer.
Detta enkla exempel visar hur rör fungerar. Utdatan från `ls` skickades inte till terminalfönstret. Istället skickades den till `grep` som indata. Utdatan vi ser kommer från `grep`, som är det sista kommandot i kedjan.
Utöka kedjan
Låt oss utöka kommandokedjan. Vi kan räkna ”.page”-filerna genom att lägga till kommandot `wc`. Vi använder option `-l` (antal rader) med `wc`. Notera att vi även har lagt till option `-l` (långt format) till `ls`. Vi kommer snart att använda detta.
ls -l | grep "page" | wc -l
`grep` är inte längre det sista kommandot i kedjan, så vi ser inte dess utdata. Istället matas utdata från `grep` in i kommandot `wc`. Det som visas i terminalfönstret kommer från `wc`. `wc` rapporterar att det finns 69 ”.page”-filer i katalogen.
Låt oss utöka kedjan igen. Vi tar bort kommandot `wc` och ersätter det med `awk`. Utdatan från `ls -l` har nio kolumner. Vi använder `awk` för att skriva ut kolumnerna fem, tre och nio. Dessa motsvarar storlek, ägare och filnamn.
ls -l | grep "page" | awk '{print $5 " " $3 " " $9}'
Vi får en lista med dessa kolumner för varje matchande fil.
Vi skickar nu den utdatan genom kommandot `sort`. Vi använder option `-n` (numerisk) för att tala om för `sort` att den första kolumnen ska behandlas som tal.
ls -l | grep "page" | awk '{print $5 " " $3 " " $9}' | sort -n
Utdatan är nu sorterad efter filstorlek, med vårt anpassade urval av tre kolumner.
Lägg till ännu ett kommando
Slutligen lägger vi till kommandot `tail`. Vi kommer att be den visa de sista fem raderna av utdatan.
ls -l | grep "page" | awk '{print $5 " " $3 " " $9}' | sort -n | tail -5
Detta kommando kan tolkas som ”visa mig de fem största ’.page’-filerna i den här katalogen, sorterade efter storlek”. Det finns inget enskilt kommando för att göra detta, men med hjälp av rör har vi skapat vårt eget. Vi kan lägga till detta – eller andra långa kommandon – som ett alias eller en funktion i skalet för att slippa skriva allt manuellt.
Här är utdatan:
Vi kan ändra sorteringsordningen genom att lägga till option `-r` (omvänd) till kommandot `sort`, och använda `head` istället för `tail` för att välja raderna från början av utdatan.
Nu listas de fem minsta ”.page”-filerna, från minsta till största:
Några andra exempel
Här är två intressanta exempel från nyligen publicerade How-To artiklar.
Vissa kommandon, som `xargs`, är skapade för att ta emot indata. Här är ett sätt att låta `wc` räkna ord, tecken och rader i flera filer. `ls` skickar filnamnen till `xargs`, som i sin tur matar filnamnen till `wc` som om de hade angetts som kommandoradsparametrar.
ls *.page | xargs wc
Det totala antalet ord, tecken och rader visas längst ned i terminalfönstret.
Här är ett sätt att få en sorterad lista över de unika filändelserna i den aktuella katalogen, tillsammans med antalet av varje typ.
ls | rev | cut -d'.' -f1 | rev | sort | uniq -c
Det händer mycket här.
`ls`: Listar filerna i katalogen.
`rev`: Vänder på texten i filnamnen.
`cut`: Klipper av strängen vid första förekomsten av avgränsaren ’.’. Texten efter detta kasseras.
`rev`: Vänder på den återstående texten, dvs filändelsen.
`sort`: Sorterar listan i alfabetisk ordning.
`uniq`: Räknar antalet av varje unikt element i listan.
Utdatan visar listan över filändelser, sorterade i alfabetisk ordning med antalet av varje unik typ.
Namngivna rör
Det finns en annan typ av rör tillgänglig, kallade namngivna rör. De rör vi använt i tidigare exempel skapas direkt av skalet när kommandoraden bearbetas. Rören skapas, används och kasseras sedan. De är temporära och lämnar inga spår. De existerar bara så länge kommandot som använder dem körs.
Namngivna rör visas som permanenta objekt i filsystemet, så du kan se dem med `ls`. De är permanenta eftersom de överlever en omstart av datorn – även om all oläst data i dem kommer att kasseras vid den tidpunkten.
Namngivna rör användes mycket tidigare för att tillåta olika processer att kommunicera med varandra, men de används inte lika mycket nu. Det finns säkert de som fortfarande använder dem effektivt, men det är inte så vanligt. I alla fall, för fullständighetens skull, så här kan du använda dem.
Namngivna rör skapas med kommandot `mkfifo`. Detta kommando skapar ett namngivet rör med namnet ”geek-pipe” i den aktuella katalogen.
mkfifo geek-pipe
Vi kan visa detaljerna för det namngivna röret med kommandot `ls -l`:
ls -l geek-pipe
Det första tecknet i listan är ett `p`, vilket betyder att det är ett rör. Om det vore ett `d` skulle det innebära att filsystemsobjektet är en katalog, och ett bindestreck `-` skulle betyda att det är en vanlig fil.
Använda det namngivna röret
Låt oss använda vårt rör. De namnlösa rör vi använde tidigare skickade data direkt från det sändande kommandot till det mottagande kommandot. Data som skickas genom ett namngivet rör stannar i röret tills det läses. Data lagras faktiskt i minnet, så storleken på det namngivna röret varierar inte i `ls`-listorna, oavsett om det finns data i det eller inte.
Vi använder två terminalfönster för detta exempel. Jag använder etiketten:
# Terminal-1
i ett terminalfönster och
# Terminal-2
i det andra, så att du kan skilja på dem. Hashtaggen `#` säger till skalet att det som följer är en kommentar och ska ignoreras.
Låt oss ta hela vårt tidigare exempel och omdirigera 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
Vi omdirigerar innehållet i det namngivna röret till `cat`, så att `cat` visar innehållet i det andra terminalfönstret. Här är utdatan:
Och du ser att du har återgått till kommandotolken i det första terminalfönstret.
Så, vad hände egentligen?
Vi omdirigerade 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 återgick 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 ett `&` i slutet av kommandot. Det stämmer. I så fall skulle vi ha återgått till kommandotolken direkt.
Poängen med att inte använda bakgrundskörning är att markera att ett namngivet rör är en blockerande process. Att lägga data i ett namngivet rör öppnar bara ena änden av röret. Den andra änden öppnas inte förrän ett program läser datan. Kärnan avbryter processen i det första terminalfönstret tills data läses från den andra änden av röret.
Rörens kraft
Idag är namngivna rör mest en kuriositet.
Däremot är vanliga Linux-rör ett av de mest användbara verktyg du kan ha i din terminalverktygslåda. Linux-kommandoraden blir levande, och du får en helt ny kraft när du kan samordna en samling kommandon för att skapa en sammanhängande funktion.
Sista tips: Det är bäst att bygga dina kommandon genom att lägga till ett kommando i taget och se till att den delen fungerar innan du går vidare.