Udev: differenze tra le versioni

17 968 byte aggiunti ,  24 ott 2015
completamento guida
mNessun oggetto della modifica
(completamento guida)
Riga 1: Riga 1:
{{Stub}}
{{File_System
{{File_System
|precedente=File_System
|precedente=File_System
Riga 6: Riga 4:
}}
}}


{{Versioni compatibili|Wheezy|Jessie}}
{{Versioni compatibili|Jessie}}


== Introduzione ==
== Introduzione ==
Riga 23: Riga 21:


== Strumenti ==
== Strumenti ==
(TODO)
Per interrogare <code>systemd-udevd</code>, è possibile ricorrere all'eseguibile <code>udevadm</code>, che per alcune operazioni richiede [[privilegi di amministrazione]]. Di seguito verranno presentate le funzionalità più comuni, finalizzate alla scrittura di regole personalizzate.
 
=== Raccolta informazioni ===
==== Monitoraggio degli eventi ====
Monitora tutti gli eventi di '''udev''', stampando anche le proprietà di ciascuno:
<pre>
$ udevadm monitor --udev
</pre>
(forma abbreviata: <code>udevadm monitor -u</code>)
 
Sono stampati sullo schermo tutti gli eventi generati. Per testarne l'efficacia si può provare, dopo aver lanciato il comando, a inserire una memoria USB. Ecco un esempio con una memoria USB di TDK, contenente una singola partizione FAT:
<pre>
UDEV  [3995.944943] add      /devices/pci0000:00/0000:00:1a.7/usb6/6-1 (usb)
UDEV  [3995.946941] add      /devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0 (usb)
UDEV  [3995.947663] add      /devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host9 (scsi)
UDEV  [3995.948500] add      /devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host9/scsi_host/host9 (scsi_host)
UDEV  [3996.972131] add      /devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host9/target9:0:0 (scsi)
UDEV  [3996.973503] add      /devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host9/target9:0:0/9:0:0:0 (scsi)
UDEV  [3996.974521] add      /devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host9/target9:0:0/9:0:0:0/scsi_disk/9:0:0:0 (scsi_disk)
UDEV  [3996.975626] add      /devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host9/target9:0:0/9:0:0:0/bsg/9:0:0:0 (bsg)
UDEV  [3996.976216] add      /devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host9/target9:0:0/9:0:0:0/scsi_device/9:0:0:0 (scsi_device)
UDEV  [3996.976824] add      /devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host9/target9:0:0/9:0:0:0/scsi_generic/sg2 (scsi_generic)
UDEV  [3999.038112] add      /devices/virtual/bdi/8:16 (bdi)
UDEV  [3999.206364] add      /devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host9/target9:0:0/9:0:0:0/block/sdb (block)
UDEV  [3999.345441] add      /devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host9/target9:0:0/9:0:0:0/block/sdb/sdb1 (block)
</pre>
Tutti questi eventi sono stati generati dal solo inserimento della memoria. L'ultimo riguarda la generazione del file di tipo dispositivo a blocchi <code>/dev/sdb1</code>, corrispondente alla partizione della memoria USB, mentre il penultimo la creazione del file a blocchi <code>/dev/sdb</code>, corrispondente all'intero dispositivo, inclusa la tabella delle partizioni. Si noti che gli eventi sono prodotti dal più generale, riguardante un generico dispositivo USB, al più particolare, riguardante la creazione di un file a blocchi che può essere montato per accedere alla partizione della memoria di massa.
 
Per ottenere maggiori informazioni su ciascun evento, si può utilizzare l'opzione <code>--property</code> (abbreviata: <code>-p</code>).Quindi per esempio:
<pre>
$ udevadm monitor -u -p
</pre>
Restituisce:
<pre>
...
UDEV  [4398.237894] add      /devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host10/target10:0:0/10:0:0:0/block/sdb (block)
ACTION=add
DEVLINKS=/dev/disk/by-id/usb-TDKMedia_Trans-It_Drive_07BA1203F92265C2-0:0 /dev/disk/by-label/Debian\x20Inst /dev/disk/by-path/pci-0000:00:1a.7-usb-0:1:1.0-scsi-0:0:0:0 /dev/d
isk/by-uuid/DEB0-0001
DEVNAME=/dev/sdb
DEVPATH=/devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host10/target10:0:0/10:0:0:0/block/sdb
DEVTYPE=disk
ID_BUS=usb
ID_FS_LABEL=Debian_Inst
ID_FS_LABEL_ENC=Debian\x20Inst
ID_FS_TYPE=vfat
ID_FS_USAGE=filesystem
ID_FS_UUID=DEB0-0001
ID_FS_UUID_ENC=DEB0-0001
ID_FS_VERSION=FAT32
ID_INSTANCE=0:0
ID_MODEL=Trans-It_Drive
ID_MODEL_ENC=Trans-It\x20Drive\x20\x20
ID_MODEL_ID=0619
ID_PATH=pci-0000:00:1a.7-usb-0:1:1.0-scsi-0:0:0:0
ID_PATH_TAG=pci-0000_00_1a_7-usb-0_1_1_0-scsi-0_0_0_0
ID_REVISION=PMAP
ID_SERIAL=TDKMedia_Trans-It_Drive_07BA1203F92265C2-0:0
ID_SERIAL_SHORT=07BA1203F92265C2
ID_TYPE=disk
ID_USB_DRIVER=usb-storage
ID_USB_INTERFACES=:080650:
ID_USB_INTERFACE_NUM=00
ID_VENDOR=TDKMedia
ID_VENDOR_ENC=TDKMedia
ID_VENDOR_ID=0718
MAJOR=8
MINOR=16
SEQNUM=2048
SUBSYSTEM=block
TAGS=:systemd:
UDISKS_PRESENTATION_NOPOLICY=0
USEC_INITIALIZED=96565
...
</pre>
dove per comodità ci si è limitati al solo output prodotto dal penultimo evento, quello corrispondente alla creazione del file di tipo dispositivo a blocchi <code>/dev/sdb</code>, ma ciascun evento avrebbe avuto delle variabili associate.
 
Questo è un comando molto utile per catturare informazioni su un evento desiderato. Infatti le proprietà potranno essere utilizzate come condizioni per creare regole personalizzate relative a un dato dispositivo o a un'intera famiglia di dispositivi (per tipo, marca, ecc...), con la granularità desiderata.
 
In modo analogo si possono verificare gli eventi derivanti dalla rimozione di un dispositivo, e in generale tutti i cambiamenti di stato di ogni dispositivo gestito da '''udev'''.
 
==== Informazioni sui file di tipo dispositivo già creati ====
Un'altra possibilità per recuperare informazioni relative a un dato dispositivo, dopo averlo inserito, è quello di interrogare <code>systemd-udevd</code> partendo dal nome associato in modo dinamico al dispositivo. Sempre nel caso di una memoria, che si suppone identificata come <code>/dev/sdb</code> e contenente un'unica partizione <code>/dev/sdb1</code>:
<pre>
$ udevadm info --name sdb1 --attribute-walk
</pre>
(Forma abbreviata: <code>udevadm info -n sdb1 -a</code>)
 
Restituisce informazioni sul file dispositivo cercato e tutti quelli presenti a livello superiore, in ordine inverso a come sarebbero monitorati. Per esempio, sempre nel caso della memoria USB, rimuovendo le informazioni meno utili:
<pre>
...
  looking at device '/devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host10/target10:0:0/10:0:0:0/block/sdb/sdb1':
    KERNEL=="sdb1"
    SUBSYSTEM=="block"
    DRIVER==""
    ATTR{ro}=="0"
    ATTR{size}=="15099904"
    ...
 
  looking at parent device '/devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host10/target10:0:0/10:0:0:0/block/sdb':
    KERNELS=="sdb"
    SUBSYSTEMS=="block"
    DRIVERS==""
    ATTRS{ro}=="0"
    ATTRS{size}=="15101952"
    ...
 
  looking at parent device '/devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host10/target10:0:0/10:0:0:0':
    KERNELS=="10:0:0:0"
    SUBSYSTEMS=="scsi"
    DRIVERS=="sd"
    ATTRS{rev}=="PMAP"
    ATTRS{type}=="0"
    ATTRS{scsi_level}=="5"
    ATTRS{model}=="Trans-It Drive  "
    ...
    ATTRS{vendor}=="TDKMedia"
    ...
 
  looking at parent device '/devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host10/target10:0:0':
    KERNELS=="target10:0:0"
    SUBSYSTEMS=="scsi"
    DRIVERS==""
 
  looking at parent device '/devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host10':
    KERNELS=="host10"
    SUBSYSTEMS=="scsi"
    DRIVERS==""
 
  looking at parent device '/devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0':
    KERNELS=="6-1:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb-storage"
    ...
 
  looking at parent device '/devices/pci0000:00/0000:00:1a.7/usb6/6-1':
    KERNELS=="6-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ...
    ATTRS{manufacturer}=="TDKMedia"
    ...
    ATTRS{product}=="Trans-It Drive"
 
  looking at parent device '/devices/pci0000:00/0000:00:1a.7/usb6':
    KERNELS=="usb6"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ...
 
  looking at parent device '/devices/pci0000:00/0000:00:1a.7':
    KERNELS=="0000:00:1a.7"
    SUBSYSTEMS=="pci"
    DRIVERS=="ehci-pci"
    ...
 
  looking at parent device '/devices/pci0000:00':
    KERNELS=="pci0000:00"
    SUBSYSTEMS==""
    DRIVERS==""
</pre>
 
==== Ottenere informazioni specifiche (''query'') ====
Per finire, se si è interessati soltanto a determinati campi, è possibile ricorrere all'opzione <code>--query</code> (abbreviata: <code>-q</code>).
 
Un esempio comune è quello di ottenere il percorso a partire da <code>/sys</code> del dispositivo, che può essere usato per testare un evento. Sempre con la memoria USB con partizione <code>/dev/sdb1</code>:
<pre>
$ udevadm info -q path -n sdb1
</pre>
Restituisce il percorso (a partire da <code>/sys/<code>):
<pre>
/devices/pci0000:00/0000:00:1a.7/usb6/6-1/6-1:1.0/host10/target10:0:0/10:0:0:0/block/sdb/sdb1
</pre>
 
=== Testare regole ===
Con il percorso a partire da <code>/sys</code> di un dato dispositivo e [[privilegi di amministrazione]], è sufficiente:
<pre>
# udevadm test /percorso
</pre>
Saranno testati ricorsivamente tutti gli eventi contenuti a partire dal percorso scelto.
 
È possibile specificare azioni (come per esempio ''add'' o ''remove'') con l'opzione <code>--action=ACTION</code> (abbreviata: <code>-a</code>).
 
Per esempio, sempre con la memoria USB, per testare gli eventi di aggiunta e rimozione del dispositivo:
<pre>
# udevadm test $(udevadm info -q path -n sdb1) -a add
# udevadm test $(udevadm info -q path -n sdb1) -a remove
</pre>
 
Le azioni possono essere controllate con il monitoraggio di '''udev''', come visto in precedenza. Di default è utilizzata ''change'', che cattura ogni tipo di azione.
 
=== Caricamento delle regole ===
Di norma le regole di '''udev''' sono caricate automaticamente, ma avranno efficacia solo per gli eventi successivi alla modifica.
 
Per forzare l'esecuzione di tutte le regole, con [[privilegi di amministrazione]] è sufficiente:
<pre>
# udevadm trigger
</pre>
 
E in caso il caricamento automatico delle nuove regole fallisse, è possibile caricarle manualmente con:
<pre>
# udevadm control --reload
</pre>


== File di configurazione ==
== File di configurazione ==
Riga 30: Riga 230:
Per lo stesso motivo non si deve occupare della gestione delle connessioni di rete. Inoltre i nomi da assegnare alle interfacce di rete sono gestiti dalle regole scritte in <code>/etc/udev/rules.d/70-persistent-net.rules</code>, generato automaticamente.}}
Per lo stesso motivo non si deve occupare della gestione delle connessioni di rete. Inoltre i nomi da assegnare alle interfacce di rete sono gestiti dalle regole scritte in <code>/etc/udev/rules.d/70-persistent-net.rules</code>, generato automaticamente.}}


(TODO)
È sufficiente creare nella directory <code>/etc/udev/rules.d</code> un nuovo file con estensione <code>.rules</code>, uno per ciascun dispositivo.
 
Il formato delle regole, per scriverne di facilmente comprensibili, è molto semplice:
* i commenti sono preceduti da cancelletto (<code>#</code>);
* ogni regola va scritta su un'unica riga, con possibilità di andare a capo soltanto lasciando un backslash <code>\</code> come ultimo carattere;
* ogni regola consiste di una o più condizioni, separate e seguite da virgola, e una o più azioni, separate da virgola;
* condizioni e azioni sono formate da tre elementi: chiave, operatore e valore, quest'ultimo racchiuso tra virgolette;
* condizioni e azioni sono distinguibili soltanto dall'operatore utilizzato e dalle chiavi utilizzabili, e inoltre il valore di una condizione può essere un pattern con <code>*</code> per rappresentare qualsiasi stringa.
 
Per una descrizione esaustiva si rimanda al manuale (<code>man udev</code>), di seguito qualche semplice esempio.
 
Per le condizioni si considera l'operatore di equivalenza (<code>==</code>) con alcune chiavi comuni (si controlli per un esempio i valori restituiti in precedenza con la chiave USB):
* <code>ACTION</code> per determinare le azioni a cui la regola va applicata, come osservati monitorando gli eventi;
* <code>KERNEL</code> il nome del file di tipo dispositivo, come sarebbe scelto senza l'attuale regola. Vista la scelta dinamica è in genere consigliabile utilizzare un pattern con <code>*</code> (per esempio in <code>/etc/udev/rules.d/70-persistent-net.rules</code> è utilizzata la condizione <code>KERNEL=="eth*"</code>);
* <code>SUBSYSTEMS</code> per identificare il sottosistema dell'evento, in base ai valori monitorati e alla granularità desiderata;
* <code>DRIVERS</code> per filtrare gli eventi in base al modulo del kernel utilizzato (per esempio nel caso della memoria USB dell'esempio sarebbe stato ''usb-storage'', ma dipende dalla granularità desiderata dal filtro);
* <code>ENV{proprietà}</code> per confrontare i valori di una data proprietà, come ottenuti dal monitoraggio di un dato evento.
 
Per le azioni si considera l'operatore di assegnamento (<code>=</code>) con alcune chiavi comuni:
* <code>NAME</code> per determinare il nome del file di tipo dispositivo da creare, permesso solo per interfacce di rete;
* <code>SYMLINK</code> per creare un link simbolico personalizzato, permesso per tutti i dispositivi, purché il nome non interferisca con quelli riservati dal kernel;
* <code>OWNER</code> per determinare l'utente proprietario;
* <code>GROUP</code> per determinare il gruppo proprietario;
* <code>MODE</code> per i permessi da associare (si veda <code>man chmod</code>, la sintassi è la stessa in forma ottale);
* <code>RUN</code> per eseguire un programma esterno. Per quest'azione si raccomanda l'uso di programmi veloci che terminano le proprie azioni in tempi brevi, per non rallentare la gestione degli eventi successivi, ed eventuali processi lanciati in background saranno terminati da '''udev''' quando termina il programma lanciato in questo modo.


== Esempi ==
== Esempi ==
=== Configurare un monitor esterno in automatico ===
=== Utilizzo di nomi persistenti per memorie rimovibili ===
Si rimanda a [[Xrandr e udev: configurare un monitor esterno in automatico | questa guida Wiki]].
Riprendendo l'esempio della memoria USB, basta creare un file <code>/etc/udev/rules.d/99-my-usb.rules</code>:
<pre>
ACTION=="add", SUBSYSTEMS=="usb", DRIVERS=="usb-storage", ENV{ID_VENDOR}=="TDKMedia", ENV{ID_FS_UUID}="...", SYMLINK="myusb"
</pre>
Le prime cinque condizioni filtrano gli eventi '''udev''', e si attivano durante la creazione (azione: ''add'') dei file dispositivo relativi al sottosistema ''usb'', al modulo del kernel ''usb-storage'' per il dispositivo con ID_VENDOR "TDKMedia" e contenente una partizione con un dato [[UUID]]. L'azione si limita a creare un link simbolico con il nome scelto, che funge da alias per quello vero e proprio (per esempio <code>/dev/sdb1</code>).
 
Per esempio ora è possibile montare la partizione scelta in /mnt con:
<pre>
# mount /dev/myusb /mnt
</pre>
a prescindere dal nome che sarà assegnato alla partizione (<code>/dev/sdb1</code>, <code>/dev/sdc1</code>, ecc...).
 
Si noti l'utilizzo di <code>SYMLINK</code> in luogo di <code>NAME</code>, in quanto è possibile soltanto creare un link simbolico personalizzato per file che non sono relativi a interfacce di rete. Si ricorda nuovamente che per effettuare il mount vero e proprio l'uso di '''udev''' è caldamente sconsigliato.
 
Un simile risultato si può ottenere impostando una regola personalizzata in <code>/etc/fstab</code>, che legga l'[[UUID]] della partizione, riservando una directory allo scopo come punto di mount personalizzato. Lo scopo di questa sezione è solo esemplificare il funzionamento di '''udev''', stesso motivo per cui si sono scritte più condizioni di quelle strettamente necessarie.
 
=== Permettere lettura e scrittura su una memoria esterna a tutti gli utenti di un dato gruppo ===
Creo un gruppo ''usbstorage'' per gestire tutte le unità rimovibili USB, supponendo siano tutte gestite dal modulo del kernel <code>usb-storage</code>:
<pre>
# addgroup usbstorage
</pre>
 
Aggiungo l'utente principale a tale gruppo:
<pre>
# adduser tuo-nome-utente usbstorage
</pre>
 
Effettuo logout e login con tale utente, per rendere effettive le modifiche.
 
Ora scrivo una regola personalizzata per tutti i dispositivi, creando un file <code>/etc/udev/rules.d/99-usbstorage.rules</code> contenente:
<pre>
ACTION=="add", SUBSYSTEMS=="usb", DRIVERS=="usb-storage", MODE="0660", OWNER="root", GROUP="usbstorage"
</pre>
 
Le prime tre condizioni filtrano gli eventi '''udev''', e si attivano durante la creazione (azione: ''add'') dei file dispositivo relativi al sottosistema ''usb'' e al modulo del kernel ''usb-storage''. Le restanti azioni assegnano al file come proprietario l'utente ''root'', il gruppo ''usbstorage'' e come permessi <code>0660</code>, corrispondente a permessi di lettura e scrittura per solo utente e gruppo.
 
Ora, in modo analogo a come funzionava il gruppo ''floppy'', sarà possibile formattare e copiare un'immagine CD direttamente sui supporti rimovibile anche senza privilegi di amministrazione, se si è membri del gruppo ''usbstorage''.
 
{{Warningbox | Si noti invece che aggiungere il proprio utente al gruppo '''disk''', quello utilizzato di default a partire da Debian 8 ([[Jessie]]), gli darebbe permessi di lettura e scrittura anche sui dischi fissi utilizzati dal sistema, il che sarebbe praticamente equivalente (quanto a pericolosità dell'impostazione) a essere [[root]].}}
 
Per annullare le modifiche è sufficiente rimuovere il file <code>/etc/udev/rules.d/99-usbstorage.rules</code> e rimuovere tutte le unità USB ancora collegate.
 
=== Limitare i permessi di lettura e scrittura di /dev/fuse al solo gruppo fuse ===
A partire da Debian 8 ([[Jessie]]), il modulo <code>fuse</code> è utilizzabile da tutti gli utenti. Per ripristinare la situazione precedente, se per esempio si utilizza un ambiente grafico minimale o alcuni utenti non utilizzano nemmeno l'interfaccia grafica, è sufficiente creare una regola personalizzata. Va ricordato infatti che la modifica è stata apportata per via dell'integrazione di ''fuse'' nei principali [[Desktop Environment]].
 
Creare <code>/etc/udev/rules.d/99-fuse.rules</code> contenente:
<pre>
ACTION=="change", KERNEL=="fuse", MODE="0660", OWNER="root", GROUP="fuse"
</pre>
 
Le prime due condizioni filtrano gli eventi '''udev''', e si attivano a ogni cambiamento (azione: ''change'', che include la creazione) del file <code>/dev/fuse</code> (kernel: ''fuse''). Le restanti azioni assegnano al file come proprietario l'utente ''root'', il gruppo ''fuse'' e come permessi <code>0660</code>, corrispondente a permessi di lettura e scrittura per solo utente e gruppo.
 
Per rendere effettiva la regola da subito, senza attendere il successivo avvio, visto che <code>/dev/fuse</code> già esiste, è necessario forzarne l'esecuzione con:
<pre>
# udevadm trigger
</pre>
 
Se si utilizzano più utenti, soltanto quelli appartenenti al gruppo ''fuse'' potranno utilizzare <code>fuseiso</code> e in generale tutti i programmi utilizzanti il modulo del kernel ''fuse''.
 
Per annullare le modifiche è sufficiente eliminare il file <code>/etc/udev/rules.d/99-fuse.rules</code> e rieseguire <code>udevadm trigger</code>.
 
=== Monitor esterno ===
Si consideri di voler configurare un monitor esterno in automatico, solo quando questo è aggiunto al sistema. Si rimanda a [[Xrandr e udev: configurare un monitor esterno in automatico | questa guida Wiki]], che utilizza anche l'azione <code>RUN</code> per lanciare un veloce script.


== Approfondimenti ==
== Approfondimenti ==
=== Manuali e file Readme ===
=== Manuali e file Leggimi ===
* Per la scrittura delle regole: <br /><code>$ man udev</code>
* Per la scrittura delle regole: <br /><code>$ man udev</code>
* Per i parametri del kernel e la sintassi del file di configurazione <code>/etc/udev/udev.conf</code>: <br /><code>$ man udevd</code>
* Per i parametri del kernel e la sintassi del file di configurazione <code>/etc/udev/udev.conf</code>: <br /><code>$ man udevd</code>
Riga 48: Riga 334:


{{Autori
{{Autori
|Autore = [[Utente:HAL 9000|HAL 9000]] 21:44, 23 ott 2015 (CEST)
|Autore = [[Utente:HAL 9000|HAL 9000]] 17:33, 24 ott 2015 (CEST)
|Estesa_da =
|Estesa_da =
:
:
3 581

contributi