Pípur og staðalstraumar
Ein öflugasta hugmyndin í Linux er hvernig forrit geta talað saman. Í stað þess að smíða eitt risastórt forrit sem gerir allt getum við skeytt saman mörgum litlum forritum til að framkvæma flókin verkefni.
Staðalstraumar
Sérhvert forrit sem keyrir í Linux opnar sjálfkrafa þrjár samskiptarásir sem kallast staðalstraumar (e. standard streams):
- Staðalinntak (e. stdin): Hér hlustar forritið. Oftast kemur þetta frá lyklaborðinu.
- Staðalúttak (e. stdout): Hér talar forritið. Oftast fer þetta á skjáinn.
- Staðalvilla (e. stderr): Sérstök rás fyrir villumeldingar.
Af hverju tvö úttök?
Ef forrit á að skila gögnum viljum við ekki endilega blanda villumeldingum saman við gögnin. Með sérstöku stderr getum við visað niðurstöður og villur á mismunandi stöðum.
Með því að keyra skipanirnar
cd ~/examples
ls welcome.txt engin-svona-skra.txt
Hefðin: skrá sem viðfang eða gögn úr staðalinntaki
Mörg klassísk Linux-forrit fylgja þeirri mikilvægu hefð að ef skrá eða gögn eru gefin sem viðfang þá vinnur forritið með þau, en ef ekkert viðfang er gefið les það úr staðalinntaki.
Þetta er ein helsta ástæðan fyrir því að pípur virka svona vel, þar sem sama forritið getur bæði unnið beint úr skrá og tekið við gögnum frá öðru forriti. Til dæmis mun skipunin sort (stytting á sort) skila sömu raðanlegu niðurstöðunni á mismunandi hátt:
sort data/names.txt # sort les skrána data/names.txt
cat data/names.txt | sort # sort les sömu gögn úr stdin
Fleiri dæmi á borð við notkun á skipuninni wc (stytting á word count) og grep (stytting á global regular expression print):
wc -l skjal.txt # telur línur í skrá
cat skjal.txt | wc -l # telur línur sem koma úr pípu
grep "Halló" skjal.txt # leitar í skrá
cat skjal.txt | grep "Halló" # leitar í stdin
Ekki öll forrit fylgja hefðinni fullkomlega
Mörg textavinnslutól gera þetta, t.d. sort, grep, wc, sed og awk. Sum forrit þurfa samt alltaf skráarnafn eða nota aðra hegðun. Ef þú ert óviss er best að skoða --help eða man.
Prófaðu: sömu gögn, tvær leiðir
Notaðu sort og wc -l bæði með skráarnafni og með pípu.
Lausn
Við getum framkvæmt þetta á tvo vegu með því að keyra skipanirnar
sort data/names.txt
cat data/names.txt | sort
wc -l data/names.txt
cat data/names.txt | wc -l
Endurvísun
Endurvísun (e. redirection) breytir því hvaðan forrit les eða hvert það skrifar í skráakerfinu.
Úttak í skrá: > og >>
Með því að nota endurvísunartáknin getum við keyrt skipanir á borð við
ls > listi.txt # býr til eða yfirskrifar
ls >> listi.txt # bætir aftan við
Inntak úr skrá: <
Á sama hátt er hægt að keyra skipunina
sort < data/names.txt
< okkur á að gögnin eru lesin úr staðalinntaki.
Villur í skrá: 2>
Þegar við viljum sía út og vista villuboð sérstaklega getum við beitt skipuninni
find / -name "skjal.txt" 2> villur.log
stderr yfir í skrána villur.log.
Allt í eina skrá: 2>&1
Ef við kjósum að beina bæði venjulegu úttaki og villuboðum á sama staðinn getum við keyrt
skipun > allt.txt 2>&1
stdout sendist í allt.txt og stderr á sama stað. Hér skiptir röðin miklu máli því við skilgreinum fyrst hvert venjulegt úttak fer og tengjum villustrauminn svo við þá slóð.
Senda í svartholið: /dev/null
Ef við viljum hreinlega farga úttaki eða villuboðum sem við höfum engan áhuga á getum við notað skipanir eins og
skipun > /dev/null
skipun 2> /dev/null
/dev/null virkar sem svarthol sem eyðir öllum gögnum sem þangað eru send.
Prófaðu: vista úttak
Vistaðu raðaðan lista af nöfnum í playground/sorted-names.txt og bættu svo línufjölda aftan við sömu skrá.
Lausn
Við getum notað endurvísun og fylgt þessum skrefum
sort data/names.txt > playground/sorted-names.txt
wc -l data/names.txt >> playground/sorted-names.txt
cat playground/sorted-names.txt
Prófaðu: aðskilja villur og úttak
Láttu ls reyna að sýna eina skrá sem er til og eina sem er ekki til. Vistaðu venjulegt úttak og villur í sitthvora skrána.
Lausn
Til þess að aðskilja staðalúttak og staðalvillu getum við keyrt skipunina
ls welcome.txt engin-svona-skra.txt > playground/ut.txt 2> playground/villur.txt
cat playground/ut.txt
cat playground/villur.txt
Pípur: |
Pípa tengir staðalúttak einnar skipunar beint við staðalinntak annarrar, sem við getum táknað með flæðinu
forrit1 | forrit2 | forrit3
Sem dæmi getum við notað keðjuna, þar sem tekin er inn skipunin uniq (stytting á unique):
cat data/names.txt | sort | uniq
Með því að vinna með tilbúnu æfingagögnunum okkar getum við prófað að keyra skipanir á borð við
cat notes/duplicate_lines.txt | sort | uniq
cat notes/duplicate_lines.txt | sort | uniq -c
Oft má sleppa cat
cat skrá.txt | grep orð virkar, en grep orð skrá.txt er einfaldara. cat er samt stundum gagnlegt þegar við erum að hugsa um pípuna sem færiband.
Litir og pípur
Mörg forrit geta greint hvort staðalúttakið þeirra fer beint í skeljagluggann eða áfram í pípu eða skrá. Þegar úttakið fer beint á skjáinn er oft gagnlegt að nota liti, en þegar úttakið fer í pípu geta litir verið til vandræða þar sem þeir samanstanda af sérstökum stýritáknum inni í textanum.
Þess vegna slökkva mörg forrit sjálfkrafa á litum þegar þau sjá að úttakið fer ekki beint á skjá, sem við getum sannreynt með því að keyra
ls --color=auto
ls --color=auto | cat
cat.
Sama á við þegar við keyrum skipanir á borð við
grep --color=auto "root" /etc/passwd
grep --color=auto "root" /etc/passwd | cat
Þvingaðir litir
Sum forrit leyfa þér að stjórna þessu, t.d. með --color=always, --color=auto eða --color=never. Ef þú notar --color=always í pípu geta litakóðarnir ferðast áfram og stundum ruglað önnur forrit sem eiga að vinna með hreinan texta.
Algeng tól í pípum
| Skipun | Hlutverk |
|---|---|
sort |
Raðar línum |
uniq |
Fjarlægir eða telur endurteknar línur sem standa saman |
wc |
Telur línur, orð og bæti |
cut |
Klippir út dálka eða stafi |
tr |
Skiptir út eða eyðir stöfum |
tee |
Skrifar bæði á skjá og í skrá |
sed |
Breytir textastraumi línu fyrir línu |
awk |
Vinnur með dálka og mynstur |
xargs |
Breytir línum úr inntaki í viðföng fyrir skipun |
tee: sjá og vista í einu
Skipunin tee (dregið af T-stykki í pípulögnum) virkar eins og T-stykki í vatnslögn þannig að úttakið fer bæði á skjáinn og í tilgreinda skrá. Við getum prófað þetta með því að keyra
ls -la | tee listi.txt
listi.txt.
Prófaðu einnig að nota skipunina cut (stytting á cut) og keyra:
cut -d, -f1 data/scores.csv | tee playground/names-from-csv.txt
tr: breyta stöfum
Ef við þurfum að skipta út eða breyta tilteknum stöfum í texta getum við notað skipunina tr (stytting á translate) eins og í eftirfarandi dæmi:
echo "Halló" | tr '[:lower:]' '[:upper:]'
echo "a,b,c" | tr ',' '\n'
sed: einföld textabreyting
Skipunin sed (stytting á stream editor) er sérstaklega hönnuð til að eiga við textastrauma og með keyrslu á borð við
echo "Halló heimur" | sed 's/heimur/Linux/'
heimur fyrir Linux á fljótlegan hátt.
awk: vinna með dálka
Þegar vinna þarf með flóknara dálka- eða línuskipulag er gott að keyra skipunina awk (nefnd eftir höfundum sínum Aho, Weinberger og Kernighan) eins og í eftirfarandi dæmi:
awk '{print $1}' logs/access.log
awk -F: '{print $1, $7}' /etc/passwd
awk vinnur með hvern dálk fyrir sig. Sjálfgefið notar það bil sem skilju, en með fánanum -F: getum við breytt því í tvípunkt.
Prófaðu einnig að vinna með CSV-skrána okkar með því að keyra
awk -F, '{print $1, $3}' data/scores.csv
xargs: nota lista sem viðföng
Þegar við viljum breyta lista yfir skrár yfir í viðföng fyrir aðra skipun getum við notað skipunina xargs (stytting á extended arguments) og keyrt:
find . -name "*.txt" | xargs wc -l
find finnur skrárnar og xargs sendir þær áfram til línutalningar.
Skráarnöfn geta innihaldið bil
Þegar við notum find með xargs er öruggara að nota núllstaf sem skilju með skipuninni
find . -name "*.txt" -print0 | xargs -0 wc -l
Raunverulegt dæmi: greina textaskrá
Segjum að við séum með logs/access.log skrá með mörgum línum og markmið okkar sé að finna þær 5 IP-tölur sem koma oftast fyrir í fyrsta dálki skráarinnar. Til þess getum við skeytt saman mörgum tólum og keyrt flókna keðju á borð við
cut -d' ' -f1 logs/access.log | sort | uniq -c | sort -nr | head -n 5
Í þessari skipun fylgjum við þessum skrefum:
cut -d' ' -f1: klippir út fyrsta dálkinn þar sem IP-talan er að finna.sort: raðar öllum línum saman svo hægt sé að telja þær.uniq -c: telur nákvæmlega hve oft hver IP-tala kemur fyrir.sort -nr: raðar niðurstöðunum tölulega þannig að stærsta talan komi fyrst.head -n 5: síar út og sýnir okkur einungis efstu 5 línurnar.
Prófaðu sjálf/ur
Hvernig myndirðu telja hversu margar einstakar línur eru í data/names.txt?
Ein lausn
Við getum raðað og eytt endurtekningum áður en við teljum með því að keyra
sort data/names.txt | uniq | wc -l
Prófaðu: algengasti liturinn
Hvaða litur kemur oftast fyrir í data/colors.txt?
Lausn
Við getum raðað litunum og síað þann vinsælasta út með því að keyra
sort data/colors.txt | uniq -c | sort -nr | head -n 1
Prófaðu: hæstu stigin
Sýndu þrjár hæstu línurnar í data/scores.csv eftir stigum. Sleppum hauslínunni fyrst.
Lausn
Við getum beitt tail og sort saman og keyrt
tail -n +2 data/scores.csv | sort -t, -k3 -nr | head -n 3
Prófaðu: loggskrá í færibandi
Finndu þrjár algengustu vefslóðirnar í logs/access.log. Vefslóðin er sjöundi dálkurinn í skránni.
Lausn
Til þess að sía út sjöunda dálkinn og telja hann getum við keyrt skipunina
cut -d' ' -f7 logs/access.log | sort | uniq -c | sort -nr | head -n 3
Vissir þú?
Pípur komu inn í Unix árið 1973. Hugmyndin var svo góð að hún breytti því hvernig fólk hannaði skipanalínuforrit: forrit þurftu ekki lengur að gera allt sjálf, heldur bara tala skýrt við næsta forrit í röðinni.
Smá samantekt
Eftir þennan hluta ættirðu að geta:
- útskýrt muninn á
stdin,stdoutogstderr, - notað
>,>>,<,2>og2>&1, - tengt skipanir saman með
|, - skilið af hverju mörg forrit lesa úr skrá eða úr staðalinntaki,
- notað
sort,uniq,cut,wc,tee,tr,sed,awkogxargsí einföldum dæmum, - áttað þig á af hverju litir hverfa stundum þegar úttak fer í pípu.