Udev on Linuxin alijärjestelmä, joka toimittaa tietokoneelle laitetapahtumia. Selkokielellä se tarkoittaa, että se on koodi, joka havaitsee, kun tietokoneeseen on kytketty laitteita, kuten verkkokortti, ulkoiset kiintolevyt (mukaan lukien USB-muistitikut), hiiret, näppäimistöt, joystickit ja gamepadit, DVD-ROM-asemat ja niin edelleen. Tämä tekee siitä potentiaalisesti hyödyllisen apuohjelman, ja se on tarpeeksi hyvin paljastettu, jotta tavallinen käyttäjä voi käsin skriptata sen tekemään asioita, kuten suorittamaan tiettyjä tehtäviä, kun tietty kiintolevy on kytketty tietokoneeseen.
Tässä artikkelissa opetetaan luomaan udev-skripti, joka käynnistyy jostain udev-tapahtumasta, kuten tietyn muistitikun kytkemisestä. Kun ymmärrät udevin kanssa työskentelyprosessin, voit käyttää sitä kaikenlaisten asioiden tekemiseen, kuten tietyn ajurin lataamiseen, kun pelilaite liitetään, tai automaattisen varmuuskopioinnin suorittamiseen, kun liität varmuuskopioaseman.
Perusskripti
Paras tapa työskennellä udevin kanssa on työskennellä pienissä palasissa. Älä kirjoita koko skriptiä etukäteen, vaan aloita jollakin, joka yksinkertaisesti vahvistaa, että udev laukaisee jonkin mukautetun tapahtuman.
Skriptin tavoitteesta riippuen et voi taata, että näet koskaan skriptin tulokset omin silmin, joten varmista, että skriptisi kirjaa lokiin, että sen laukaisu onnistui. Tavallinen paikka lokitiedostoille on /var-hakemistossa, mutta se on useimmiten pääkäyttäjän aluetta. Käytä testaamiseen /tmp:tä, johon normaalit käyttäjät pääsevät käsiksi ja joka yleensä tyhjennetään uudelleenkäynnistyksen yhteydessä.
Avaa suosikkitekstieditori ja kirjoita tämä yksinkertainen skripti:
#!/usr/bin/bash
/usr/bin/date >> /tmp/udev.log
Sijoita tämä tiedostoon /usr/local/bin tai johonkin vastaavaan paikkaan oletusarvoisessa suorituspolussa. Kutsu sitä trigger.sh:ksi ja tee siitä tietenkin suoritettava chmod +x:llä.
$ sudo mv trigger.sh /usr/local/bin
$ sudo chmod +x /usr/local/bin/trigger.sh
Tällä skriptillä ei ole mitään tekemistä udevin kanssa. Kun se suoritetaan, skripti sijoittaa aikaleiman tiedostoon /tmp/udev.log. Testaa skripti itse:
$ /usr/local/bin/trigger.sh
$ cat /tmp/udev.log
Tue Oct 31 01:05:28 NZDT 2035
Seuraava vaihe on saada udev laukaisemaan skriptin.
Laitteen yksilöinti
Jotta skriptisi voidaan laukaista laitetapahtumasta, udevin on tiedettävä, millä edellytyksillä sen pitäisi kutsua skriptiä. Todellisessa elämässä voit tunnistaa muistitikun sen värin, valmistajan ja sen perusteella, että olet juuri liittänyt sen tietokoneeseen. Tietokoneesi tarvitsee kuitenkin erilaiset kriteerit.
Udev tunnistaa laitteet sarjanumeroiden, valmistajien ja jopa myyjän tunnistenumeroiden ja tuotetunnistenumeroiden perusteella. Koska tämä on udev-skriptisi elinkaaren alkuvaiheessa, ole mahdollisimman laaja, epäspesifinen ja kaiken kattava. Toisin sanoen, haluat ensin saada kiinni lähes minkä tahansa kelvollisen udev-tapahtuman käynnistämään skriptisi.
Komennolla udevadm monitor voit napata udevin reaaliajassa ja nähdä, mitä se näkee, kun kytket eri laitteita. Ryhdy pääkäyttäjäksi ja kokeile sitä.
$ su
# udevadm monitor
Monitor-toiminto tulostaa vastaanotetut tapahtumat seuraaville:
- UDEV: tapahtuma, jonka udev lähettää säännön käsittelyn jälkeen
- KERNEL: ytimen uevent
Kun udevadm monitor on käynnissä, liitä muistitikku ja katso, kuinka kaikenlaista informaatiota pursuaa näytöllesi. Huomaa, että tapahtuman tyyppi on ADD-tapahtuma. Se on hyvä tapa tunnistaa, minkä tyyppisen tapahtuman haluat.
Komento udevadm monitor antaa paljon hyvää tietoa, mutta voit nähdä sen kauniimmin muotoiltuna komennolla udevadm info, olettaen, että tiedät, missä muistitikkuasema tällä hetkellä sijaitsee /dev-puussa. Jos näin ei ole, irrota ja liitä peukaloasemasi takaisin ja anna sitten välittömästi tämä komento:
$ su -c 'dmesg | tail | fgrep -i sd*'
Jos tuo komento palauttaisi esimerkiksi sdb: sdb1, tiedät, että ydin on antanut peukaloasemallesi sdb-merkinnän.
Vaihtoehtoisesti voit käyttää komentoa lsblk nähdäksesi kaikki järjestelmääsi liitetyt asemat, mukaan lukien niiden koot ja osiot.
Nyt kun olet selvittänyt, missä asemasi sijaitsee tiedostojärjestelmässäsi, voit tarkastella udevin tietoja kyseisestä laitteesta tällä komennolla:
# udevadm info -a -n /dev/sdb | less
Tämä palauttaa paljon tietoa. Keskity nyt ensimmäiseen tietolohkoon.
Tehtäväsi on poimia udevin raportista laitteesta ne osat, jotka ovat kaikkein ainutlaatuisimpia kyseiselle laitteelle, ja sitten käskeä udevia käynnistämään skriptisi, kun näitä ainutlaatuisia ominaisuuksia havaitaan.
Udevadm-infoprosessi raportoi laitteesta (määritetty laitepolun avulla) ja ”kävelee” sen jälkeen ylöspäin vanhempien laitteiden ketjussa. Jokaisesta löydetystä laitteesta se tulostaa kaikki mahdolliset attribuutit avain-arvomuodossa. Voit laatia säännön, joka vastaa laitteen attribuuttien ja yhden vanhemman laitteen attribuuttien mukaan.
looking at device '/devices/000:000/blah/blah//block/sdb':
KERNEL=="sdb"
SUBSYSTEM=="block"
DRIVER==""
ATTR{ro}=="0"
ATTR{size}=="125722368"
ATTR{stat}==" 2765 1537 5393"
ATTR{range}=="16"
ATTR{discard\_alignment}=="0"
ATTR{removable}=="1"
ATTR{blah}=="blah"
Udev-säännön on sisällettävä yksi attribuutti yhdestä vanhemmasta laitteesta.
Parent-attribuutit ovat asioita, jotka kuvaavat laitetta perustasoltaan, kuten se on jotain, joka on kytketty fyysiseen porttiin, tai se on jotain, jolla on koko, tai tämä on irrotettava laite.
Koska sdb:n KERNEL-merkintä voi muuttua riippuen siitä, kuinka monta muuta asemaa oli kytketty ennen kuin kytkit tuon peukalolevyaseman paikalleen, se ei ole optimaalinen vanhempiattribuutti udev-säännölle. Se toimii kuitenkin konseptin todisteena, joten voit käyttää sitä. Vielä parempi ehdokas on SUBSYSTEM-attribuutti, joka tunnistaa, että kyseessä on ”lohko”-järjestelmälaite (minkä vuoksi lsblk-komento listaa laitteen).
Avaa tiedosto nimeltä 80-local.rules tiedostoon /etc/udev/rules.d ja kirjoita tämä koodi:
SUBSYSTEM=="block", ACTION=="add", RUN+="/usr/local/bin/trigger.sh"
Tallenna tiedosto, irrota testimuistitikku ja käynnistä uudelleen.
Odota, käynnistä uudelleen Linux-koneella?
Teoreettisesti voit vain antaa komennon udevadm control –reload, jonka pitäisi ladata kaikki säännöt, mutta tässä vaiheessa peliä on parasta eliminoida kaikki muuttujat. Udev on tarpeeksi monimutkainen, etkä halua maata sängyssä koko yötä miettimässä, toimiiko sääntö syntaksivirheen takia vai olisiko sinun vain pitänyt käynnistää uudelleen. Käynnistä siis uudelleen riippumatta siitä, mitä POSIX-ylpeytesi sanoo sinulle.
Kun järjestelmäsi on taas verkossa, vaihda tekstikonsoliin (Ctl+Alt+F3 tai vastaavalla) ja liitä muistitikku. Jos käytät uudempaa ydintä, konsolissa näkyy todennäköisesti paljon tulostetta, kun liität aseman. Jos näet virheilmoituksen, kuten Could not execute /usr/local/bin/trigger.sh, olet todennäköisesti unohtanut tehdä skriptistä suoritettavan. Muuten toivottavasti näet vain sen, että laite kytkettiin, se sai jonkinlaisen ytimen laitemäärityksen ja niin edelleen.
Nyt totuuden hetki:
$ cat /tmp/udev.log
Tue Oct 31 01:35:28 NZDT 2035
Jos näet hyvin tuoreen päivämäärän ja kellonajan, joka palautetaan tiedostosta /tmp/udev.log, udev on onnistuneesti laukaissut skriptisi.
Säännön tarkentaminen käyttökelpoiseksi
Ongelma tässä säännössä on se, että se on hyvin yleinen. Hiiren, muistitikun tai jonkun muun muistitikun kytkeminen pistorasiaan laukaisee skriptisi umpimähkään. Nyt on aika alkaa keskittyä tarkalleen siihen, minkä muistitikun haluat laukaista komentosarjasi.
Yksi tapa tehdä tämä on valmistajan tunnisteen ja tuotetunnisteen avulla. Näiden numeroiden saamiseksi voit käyttää lsusb-komentoa.
$ lsusb
Bus 001 Device 002: ID 8087:0024 Slacker Corp. Hub
Bus 002 Device 002: ID 8087:0024 Slacker Corp. Hub
Bus 003 Device 005: ID 03f0:3307 TyCoon Corp.
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 hub
Bus 001 Device 003: ID 13d3:5165 SBo Networks
Tässä esimerkissä 03f0:3307 ennen TyCoon Corp. tarkoittaa idVendor- ja idProduct-attribuutteja. Näet nämä numerot myös udevadm info -a -n /dev/sdb | grep vendor -komennon tulosteessa, mutta minusta lsusb-komennon tuloste on hieman miellyttävämpi silmille.
Voit nyt sisällyttää nämä attribuutit sääntöösi.
SUBSYSTEM=="block", ATTRS{idVendor}=="03f0", ACTION=="add", RUN+="/usr/local/bin/thumb.sh"
Testaa tätä (kyllä, sinun pitäisi silti käynnistää uudelleen, vain varmistaaksesi, että saat udev:ltä tuoreita reaktioita), ja sen pitäisi toimia samalla tavalla kuin ennenkin, mutta nyt skriptin ei tarvitse käynnistyä, jos kytket esimerkiksi eri yrityksen valmistaman muistitikun (siis eri idVendorilla) tai hiiren tai tulostimen.
Jatka uusien attribuuttien lisäämistä keskittyäksesi tarkemmin tuohon yhteen ainutkertaiseen muistitikkuun, jonka haluat skriptin käynnistyvän. Käyttämällä udevadm info -a -n /dev/sdb saat selville esimerkiksi myyjän nimen, joskus sarjanumeron tai tuotenimen ja niin edelleen.
Oman mielenterveytesi vuoksi muista lisätä vain yksi uusi attribuutti kerrallaan. Useimmat virheet, joita olen tehnyt (ja nähnyt muidenkin ihmisten verkossa tekevän), ovat heittäneet kasan attribuutteja udev-sääntöönsä ja ihmetelleet, miksi asia ei enää toimi. Attribuuttien testaaminen yksi kerrallaan on turvallisin tapa varmistaa, että udev pystyy tunnistamaan laitteesi onnistuneesti.
Turvallisuus
Tämä tuo esiin turvallisuusongelmat, jotka liittyvät udev-sääntöjen kirjoittamiseen niin, että ne tekevät automaattisesti jotain, kun asema kytketään. Minun koneillani ei ole edes automaattinen kiinnitys päällä, ja silti tässä artikkelissa ehdotetaan skriptejä ja sääntöjä, jotka suorittavat komentoja vain siksi, että jokin on kytketty.
Kaksi asiaa, jotka on syytä pitää mielessä:
- Kohdista udev-sääntöjäsi, kun olet saanut ne toimimaan niin, että ne laukaisevat skriptejä vain silloin, kun todella haluat. Sellaisen skriptin suorittaminen, joka kopioi sokeasti dataa koneellesi tai koneeltasi, on huono idea siinä tapauksessa, että kuka tahansa, jolla sattuu olemaan mukanaan samanmerkkinen muistitikku, liittää sen laatikkoosi.
- Älä kirjoita udev-sääntöjäsi ja skriptejäsi ja unohda ne. Tiedän, missä tietokoneissa udev-sääntöni ovat, ja nämä laatikot ovat useimmiten henkilökohtaisia tietokoneitani, eivät niitä, joita otan mukaan konferensseihin tai jotka ovat toimistossani töissä. Mitä ”sosiaalisempi” tietokone on, sitä epätodennäköisemmin se saa udev-säännön, joka saattaa johtaa siihen, että tietoni päätyvät jonkun toisen laitteeseen tai jonkun toisen tiedot tai haittaohjelmat minun laitteeseeni.
Toisin sanoen, kuten niin monen GNU-järjestelmän tarjoaman vallan kohdalla, sinun tehtäväsi on olla tietoinen siitä, miten käytät tätä valtaa. Jos käytät sitä väärin tai et kohtele sitä kunnioittavasti, se voi hyvinkin mennä kauheasti pieleen.
Udev todellisessa maailmassa
Nyt kun voit varmistaa, että udev käynnistää skriptisi, voit kääntää huomiosi skriptin toimintaan. Juuri nyt se on hyödytön, sillä se ei tee muuta kuin kirjaa, että se on suoritettu.
Käytän udevia käynnistämään automaattisia varmuuskopioita muistitikuistani. Ajatuksena on, että aktiivisten asiakirjojeni master-kopiot ovat muistitikulla (koska se kulkee mukanani kaikkialle, missä käyn, ja sitä voidaan työstää milloin tahansa), ja nämä master-dokumentit varmuuskopioidaan tietokoneelleni aina, kun liitän muistitikun kyseiseen koneeseen. Toisin sanoen tietokoneeni on varmuuskopioasema ja tuotantotietoni ovat siirrettävissä. Lähdekoodi on saatavilla, joten katso rohkeasti attachupin koodista lisää esimerkkejä udev-testien rajoittamisesta.
Koska käytän udevia eniten tähän, käytän sitä tässä esimerkkinä, mutta udev voi tarttua moneen muuhunkin, kuten pelipadeihin (tämä on hyödyllistä järjestelmissä, joita ei ole asetettu lataamaan xboxdrv-moduulia, kun pelipadi liitetään) ja kameroihin ja mikrofoneihin (hyödyllinen tulojen asettamiseen, kun tietty mikrofoni liitetään), joten ymmärräthän, että udevia voi käyttää muuhunkin tarkoitukseen kuin tähän yhteen esimerkkiin.
Yksinkertainen versio varmuuskopiointijärjestelmästäni on kahden komennon prosessi:
SUBSYSTEM=="block", ATTRS{idVendor}=="03f0", ACTION=="add", SYMLINK+="safety%n"
SUBSYSTEM=="block", ATTRS{idVendor}=="03f0", ACTION=="add", RUN+="/usr/local/bin/trigger.sh"
Ensimmäinen rivi havaitsee peukalolevyni jo käsitellyillä attribuuteilla ja antaa sitten peukalolevylle symlinkin laitepuussa. Sen antama symlinkki on safety%n. %n on udev-makro, joka vastaa sitä numeroa, jonka ydin antaa laitteelle, kuten sdb1, sdb2, sdb3 ja niin edelleen. Joten %n olisi 1 tai 2 tai 3.
Tämä luo symlinkin dev-puuhun, joten se ei häiritse normaalia laitteen kytkemistä. Tämä tarkoittaa, että jos käytät työpöytäympäristöä, joka tykkää liittää laitteet automaattisesti, et aiheuta sille ongelmia.
Kakkosrivi ajaa skriptin.
Minun varmuuskopiointiskriptini näyttää tältä:
#!/usr/bin/bash
mount /dev/safety1 /mnt/hd
sleep 2
rsync -az /mnt/hd/ /home/seth/backups/ && umount /dev/safety1
Skripti käyttää symlinkkiä, jolloin udev ei nimeä asemaa joksikin odottamattomaksi (esimerkiksi jos minulla on jo tietokoneeseeni kytketty DISK-niminen muistitikku ja kytken siihen toisen muistitikkuni, jonka nimi on niin ikään DISK, jälkimmäisen muistitikun nimeksi tulee DISK_, mikä tekisi tyhjäksi skriptini). Se asentaa safety1:n (aseman ensimmäisen osion) haluamaani kiinnityspisteeseen /mnt/hd.
Kun se on kiinnitetty turvallisesti, se käyttää rsync:tä aseman varmuuskopioimiseen varmuuskopiointikansiooni (varsinainen skriptini käyttää rdiff-backupia, ja sinun skriptisi voi käyttää mitä tahansa haluamaasi automaattista varmuuskopiointiratkaisua).
Udev on sinun dev:si
Udev on erittäin joustava järjestelmä, ja sen avulla voit määritellä sääntöjä ja toimintoja tavoilla, joita harvat muut järjestelmät uskaltavat käyttäjille tarjota. Opettele se ja käytä sitä ja nauti POSIXin voimasta.
Tämä artikkeli perustuu Slackermedian käsikirjan sisältöön, joka on lisensoitu GNU Free Documentation License 1.3 -lisenssillä.