(toiminnot)

hwechtla-tl: Unix-komentotulkki

Kierre.png

Mikä on WikiWiki?
nettipäiväkirja
koko wiki (etsi)
viime muutokset


Unix-komentotulkki ja sen kautta käynnistettävät ohjelmat muodostavat yhdessä Unix-ympäristön, joka on verraton työkalukokoelma tiedonkäsittely-, automaatio- ja viestintätarpeisiin. Unix-ympäristö on kehittynyt ja hioutunut aina 70-luvulta asti. Nykyisellään se on todellinen Sveitsin armeijan linkkuveitsi, jolla voi tehdä mitä tahansa palvelimien etähallinnoinnista videoiden muokkaukseen -- unohtamatta toki alkuperäisiäkään vahvuuksia, kuten tiedostojen hallintaa ja tiedon etsintää tekstimuotoisista aineistoista. Tämä työkalujen kokoelma löytyy valmiina erilaisista Unixin kaltaisista järjestelmistä, kuten Linuxista, BSD-järjestelmistä ja MacOS:sta, mutta se on saatavilla käytännössä kaikkiin yleiskäyttöisiin käyttöjärjestelmiin.

Kaksi lyhyttä tarinaa Unix-komentotulkista

Olimme nörttituttujeni kanssa kahvilla, ja puhe kääntyi siihen, mikä on kunkin kaikkein tärkein taito tietokoneiden kanssa. Kävimme läpi erilaisia taitoja tiedostomuodoista (esimerkiksi JSON) siihen, miten kirjoitetaan rekursioita ohjelmointikielissä.

Kun joku nosti esiin Unix-ympäristön käyttötaidot, kukaan ei enää pystynyt keksimään mitään parempaa. Ainoat vaihtoehdot, joilla oli edes mahdollisuuksia kilpailla, olivat tietokantojen kanssa käytetty SQL-kyselykieli ja ohjelmointitaito ylipäänsä. Unix-ympäristö päihitti nekin käytännöllisyydessä ja SQL:n vielä laajassa sovellusalassa. Oli kuin olisimme löytäneet salaseuran, joka meitä yhdistää.

2000-luvun alussa luennoin Helsingin Yliopiston kieliteknologian laitoksella tekstityökalut-nimistä kurssia. Kurssin sisältö oli käytännössä tekstiaineistojen käsittelyä Unix-komentotulkin avulla. Vaikka kurssista kerättiin palautetta normaaliin tapaan, tärkeimmän palautteeni kurssista sain vasta yli vuosikymmenen kuluttua.

Aloin tavata eri yhteyksissä ihmisiä, joiden ura oli käytännössä määrittynyt tämän yhden kurssin kautta. He muistivat minut ja sanoivat kiitoksensa, kun polkumme ristesivät. He olivat päätyneet IT-alalle, kuka ohjelmoijaksi, kuka esihenkilöksi, kuka tuoteomistajaksi. Heitä yhdisti se, että he kokivat tämän yhden työkalun avanneen heille, mitä tietokoneet todella tekevät ja mistä tietokoneiden viestintäverkoissa on kyse. Lisäksi tietysti Unix-komentotulkki antoi heille keinot teettää tietokoneellaan asioita, joita he eivät olisi muuten saaneet selitetyksi koneelleen.

Minusta alkoi tuntua, kuin olisin unohduksiin vaipuneen muinaisen viisauden evankelista, mystisten salaisuuksien guru. Mutta tietokoneiden toiminta ei ole uskonnollista, eikä yksikään Unix-komento ole salattu loitsu, vaan täysin selkeä toimintaohje siitä, mitä haluan koneen tekevän.

Mitä Unix-komentotulkilla voi tehdä?

Lyhyt vastaus on: mitä tahansa. Mutta koska esimerkki kertoo enemmän kuin tuhat luonnehdintaa, aloitan niillä. Seuraavissa esimerkeissä $-merkin (dollarimerkin) jälkeen tuleva teksti on kirjoittamani komento, loput on tietokoneen vastausta pyyntöihini ja kysymyksiini.

Kuinka monta perhetuttua on yhteystietolistassani?

:~$ grep -w perhetuttu proj/yhteystiedot/osoitteet.txt | wc -l
47

Mikä on tuttavieni yleisin etunimi ja kuinka monta heitä (nimenhaltijoita) on?

:~$ cut -d' ' -f1 proj/yhteystiedot/osoitteet.txt | sort | uniq -c | sort -rn | head -1
     11 Hanna

Milloin suomenkielisen wikipedian Suomi-aiheista artikkelia on viimeksi päivitetty?

:~$ curl -s https://fi.wikipedia.org/wiki/Suomi | grep -o 'viimeksi muutettu [^<]*'
viimeksi muutettu 27. joulukuuta 2022 kello 09.54.

Millä kameralla otinkaan erään kuvani?

:~$ exif -m binaries/2007-05/varpaat1.jpeg | grep Manufacturer | cut -f2
OLYMPUS OPTICAL CO.,LTD

Mitä lämpötilaa Norjan ilmatieteenlaitos ennustaa kotini lähellä seuraaviksi 5 tunniksi? Komento on rivitetty useammalle riville selkeyden vuoksi.

:~$ curl -s 'https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=60.2656693&lon=25.0047308' |
    jq '.properties.timeseries[] | .time,.data.instant.details.air_temperature' |
    head -10

"2023-01-01T17:00:00Z"
-2.2
"2023-01-01T18:00:00Z"
-2.2
"2023-01-01T19:00:00Z"
-2.1
"2023-01-01T20:00:00Z"
-2.1
"2023-01-01T21:00:00Z"
-1.9

Tulosten ei välttämättä tarvitse tulla näytölle -- ne voi lähettää yhtä hyvin tulostimelle, sähköpostilla johonkin osoitteeseen, äänikortille soitettavaksi, tallettaa tiedostoon tai lähes mitä vain. Seuraava komento taivuttaa glass.ogg-tiedostoon tallennetun äänen siten että ääni kohoaa alussa, ja tallentaa tuloksen osuuskuntamme aulis-palvelimelle. Tämäkin komento on rivitetty selkeyden vuoksi.

:~$ sox /usr/share/sounds/mate/default/alerts/glass.ogg -t ogg - bend .0,140,.5 | 
    ssh aulis "cat > tmp/glass-bent.ogg"

Komentotulkki ei sano vastaukseksi mitään, koska komento yksinkertaisesti onnistui kaikin tavoin. Mutta palvelimella on uusi tiedosto, kooltaan kolmisentoista kilotavua, ja voin pyytää komentotulkkia näyttämään sen:

:~$ ssh aulis ls -l tmp/glass-bent.ogg
-rw-r--r-- 1 atehwa atehwa 12948 Jan  1 20:15 tmp/glass-bent.ogg

Miten Unix-ympäristö toimii?

Unix-ympäristössä yhdistyy kaksi ideaa, jotka yhdessä rakentavat valtavat mahdollisuudet käyttäjälle:

  1. Jokaiseen tarpeeseen -- kuten tiedostojen sisällön pakkaaminen tai tekstin syntetisointi puheeksi -- on oma ohjelmansa, usein useampikin vaihtoehtoinen. Jotkin ovat yksinkertaisia, jotkin monimutkaisia, mutta kaikille yhteistä on, että ne tekevät täsmälleen sen mitä niiltä pyytää, eivätkä yritä arvailla, mitä käyttäjä haluaa.
  2. Nämä ohjelmat noudattavat toiminnassaan yhteisiä käytäntöjä, joiden vuoksi niitä on mahdollista ja helppoa yhdistellä monimutkaisiksi kokonaisuuksiksi vähän kuin lego-palasia. Komentotulkki tarjoaa "liimakielen", jolla on suhteellisen helppo kertoa, miten komennot yhdistetään. Ennen kaikkea yhden ohjelman tulokset voi antaa helposti toiselle aineistoksi (eli syötteeksi).

Tarkastellaanpa kumpaakin näistä piirteistä erikseen.

Valtava ohjelmavalikoima

Ensimmäinen periaate, vaihtoehtoisten ohjelmien paljous, on tuttu muistakin ympäristöistä. Esimerkiksi kännyköiden sovellusvalikoimassa on sama idea: eri tarpeisiin toteutetaan omat ohjelmansa (sovelluksensa), ja kätevin sovellus saa käyttäjät puolelleen. Mutta kännyköiden sovelluksista puuttuu Unix-ympäristön ohjelmien yhdisteltävyys. Ne ovat kaikki omissa kuplissaan, ja niiden yhteisiä toimintoja on vain muutamia ja nekin ennalta määrättyjä: ilmoitusten tuottaminen, toisen sovelluksen avaaminen, tiedon (esimerkiksi kuvan) jakaminen sovelluksesta toiseen.

:~$ grep reproduce, LICENSE
      copyright license to reproduce, prepare Derivative Works of,
:~$ sed -ne /reproduce,/p LICENSE
      copyright license to reproduce, prepare Derivative Works of,
:~$ awk /reproduce,/ LICENSE
      copyright license to reproduce, prepare Derivative Works of,

# grep on tyypillisin tekstin etsimiseen käytetty ohjelma, mutta
# vaihtoehdoista ei ole pulaa.

Yhdisteltävyys ei ole ainoa ero Unix-ympäristön ja kännykkäsovellusten välillä. Unix-ympäristön ohjelmat eivät yleensä ole vuorovaikutteisia: ne käynnistetään kerran, ne tekevät tehtävänsä, ja sitten ne sulkeutuvat. Ne voivat periaatteessa kysellä käyttäjältä lisäohjeita toimiessaan, mutta tämänkin voi yleensä estää jollain ohjelman asetuksella. Ne ovat tyypillisesti luotettavampia kuin kännykkäsovellukset: ne tekevät täsmälleen sen mitä pyydetään eivätkä mitään muuta. Unix-ympäristön ohjelmat eivät niin ikään yleensä keskity tietyn palvelun tai edes tiedostomuodon ympärille. Ei ole yhtä Unix-ohjelmaa, jolla "käsitellään" HTML-tiedostoja. Unix-ympäristön ohjelmat ovat tyypillisesti sen sijaan erikoistuneet tiettyyn toimintoon, kuten etäyhteyden muodostamiseen, kuvan koon muuttamiseen tai tietyn tekstin etsimiseen tiedoston sisällöstä.

:~$ w3m -dump /usr/share/doc/mutt/html/gettingstarted.html | head -10
                          Chapter 2. Getting Started
Prev                                                                      Next



Chapter 2. Getting Started

Table of Contents

1. Core Concepts
:~$ tr -dc '<' < /usr/share/doc/mutt/html/gettingstarted.html | wc -c
3861

# Haluanko HTML-tiedostosta tekstiä näytölle vai tietää, kuinka monta
# tagia se sisältää?  Tiedoston käsittelyyn valittu ohjelma riippuu
# siitä, mitä haluan tehdä.

Ohjelmien tai komentojen suuri määrä on tärkeimpiä syitä, miksi Unix-komentotulkilla on kohtalaisen korkea oppimiskynnys. Kaikkia komentoja ei tietenkään tarvitse opetella heti, eikä se olisi edes mahdollista, mutta mitä useampia komentoja osaa, sitä useampia asioita komentotulkilla saa aikaan. Niinpä käytön opettelu aloitetaan pienestä, ja ajan myötä käyttäjä huomaa ilmaisevansa itseään yhä uusissa tapauksissa mieluiten komennoilla.

:~$ find /usr/share/doc/w3m/ -name '*.html' | xargs wc -w
  4553 /usr/share/doc/w3m/MANUAL.html
  2107 /usr/share/doc/w3m/FAQ.html
   742 /usr/share/doc/w3m/ja/MANUAL.html
   386 /usr/share/doc/w3m/ja/FAQ.html
   269 /usr/share/doc/w3m/ja/STORY.html
  1642 /usr/share/doc/w3m/STORY.html
  4428 /usr/share/doc/w3m/de/MANUAL.html
  2154 /usr/share/doc/w3m/de/FAQ.html
 16281 yhteensä

# Jo pelkästään se, että lasken w3m-ohjelman käyttöohjeissa olevien
# sanojen määrän, vaatii 3 komennon yhteistoimintaa: find, xargs ja wc.

Tarjolla olevien ohjelmien keskinäinen kilpailu ja anarkia tekevät Unix-ympäristöstä epäyhtenäisen. Tietyt ohjelmat löytyvät tyypillisesti komentotulkista kuin komentotulkista, mutta toiset asennetaan sitä mukaa, kuin niitä halutaan käyttää. Ei ole yhtä oikeaa määritelmää siitä, millainen Unix-ympäristö on, ja käytännössä jokaiselle perusohjelmallekin on 2--3 vaihtoehtoista toteutusta. Anarkiaa rauhoittaa huomattavasti se, että Unix-ympäristön ohjelmat eivät vanhene koskaan eivätkä vanhat toiminnot lakkaa toimimasta. Muutos tapahtuu sitä kautta, että käyttäjät ottavat käyttöön uusia, vaihtoehtoisia ohjelmia tai ohjelmien toimintoja, joista eivät ole ennen tienneet.

:~$ mawk 'BEGIN { print "moi!" }'
moi!
:~$ gawk 'BEGIN { print "moi!" }'
moi!

# Kaksi täysin erillistä toteutusta AWK-ohjelmointikielelle, mawk ja
# gawk.  Toiminta näyttää kuitenkin kovasti samanlaiselta.

Toimintojen yhdistäminen

Unix-ympäristön periaate on, että hyvä ohjelma tekee yhden selkeän asian ja antaa siitä tulokset, mahdollisesti jatkokäsiteltäviksi. Tämä yhdisteltävyys (kompositionaalisuus) vähentää olennaisesti toimintoja, jotka tarvitsee toteuttaa yhteen ohjelmaan. Esimerkiksi RTF-tiedostoja käsittelevään ohjelmaan ei tarvitse toteuttaa toimintoa sanojen laskemiseksi; sen sijaan on tarjolla yksi ohjelma, "unrtf", joka muuttaa RTF-tiedoston sisällön tekstiksi, ja toinen, "wc", joka osaa laskea sanat tästä tekstistä.

:~$ curl -s https://www.vantaa.fi/sites/default/files/document/Yritysten%20ilmastokysely%202021.pdf |
    pdftotext - - | grep -A3 Lähteet

Lähteet
TEM / KPMG Oy (2016). Selvitys sidosryhmien käsityksistä suomalaisten yritysten yhteiskuntavastuusta. Työ- ja
elinkeinoministeriö.
https://tem.fi/documents/1410877/2869440/Selvitys+sidosryhmien+k%C3%A4sityksist%C3%A4+suomalaisten+yritys

# Jokaiseen vaiheeseen oma ohjelmansa: curl lataa verkosta, pdftotext
# muuntaa tekstiksi, grep etsii tietyn tekstin.

Jotta tällainen tiedon siirto ohjelmien välillä olisi mahdollista, ohjelmilla täytyy olla jokin yhteisymmärrys siitä, mitä ja minkä muotoista niiden välillä siirtyvä tieto on. Unix-ympäristö ottaa tähän äärimmäisen vähän kantaa: ohjelmien välillä kulkeva asia on "tiedosto" eli "tavuvirta", mikä tarkoittaa käytännössä jonkin pituista pötköä/listaa lukuja väliltä 0--255. Mitä nämä luvut tarkoittavat, on tulkinnallinen kysymys ja riippuu käytetystä komennosta. Mutta kun yhdeltä ohjelmalta siirtyy tietoa toiselle syötteeksi, se on siis lukuja väliltä 0--255, ja tämä muodostaa pienimmän yhteisen tekijän, jota kaikki käytettävissä olevat ohjelmat noudattavat.

:~$ curl -s https://www.vantaa.fi/sites/default/files/document/Yritysten%20ilmastokysely%202021.pdf |
    od -t u1 | head -1
0000000  37  80  68  70  45  49  46  55  13  10  37 181 181 181 181  13

# Jos haluan oikeasti nähdä, mitä lukuja edellisessä komennossa meni
# curl-komennolta pdftotext-komennolle, voin käyttää od-komentoa joka
# näyttää syötteekseen tulevan lukujonon.  Yllä olevan lukujonon 8
# ensimmäistä lukua ovat teksti "%PDF-1.7" ASCII-koodattuna.

Yleensä järkevien tulosten saamiseksi ohjelmien on oltava samassa käsityksessä siitä, miten niiden välillä kulkevat luvut tulkitaan. Jos esimerkiksi toinen ohjelma lähettää OGG-koodattua äänidataa mutta toinen luulee ottavansa vastaan tekstiä, tämä vastaan otettu "teksti" on käytännössä satunnaista mössöä. Toisaalta tietyt ohjelmat eivät ole riippuvaisia siitä, miten niille annettu tieto on tarkoitus tulkita: esimerkiksi pakkausohjelma "gzip" ottaa vastaan minkä tahansa tavuvirran ja yrittää tuottaa siitä toisen, yleensä vähemmän tilaa vievän tavuvirran, josta alkuperäinen data voidaan palauttaa.

:~$ gzip -c /usr/share/sounds/mate/default/alerts/sonar.ogg | wc -c
19098
:~$ cat /usr/share/sounds/mate/default/alerts/sonar.ogg | wc -c
20011

# gzip:lle voi antaa käytännössä syötteeksi mitä vain.
# sonar.ogg-tiedostosta se jopa sai vähennetyksi tilankulutusta noin
# kilotavun, vaikka äänidata ei yleensä juurikaan pakkaudu
# yleiskäyttöisillä pakkausohjelmilla.

Koska useimpien ohjelmien yhteistyö perustuu niiden välillä kulkevan tiedon yhteneväiselle tulkinnalle, Unix-ympäristön ohjelmilla on taipumus ymmärtää yleisessä tiedossa olevia ja hyvin kuvailtuja tiedoston tulkintaohjeita, tiedostomuotoja. Esimerkiksi JPEG-tiedostomuoto on määrittely siitä, miten digitaalinen kuva esitetään tavuvirtana. Jos yksi ohjelma osaa tuottaa JPEG-koodattua tietoa ja toinen osaa sen lukea, nämä kaksi ohjelmaa pystyvät tekemään yhteistyötä. Toinen voi vaikkapa luoda pointillistisen taideteoksen ja toinen voi lisätä siihen häikäisyefektin -- en tosin usko, että (vain) tähän tarkoitettuja ohjelmia on oikeasti viitsitty tehdä :)

:~$ dot -Tjpeg tmp/koe.dot | convert -resize 100x100 - pieni.jpeg

# dot tuottaa JPEG-kuvan kaaviomäärittelystä, convert pienentää dot:lta
# saamansa kuvan.  Tulos ohjataan pieni.jpeg-tiedostoon.

Erittäin monet Unix-ympäristön ohjelmat tulkitsevat vastaanottamansa ja tuottamansa tavuvirrat tekstitiedostoina. Tekstitiedosto on tulkinta, jossa tavuvirran jokainen luku tarkoittaa tiettyä merkkiä ja tietyt erikoisluvut asettelullisia ohjeita, kuten luku 10 rivinvaihtoa. Myös komentotulkki on tässä puolueellinen siten, että jos jokin ohjelma tuottaa tulosta tietokoneen käyttäjän näytölle, sen tuottamat tavut tulkitaan tekstiksi juuri tämän tulkintatavan mukaan ja näytetään siis käyttäjälle tekstinä.

:~$ dot -Tjpeg tmp/koe.dot | tail -c 80; echo
(V@Ey$4
?$!Pmy\V;su,(

# Jos yritän katsoa dot:n tuottamaa JPEG-kuvaa komentotulkissa, tulos ei
# ole kovin hieno, koska komentotulkki tulkitsee JPEG-datan (väärin)
# tekstitiedostoksi.

Monet tiedostomuodot ovat muuten tekstitiedostoja, mutta niissä on omia lisäsääntöjään. Esimerkiksi HTML-tiedostot ovat tekstitiedostoja, joihin on lisätty "<"- ja ">"-merkkien välissä olevia muotoiluohjeita, jotka kertovat, mikä teksti on otsikko, mikä yläviite, ja niin edelleen. Ohjelmien lähdekoodi taas on tekstitiedostoja, joiden sisältö noudattaa käytetyn ohjelmointikielen sääntöjä, syntaksia. Ja tietyt tekstitiedostojen käytännöt ovat niin yleisiä, ettei niille ole edes annettu nimeä: esimerkiksi yleensä, jos tiedostoon halutaan kirjoittaa lista jotain (kuten lämpötilamittauksia tai ihmisten yhteystietoja), kukin listan kohta on yleensä omalla rivillään eli listan kohdat on eroteltu rivinvaihdoin.

:~$ grep Kruununhaka proj/vaalikartat/data/ekv-2019_areas.csv
091_001A;091;area;Kruununhaka A                           ;Kronohagen A
091_002A;091;area;Kruununhaka B                           ;Kronohagen B

# CSV-tiedostomuoto on oikeastaan Unix-käytäntöjen mukaan muotoiltua
# taulukkodataa.  Tässä etsitään eduskuntavaalien 2019 äänestysalueet
# sisältävästä tiedostosta ne, joiden nimessä on "Kruununhaka".

Unix-komentotulkin käytön opettelu

Jos haluat tulla todelliseksi tietokoneen tehokäyttäjäksi ja oppia samalla ymmärtämään paremmin tiedostojen, tietokoneen ja viestintäverkkojen sisältöä, suosittelen lämpimästi Unix-komentotulkin kokeilemista. Materiaalia on runsaasti tarjolla netissä, mutta koska komentotulkin käyttökohteet ovat niin moninaiset, on tietysti oppimateriaalejakin kirjoitettu monesta eri näkökulmasta.

Aion myös tulevissa Skrolleissa paneutua tarkemmin Unix-komentotulkin erilaisiin käyttötapauksiin ja siihen, miten sillä tehdään tietynlaisia asioita. Paneudun jatko-osissa tärkeisiin tietokoneen käyttäjän tehtäviin, mutta otan mieluusti myös vastaan ehdotuksia kiinnostavista osa-alueista.



Pikalinkit:


kommentoi (viimeksi muutettu 16.01.2023 21:36)