Mustand: sisu ei ole veel tehniliselt ega keeleliselt täielikult kontrollitud ega toimetatud.

Peatüki vaade

Linux/Unix/macOS käsurea kiirõpik

Praegu loed peatükki Sisend, väljund, torud ja suunamine, mis kuulub osasse Osa I: Esimesed sammud.

Sisend, väljund, torud ja suunamine

Loogika

Kõige tähtsam mõte:

  • käsk võib kirjutada tavalist väljundit
  • käsk võib anda ka eraldi veateateid
  • tavalise väljundi võib suunata faili
  • tavalise väljundi võib anda teisele käsule
  • käske saab ka lihtsalt järjest või tingimusega käivitada

Need ei ole sama asi. Faili suunamine, toru ja tingimuslik käsujada lahendavad eri probleeme.

Kiirülevaade

Eesmärk on panna käsud koostööd tegema: salvesta väljund, ühenda käsud või käivita järgmine samm tingimusega.

Märk või käskMilleksMida tavaliselt näed
>kirjuta stdout faili üleekraanil vähem, failis uus sisu
>>lisa stdout faili lõppufail kasvab, vana sisu jääb alles
|anna stdout järgmise käsu sisendiksnäed tavaliselt viimase käsu tulemust
;käivita käsud järjestjärgmine käsk jookseb igal juhul
&&jätka ainult edu korraljärgmine käsk jookseb ainult 0 koodi järel
||käivita varuplaan vea korraljärgmine käsk jookseb vea järel
2>suuna veateated failistderr läheb eraldi faili
teenäita ja salvesta korragaväljund on ekraanil ja failis

Lõpetuskood ei paista otse välja; vajadusel küsi seda käsuga echo $?.

Tüüpilised algaja vead

  • aetakse segi ; ja |
  • kirjutatakse fail kogemata > abil üle, kuigi taheti lisada >>
  • eeldatakse, et sudo echo ... > fail annab suunamisele samuti root-õiguse
  • imestatakse, miks edukas käsk vaikis, kuigi väljund läks tegelikult faili või torusse

1. Tavaline väljund, veaväljund ja lõpetuskood

Käsureal on hea eristada kolme mõistet:

  • stdout: tavaline väljund, mida käsk kirjutab
  • stderr: eraldi veaväljund vigade ja hoiatuste jaoks
  • lõpetuskood ehk exit code: märge selle kohta, kas käsk lõppes edukalt

Praktiline rusikareegel on:

  • 0 tähendab tavaliselt edu
  • mõni muu arv tähendab tavaliselt, et midagi läks valesti

Kui tahad näha viimase käsu lõpetuskoodi, saad kasutada:


ls sonad.txt
echo $?
ls puuduv_fail
echo $?

See mõte muutub oluliseks hiljem siis, kui jõuame märkideni && ja ||.

2. > kirjutab faili

Kui tahad käsu väljundi faili panna, kasuta märki >.


echo tere > sonad.txt
cat sonad.txt

Siin:

  • echo tere toodab teksti
  • > suunab selle faili
  • cat sonad.txt näitab tulemust

Oluline reegel: > kirjutab vana sisu üle.

3. >> lisab faili lõppu

Kui tahad olemasolevale failile juurde lisada, kasuta märki >>.


echo esimene > read.txt
echo teine >> read.txt
cat read.txt

Tulemus on:


esimene
teine

Peamine vahe on lihtne: > kirjutab üle, >> lisab lõppu.

4. Toru |

Toru ei kirjuta väljundit faili. Ta saadab ühe käsu väljundi järgmise käsu sisendiks.

Näide:


printf 'üks\nkaks\nkolm\n' | wc -l

Siin:

  • printf toodab kolm rida
  • toru | saadab need edasi
  • wc -l loeb kokku, mitu rida tuli

See on teistsugune loogika kui > abil faili kirjutamine.

5. Järjestikused käsud: ;

Märk ; tähendab lihtsalt: käivita järgmine käsk pärast eelmist.


pwd ; ls ; date

Siin käivitatakse kolm käsku järjest. ; ei anna andmeid ühest käsust teise edasi. Vahe on lihtne: ; käivitab käsud järjest, | ühendab käsud voona.

6. && ja ||

Need kaks märki lisavad käsujadale tingimuse. Nad ei vaata faili sisu ega toru kaudu tulevaid ridu, vaid eelmise käsu lõpetuskoodi.

&&


mkdir proov && cd proov

See tähendab: tee teine käsk ainult siis, kui esimene õnnestus.

||


grep 'midagi' puuduv.txt || echo 'otsing ebaõnnestus'

See tähendab: tee teine käsk siis, kui esimene ebaõnnestus.

Võrdlus


false ; echo 'see käivitus ikkagi'
false && echo 'seda ei näe'
false || echo 'varukäsk läks tööle'

Siin juhtub:

  • ; järel läheb järgmine käsk alati käima
  • && järel järgmine käsk ei käivitu, sest esimene ebaõnnestus
  • || järel järgmine käsk käivitub just sellepärast, et esimene ebaõnnestus

7. Vead ja 2>

Tavaline väljund ja veateated ei ole käsureal päris sama asi.

  • tavaline väljund läheb tavaliselt stdout kaudu
  • vead lähevad tavaliselt stderr kaudu

Kui tahad vead eraldi faili panna, kasuta:


ls puuduv_fail 2> vead.txt
cat vead.txt

Siin:

  • 2> tähendab veaväljundi suunamist
  • tavaline väljund läheks endiselt ekraanile

Kui tahad veateate lihtsalt ära peita, siis võid kirjutada:


ls puuduv_fail 2> /dev/null

/dev/null on erifail, kuhu saadetud väljund kaob ära. Seda võib mõelda kui musta auku väljundile. Aprillinaljana öeldakse vahel, et /dev/null sai täis, aga päriselt tähendab see lihtsalt kohta, kuhu saab midagi teadlikult “mitte kuhugi” saata.

8. tee

tee on kasulik siis, kui tahad väljundit korraga ekraanil näha ja faili salvestada.

Näide:


printf 'Tallinn\nTartu\nNarva\n' | tee linnad.txt
cat linnad.txt

Kui tahad faili lõppu lisada, kasuta:


printf 'Pärnu\n' | tee -a linnad.txt

9. 2>&1 ja muud keerulisemad kujud

Kui tahad ühendada veaväljundi tavalise väljundiga, kohtad kuju:


find . -name '*.md' > tulemused.txt 2>&1

See tähendab, et nii tavaline väljund kui ka vead lähevad samasse faili.

See ei ole esimene kuju, mida pähe õppida, aga hea on teada, et selline võimalus on olemas.

10. Miks sudo echo ... > fail ei tööta nii, nagu algaja ootab

Paljud proovivad kuju:


sudo echo 'naide=1' > /etc/naide.conf

Aga siin teeb ümbersuunamise > sinu praegune shell, mitte sudo.

Sellepärast kasutatakse sageli hoopis sellist kuju:


echo 'naide=1' | sudo tee /etc/naide.conf

Peamine loogika on:

  • sudo echo ... > fail ei anna root-õigust shelli suunamisele
  • sudo tee fail avab faili protsessis, millel on vajalikud õigused

11. Kui väljund ei ilmu kohe

Mõni programm ei kirjuta iga rida kohe ekraanile või torusse edasi, vaid kogub väljundi vahepeal puhvrisse.

See tähendab:

  • terminalis töötav programm võib näidata ridu kohe
  • sama programm toru või faili kaudu võib väljundi edasi anda hiljem

Pythoni puhul kohtab seda sageli. Selleks on olemas näiteks:

  • python3 -u programm.py
  • print(..., flush=True)

See on juba natuke järgmise taseme teema, aga hea on teada, miks mõni toru “vaikib” kauem kui ootasid.

Minitest

  1. Loo fail käsuga echo tere > fail.txt.
  2. Lisa teine rida käsuga echo maailm >> fail.txt.
  3. Näita faili sisu käsuga cat.
  4. Ühenda kaks käsku toruga, näiteks printf ... | wc -l.
  5. Võrdle käske pwd ; ls ja pwd | ls.
  6. Proovi, kuidas false && echo ok erineb käsust false || echo ok.

Peatüki täisspikker

Algaja

Eesmärk

Ühenda käske nii, et ühe väljund saab järgmise sisendiks, või saada väljund faili; vea- ja tavaväljundit tasub mõelda eraldi.

Põhikäsud

  • echoprindi tekst
  • printfvorminda tekst
  • catnäita faili
  • teeekraan ja fail
  • wcloe kokku

Olulisemad lipud, märgid ja kiirnupud

  • >stdout faili
  • >>lisa stdout faili lõppu juurde
  • |anna edasi järgmisele
  • ;käivita lihtsalt järjest
  • &&tee edasi edu korral
  • ||tee edasi vea korral
  • 2>stderr eraldi faili
  • 2>&1stderr samasse kohta
  • /dev/nullmust auk väljundile

Tüüpilised kujud

  • käsk > valjund.txtstdout faili
  • käsk >> logi.txtlisa stdout faili lõppu juurde
  • käsk 2> vead.txtstderr eraldi
  • käsk > valjund.txt 2> vead.txteralda mõlemad
  • käsk 2> /dev/nullpeida veateated
  • cat fail.txt | wc -ltoru loendusse
  • käsk ; järgminejärgmine alati
  • käsk && järgminejärgmine ainult edul
  • käsk || varuplaanvaruplaan vea korral
  • käsk > koik.txt 2>&1stdout ja stderr koos