Aus Linux-Magazin 09/2006

Hotplug unter Debian, SLES 9 und RHAS 4 erweitern

Von Haus aus taugt Debians Hotplug zu wenig mehr, als Treiber zu laden und Geräte zu konfigurieren. Mit den hier exklusiv vorgestellten Skripten reagiert Linux jedoch auch auf angeschlossene Netzwerkkabel sowie Handys in der Umgebung und lässt Anwender Hotplug-Events für eigene Zwecke nutzen.

Bei Debian Sage, Suse Enterprise Linux 9, Red Hat Advanced Server 4 und älteren Systemen ist der Hotplug-Daemon die zentrale Anlaufstelle für alle Ereignisse, die mit Geräten zusammenhängen. Jedoch leistet der Daemon kaum mehr, als nur die Treiber für neue Geräte zu laden. Schon die simple Aufgabe, auf ein angeschlossenes oder abgeklemmtes Netzwerkkabel zu reagieren, überfordert die Implementation der oben genannten Distributionen.

Dabei ist das Kernel-Hotplugging mit seiner Zweiteilung in Kernelfunktion und Hotplug-Daemon leicht erweiterbar, mit Hilfe weniger von der Redaktion entwickelter Skripte sowie dem Netplug-Daemon ist Hotplug durchaus in der Lage, vollautomatisch ein Backup auf einen gerade angeschlossenen USB-Stick zu starten, die MP3-Sammlung eines in der Nähe befindlichen Handys zu aktualisieren oder Netzwerkschnittstellen dynamisch zu konfigurieren.

Ist der Kernel mit der Option »CONFIG_HOTPLUG« übersetzt, legt die Pseudodatei »/proc/sys/kernel/hotplug« fest, welchen Daemon der Kernel aufrufen soll, wenn bestimmte Bustreiber ein neues Gerät am System anmelden (Abbildung 1). Das bedeutet nicht zwangsläufig, dass das betreffende Gerät, etwa »eth0«, soeben physikalisch mit dem Rechner verbunden wurde, Hotplug wird nur mitgeteilt, dass ein neues Gerät im System verfügbar ist.

Abbildung 1: Wann immer die Bustreiber ein neues Gerät im System anmelden, startet der Kernel über seine Hotplug-Funktion den Hotplug-Daemon. Hotplug bedient sich dann der für das jeweilige Bussystem zuständigen Agenten-Skripte aus dem Verzeichnis »/etc/hotplug«.

Abbildung 1: Wann immer die Bustreiber ein neues Gerät im System anmelden, startet der Kernel über seine Hotplug-Funktion den Hotplug-Daemon. Hotplug bedient sich dann der für das jeweilige Bussystem zuständigen Agenten-Skripte aus dem Verzeichnis »/etc/hotplug«.

So erzeugt zum Beispiel der Netzwerkkartentreiber »tg3« einen Hotplug-Event, wenn er geladen wird und die passende Hardware in Form eines Broadcom-Chips vorfindet. Insofern ist Hotplug nicht nur für Hotplugging-Events zuständig, sondern auch für Coldplugging, wenn lediglich der passende Treiber ge- oder entladen wird und sich am Computer physikalisch nichts verändert.

Besitzt das Gerät selbst noch Hotplugging-Möglichkeiten, berücksichtigt das Kernel-Hotplugging diese jedoch nicht. Bestes Beispiel ist eine Netzwerkkarte: Laut Spezifikation ist es durchaus möglich, ein Netzwerkkabel im Betrieb zu entfernen, einzustecken oder auch den Rechner mit einem völlig anderen Netzwerk zu verbinden. Obwohl praktisch alle Treiber längst erkennen, wann eine Verbindung (Link) zu einem Switch oder anderen Netzwerkgeräten besteht, leiten sie diese Information nicht an Hotplug weiter. Der Grund dafür ist, dass ein Netzwerkkartentreiber nicht zu den Bussystem-Treibern zählt.

Kabelkontrolle

Die Verbindungserkennung bei Netzwerkanschlüssen übernimmt zum Beispiel »netplugd« von [1]. Der Entwickler Bryan O\’Sullivan sieht vor, den Daemon über »init« mit einer Maske der zu überwachenden Netzwerkanschlüsse aufzurufen. Nach dem Start überwacht dann jeweils ein »netplugd«-Prozess einen Anschluss. Wie »netplugd« auf eine Link-Veränderung am Anschluss reagiert, legt das Bash-Skript »/etc/netplug.d/netplug« fest, indem es zum Beispiel einen DHCP-Client startet, um eine neue IP-Adresse zu beziehen.

Für die Konfiguration des Netzwerkgeräts ist aber eigentlich Hotplug zuständig, genauer gesagt das Skript »/etc/ hotplug/net.agent«. Bei Ethernet-Devices startet das Skript »ifup«, das die IP-Adresse entweder statisch zuweist oder aber per DHCP besorgt. Noch dazu ruft das Init-Skript »/etc/init.d/networking« bei jedem Systemstart »ifup« auf und richtet sämtliche in der Konfigurationsdatei »/etc/network/interfaces« eingetragenen Netzwerkgeräte ein.

Diese Vorgehensweise ist wenig sinnvoll und führt zu erheblichen Verzögerungen beim Systemstart, etwa wenn auf einem Notebook ohne Netzwerkverbindung der DHCP-Client vergeblich auf eine Antwort wartet. Außerdem ist es aus Sicht eines Administrators nicht wünschenswert, die Systemkonfiguration auf zu viele Stellen zu verteilen. Mit Hilfe des Hotplug-Daemon lassen sich jedoch beide Probleme lösen.

Hotplug-Klasse

Zunächst muss der »ifup«-Aufruf im Init-Skript »networking« entschärft werden. Da ohnehin jeder Netzwerktreiber einen Hotplug-Event erzeugt, sobald er geladen wurde und die Hardware initialisiert hat, darf das Kommando »ifup -a« im Init-Skript lediglich die Loopback-Devices konfigurieren – sie erzeugen als einzige keine Hotplug-Events.

Dazu überarbeitet Listing 1 die Datei »/etc/network/interfaces« so, dass die Ethernet-Devices in der Klasse »hotplug« liegen und nicht mehr automatisch konfiguriert werden. Das Listing zeigt die Einträge für einen Rechner mit zwei Netzwerkkarten, eine per DHCP und eine statisch eingerichtet.

Listing 1:
Interface-Klassen

01 auto lo
02 iface lo inet loopback
03 
04 allow-hotplug eth0
05 iface eth0 inet dhcp
06 
07 allow-hotplug eth1
08 iface eth1 inet static
09   address 192.168.178.110
10   netmask 255.255.255.0
11   network 192.168.178.0
12   broadcast 192.168.178.255
13   gateway 192.168.178.1

Mit dem Schlüsselwort »allow-hotplug« an Stelle des üblichen »auto« ignoriert »ifup -a« diese Netzwerkgeräte. Beim Aufruf des Hotplug-Daemon übergeben die Netzwerktreiber die Umgebungsvariablen »ACTION« und »INTERFACE«. »ACTION« enthält entweder »register« und »unregister«, je nachdem, ob der Treiber ein Netzwerkgerät hinzugefügt oder entfernt hat, während »INTERFACE« den Namen des betroffenen Netzwerkgeräts enthält, etwa »eth0« oder »eth1«.

Im Fall einer statischen Netzwerkkonfiguration wie bei »eth1« in Listing 1 ist es Ansichtssache, ob Hotplug die Einrichtung durchführen soll, sobald das Device verfügbar ist, oder ob dies erst bei angeschlossenem Netzwerkkabel passiert. Bei Servern kann es durchaus interessant sein, den Netzwerkanschluss sofort mit IP-Adresse und Routing-Informationen zu versehen, wenn sich Serverprogramme wie etwa Apache, Bind oder auch Cups ihre Dienste sowohl lokal wie nach außen anbieten und beim Start an eine feste IP-Adresse binden.

Neuer Netz-Agent

Alle anderen Netzwerkanschlüsse, die ihre Adressen von außen beziehen, soll das System sinnvollerweise erst dann konfigurieren, wenn überhaupt eine Netzwerkverbindung besteht. Listing 2 zeigt einen Ausschnitt des angepassten Netz-Agenten von [2], der mit dynamisch konfigurierten Hotplug-Netzwerkschnittstellen umgehen kann.

Listing 2:
Netz-Agent

01 #!/bin/sh
02 [...]
03 case $ACTION in
04 add|register)
05 [...]
06 if grep -q "^auto[[:space:]].*${INTERFACE}" /etc/network/interfaces; then
07   autoif=true
08 elif grep -q "^allow-hotplug[[:space:]].*${INTERFACE}" /etc/network/interfaces; then
09   hotplugif=true
10 fi
11 if grep -q "^iface[[:space:]]*${INTERFACE}[[:space:]]*inet[[:space:]]*static" /etc/network/interfaces; then
12   staticif=true
13 fi
14 if [ "${hotplugif}" = "true" -a "${staticif}" != "true" ]; then
15   if [ -x /sbin/netplugd ]; then
16     debug_mesg "iface $INTERFACE will be configured when link is active"
17     ifconfig ${INTERFACE} 0.0.0.0 up
18     start-stop-daemon --start --background --pidfile /var/run/netplugd.${INTERFACE} --exec /sbin/netplugd -- -i ${INTERFACE} -p /var/run/netplugd.${INTERFACE}
19   else
20     mesg "E: /sbin/netplugd not found. You need to install netplugd."
21   fi
22   exit 0
23 elif [ "${hotplugif}" = "true" -a "${staticif}" = "true" ]; then
24   if ps -C ifup ho args | grep -q "$INTERFACE"; then
25     debug_mesg "Already ifup-ing that interface"
26   else
27     start-stop-daemon --start --background --pidfile /var/run/hotplug.net.ifup.bogus --startas /etc/hotplug/net.ifup -- "$INTERFACE"
28   fi
29   exit 0
30 elif [ "${NET_AGENT_POLICY}" = "auto" -a "${autoif}" = "true" ]; then
31   IFUPARG="$INTERFACE"
32   if [ "$autoif" = "true" ]; then
33     IFUPARG='('$INTERFACE'|-a|--all)'
34   fi
35   if ps -C ifup ho args | grep -q "$IFUPARG"; then
36     debug_mesg "Already ifup-ing that interface"
37   else
38     start-stop-daemon --start --background --pidfile /var/run/hotplug.net.ifup.bogus --startas /etc/hotplug/net.ifup -- "$INTERFACE$LIFACE"
39   fi
40   exit 0
41 fi
42 [...]

In den Zeilen 6 bis 10 erfährt der Agent, ob er die betroffene Schnittstelle »INTERFACE« automatisch konfigurieren soll oder ob es sich um eine Hotplug-Schnittstelle handelt. Das geschieht aus Kompatibilitätsgründen, so lassen sich Ethernet-Devices auch weiterhin unabhängig von Hotplug einrichten. Die Zeilen 11 bis 13 stellen fest, ob das Device statisch konfiguriert wird, zu erkennen an dem Schlüsselwort »static« in der entsprechenden Zeile der Datei »/etc/network/interfaces«. In diesem Fall soll Hotplug die Schnittstelle ohne Rücksicht auf den Link-Status konfigurieren.

Bei Netzwerkschnittstellen, die ihre Adresse dynamisch erhalten, soll »netplugd« den Link-Status überwachen. Die Zeilen 14 bis 22 decken diesen Fall ab, sie prüfen auch, ob das Programm überhaupt installiert ist. Zeile 17 enthält eine Besonderheit: Sie weist der Schnittstelle die IP-Adresse 0.0.0.0 zu und aktiviert sie. Das hebt eine eventuell noch vorhandene Adressenzuweisung auf und stellt sicher, dass »netplugd« Veränderungen beim Link-Status überhaupt merkt.

Bei inaktiven Netzwerkschnittstellen leuchtet zwar eventuell die Link-LED am Anschluss (Abbildung 2), der Treiber jedoch erkennt, dass die Schnittstelle inaktiv ist, und meldet damit weder den Link-Status weiter noch bestimmt er die Übertragungsgeschwindigkeit. Der Befehl in Zeile 17 erlaubt die Weitergabe des Status, indem er die Schnittstelle aktiviert, ohne ihr eine gültige IP-Adresse zuzuweisen.

Abbildung 2: Ist das Netzwerk-Device per »ifconfig« oder »ifdown« abgeschaltet, leuchtet zwar bei angeschlossenem Kabel die Link-LED. Aber der Treiber versucht weder die Netzwerkgeschwindigkeit zu ermitteln noch meldet er ein angeschlossenes Kabel.

Abbildung 2: Ist das Netzwerk-Device per »ifconfig« oder »ifdown« abgeschaltet, leuchtet zwar bei angeschlossenem Kabel die Link-LED. Aber der Treiber versucht weder die Netzwerkgeschwindigkeit zu ermitteln noch meldet er ein angeschlossenes Kabel.

Doppel-Gateway

Die Zeilen 23 bis 29 übernehmen die Einrichtung der Hotplug-Schnittstellen mit statischer IP-Adresse, bei denen die Datei »/etc/network/interfaces« das vorsieht. Ein Problem entsteht, wenn die statische Konfiguration wie in Listing 1 einen Standard-Gateway festlegt, während ein anderes Netzwerkgerät seine Daten vom DHCP-Server bezieht.

Im Beispiel ist der Standard-Gateway über »eth1« zu erreichen, selbst wenn gerade kein Kabel an der Netzwerkkarte angeschlossen ist. Übermittelt nun ein DHCP-Server über das Netzwerkkabel von »eth0« neben der IP-Adresse auch einen neuen Standard-Gateway, taucht dies in der Routing-Tabelle auf – es gibt somit zwei Standard-Gateways, was zu massiven Routing-Problemen führt.

Bei Notebooks oder portablen Rechnern ist es daher sinnvoll, eine Netzwerkschnittstelle nur bei eingestecktem Kabel zu konfigurieren, selbst wenn die Adressen statisch sind. Die nötigen Änderungen sind minimal – der Codeblock von Zeile 23 bis 29 entfällt, die Überprüfung in den Zeilen 11 bis 13 ist ebenfalls überflüssig und Zeile 14 muss folgendermaßen lauten:

elif [ "${hotplugif}" = "true" ]; then

Die Zeilen 30 bis 41 aus Listing 2 sind gegenüber dem ursprünglichen Netz-Agenten von Debian Sarge kaum verändert, sie sind für automatisch konfigurierte Netzwerkgeräte zuständig. Es gibt nur einen wesentlichen Unterschied zum Codeblock der Zeilen 23 bis 29: Die Überprüfung, ob »ifup« bereits läuft, muss nicht nur wie in Zeile 24 das betroffene Interface berücksichtigen, sondern auch »ifup -a« und »ifup –all«. Dies erledigt Zeile 35, nachdem die Zeilen 31 bis 34 das Suchmuster von »grep« in den Zeilen 31 bis 34 angelegt haben.

Netplug anpassen

Der Netplug-Daemon ist eigentlich darauf ausgelegt, unabhängig von Hotplug zu arbeiten. Bei jedem Link-Event ruft der Daemon das Skript »/etc/netplug.d/netplug« auf und übergibt das betroffene Interface sowie das Ereignis, entweder »in« oder »out«, als Parameter. Listing 3 zeigt das neue Netplug-Skript, das jetzt die Link-Events unter der Busbezeichnung »net_link« an Hotplug weiterleitet. Der Vorteil ist, dass der Administrator sämtliche Reaktionen auf die während des Betriebs auftretenden Events zentral im Hotplug konfiguriert.

Listing 3:
Netplug-Skript

01 #!/bin/bash
02 export INTERFACE="$1"
03 case "$2" in
04   in)
05     export ACTION="register"
06     /sbin/hotplug net_link
07     ;;
08   out)
09     export ACTION="unregister"
10     /sbin/hotplug net_link
11     ;;
12 esac

Für Hotplug ist es nicht weiter relevant, ob der Kernel oder Netplug die Events auslösen. Wenn Netplug unter dem Benutzer »root« läuft, kann Hotplug falls notwendig Treiber nachladen, Devices anlegen und Netzwerkgeräte konfigurieren. Da »/sbin/hotplug« lediglich im Verzeichnis »/etc/hotplug« nach einem Agenten sucht, der den Namen des gemeldeten Busses trägt, lässt sich Hotplug um beliebige Pseudo-Bussysteme erweitern (Abbildung 3).

Abbildung 3: Wenn die zusätzlichen Daemons mit Root-Rechten laufen, ergibt sich für Hotplug kein Unterschied, ob die Events vom Kernel oder einem der Daemons stammen. Für die neuen Pseudobusse sind jedoch auch zusätzliche Agenten erforderlich.

Abbildung 3: Wenn die zusätzlichen Daemons mit Root-Rechten laufen, ergibt sich für Hotplug kein Unterschied, ob die Events vom Kernel oder einem der Daemons stammen. Für die neuen Pseudobusse sind jedoch auch zusätzliche Agenten erforderlich.

Listing 4 zeigt die Funktionsweise des neuen Net-Link-Agenten »/etc/hotplug/net_link.agent«. Beim Anschließen des Netzwerkkabels überprüft der Agent in Zeile 6, ob es sich bei dem betroffenen Gerät tatsächlich um ein per Hotplug einzurichtendes Device handelt. Zeile 8 stellt noch sicher, dass nicht gerade ein anderer »ifup«-Prozess versucht die Netzwerkschnittstelle zu konfigurieren. Zeile 11 richtet dann die Netzwerkschnittstelle mit Hilfe des Skripts »net.ifup« von Debian Sarge ein.

Listing 4:
Net-Link-Agent

01 #!/bin/sh
02 [...]
03 case $ACTION in
04 add|register)
05 [...]
06   if grep -q "^allow-hotplug[[:space:]].*${INTERFACE}" /etc/network/interfaces; then
07     # this $INTERFACE is marked as class hotplug
08     if ps -C ifup ho args | grep -q "$INTERFACE"; then
09       debug_mesg "Already ifup-ing that interface"
10     else
11       start-stop-daemon --start --background --pidfile /var/run/hotplug.net.ifup.bogus --startas /etc/hotplug/net.ifup -- "$INTERFACE"
12     fi
13     exit 0
14 [...]
15   ;;
16 remove|unregister)
17 [...]
18   debug_mesg "Invoking ifdown $INTERFACE"
19   if [ -e /var/run/netplugd.${INTERFACE} ]; then
20     kill `cat /var/run/netplugd.${INTERFACE}`
21   fi
22   ifdown "${INTERFACE}"
23   ifconfig ${INTERFACE} 0.0.0.0 up
24   start-stop-daemon --start --background --pidfile /var/run/netplugd.${INTERFACE} --exec /sbin/netplugd -- -i ${INTERFACE} -p /var/run/netplug
25 [...]
26   ;;
27 [...]
28 esac

Entfernt jemand das Netzwerkkabel, kommt der Codeblock von Zeile 16 bis 26 zum Zuge. Zunächst muss der Net-Link-Agent in den Zeilen 19 bis 21 den Prozess von »netplugd« beenden, der die betroffene Schnittstelle überwacht und auch den Event ausgelöst hat. Anschließend schaltet der Agent in Zeile 22 die Schnittstelle per »ifdown« ab.

Probleme mit Adressen

Wie beschrieben liefert eine deaktivierte Netzwerkschnittstelle keine Link-Events mehr, sodass »netplugd« nicht mehr auf das Einstecken eines Netzwerkkabels reagieren kann. Auf der anderen Seite behält das Ethernet-Device seine alte IP-Adresse so lange, bis es eine neue zugewiesen bekommt. Es ist also nicht möglich, die Schnittstelle einfach per »ifconfig eth0 up« wieder zu aktivieren, da dies einen neuen Eintrag für das Gerät in der Routing-Tabelle zur Folge hätte. Deshalb konfiguriert der Net-Link-Agent die Schnittstelle in Zeile 23 von Listing 4 mit »0.0.0.0« als IP-Adresse und aktiviert sie. Die Angabe »0.0.0.0« entspricht in diesem Fall keiner gültigen IP-Adresse, das Routing bleibt unangetastet.

Die Zuweisung der IP-Adresse 0.0.0.0 quittiert »netplugd« allerdings mit der Fehlermeldung »unexpected state DOWNANDOUT for UP« und beendet sich. Um diesem Effekt zu begegnen, schaltete der Net-Link-Agent den Dienst in den Zeilen 19 bis 21 ab. Damit die Netzwerkschnittstelle aber weiterhin überwacht und neu konfiguriert wird, sobald wieder eine Verbindung zum Netzwerk besteht, startet der Net-Link-Agent »netplugd« in Zeile 24 erneut.

Prinzipiell unterstützt »netplugd« bei der Zuweisung der zu überwachenden Schnittstellen auch Wildcards wie »eth*«. Da Netplug jedoch beim Abschalten der Schnittstelle ebenfalls stirbt, muss pro Schnittstelle ein eigener Netplug-Daemon laufen. Deshalb soll die Konfigurationsdatei »/etc/netplug/netplugd.conf« unbedingt komplett leer, aber vorhanden sein, damit »netplugd« die zu überwachende Schnittstelle ausschließlich über die Kommandozeile erhält.

Bluetooth-Events

Daemons, die wie »netplugd« aus logischen Änderungen des Betriebszustands Events erzeugen und per Hotplug behandeln, eignen sich in Kombination mit Hotplug auch für andere Einsatzzwecke. So lässt sich zum Beispiel die Nähe eines Bluetooth-Handys feststellen.

Listing 5 zeigt den Daemon »bluenear«. Er versucht im Abstand von fünf Minuten mit »hcitool« eine Verbindung zum Handy herzustellen. Klappt dies, bestimmt er noch die Link-Qualität, die zwischen 0 und 255 liegt. Sinkt die Qualität unter 128, ist das Telefon und damit der Benutzer wahrscheinlich nicht mehr am Rechner, was einen entsprechenden Hotplug-Event erzeugt. Dies kann ein User-Agent nutzen, um zum Beispiel den Bildschirm zu sperren.

Listing 5:
»bluenear«

01 #!/bin/bash
02 export INTERFACE="00:01:E3:45:FF:FF"
03 STATE="away"
04 
05 while true; do
06   hcitool cc ${INTERFACE} 2>/dev/null
07   if hcitool con|grep -q ${INTERFACE}; then
08     Signal="`hcitool lq ${INTERFACE}`"
09     hcitool dc ${INTERFACE}
10 
11     if [ "${Signal##*: }" -lt 128 ]; then
12       if [ "$STATE" != "away" ]; then
13         STATE="away"
14         export ACTION="unregister"
15         /sbin/hotplug user
16       fi
17     else
18       if [ "$STATE" != "near" ]; then
19         STATE="near"
20         export ACTION="register"
21         /sbin/hotplug user
22       fi
23     fi
24   else
25     if [ "$STATE" != "away" ]; then
26       STATE="away"
27       export ACTION="unregister"
28       /sbin/hotplug user
29     fi
30   fi
31   sleep 5m
32 done

In den Zeilen 6 und 7 erfolgt die Überprüfung, ob sich das Bluetooth-Gerät in Reichweite befindet, absichtlich über einen direkten Verbindungsaufbau per »hotplug cc« gefolgt vom Abruf der Verbindungsübersicht »hotplug con«. Dafür muss aber die Bluetooth-ID bekannt und in Zeile 2 eingetragen sein. Mit »hcitool scan« würden zwar alle nahen Bluetooth-Geräte aufgelistet, der Parameter »scan« zeigt jedoch nur sichtbare Bluetooth-Geräte an. Gerade die sind aber ein ernst zu nehmendes Sicherheitsrisiko für Angriffe, sodass der Autor den etwas umständlicheren direkten Verbindungsaufbau bevorzugt.

Ein weiterer Vorteil einer direkten Bluetooth-Verbindung ist, dass »hcitool« in Zeile 8 die Signalstärke bestimmt: Sinkt sie unter den voreingestellten Wert, ist die Distanz zwischen Bluetooth-Gerät und Rechner zu groß und der Benutzer wird in den Zeilen 13 bis 15 als abwesend gemeldet. Gleiches passiert in den Zeilen 26 bis 28, wenn der Verbindungsaufbau fehlschlägt. Ist das Handy wieder in der Nähe, melden die Zeilen 19 bis 21 den Benutzer zurück.

Hotplug delegieren

Viele USB-Geräte dienen nur einem Zweck: Schließt der Benutzer zum Beispiel einen Scanner an, möchte er wahrscheinlich etwas einscannen, wenn er die Digitalkamera anschließt, die dort gespeicherten Bilder übertragen. Diese Kausalität eröffnet Raum fürs Automatisieren: Wer für den Datentransfer zwischen heimischem PC und Arbeitsplatzrechner stets denselben USB-Speicher verwendet, kann sich viel Tipparbeit ersparen, indem er den Datenaustausch mit Hotplug automatisieren.

Der Knackpunkt ist, den Benutzern Hotplug-Events zugänglich zu machen. Dazu ist eine Erweiterung des USB-Hotplug-Agenten erforderlich und die Benutzer müssen ihrerseits für die gewünschten Geräte eigene Hotplug-Skripte anlegen. Listing 6 zeigt die Erweiterung, die Root unter dem Namen »/etc/hotplug/usb.specialdev« abspeichert. Damit der USB-Agent die Erweiterung auch berücksichtigt, fügt der Admin die Zeile ». usb.specialdev« in den USB-Agenten »usb.agent« im gleichen Verzeichnis ein, und zwar als letzten Befehl des »add«-Blocks ganz am Ende der Datei, sodass der Agent, nachdem er die Treiber geladen und initialisiert hat, die User-Hotplug-Skripte abarbeitet.

Listing 6:
»usb.specialdev«

01 if [ ! -e "/sys${DEVPATH}/idProduct" -o ! -e "/sys${DEVPATH}/idVendor" ]; then
02   exit 0
03 fi
04 
05 read VendorID < /sys${DEVPATH}/idVendor
06 read ProductID < /sys${DEVPATH}/idProduct
07 read SerialNo < /sys${DEVPATH}/serial
08 
09 for User in `cut -d":" -f1,6</etc/passwd`; do
10   UserName=${User%:*}
11   UserHome=${User#*:}
12 
13   for HpScript in ${UserHome}/.hotplug/${VendorID}.${ProductID}*; do
14     if [ -e "${HpScript}" ]; then
15       UserSerial=${HpScript##*/}
16       UserSerial=${UserSerial/${VendorID}.${ProductID}}
17       UserSerial=${UserSerial#:}
18       if [ -n "${UserSerial}" -a "${UserSerial}" != "${SerialNo}" ]; then
19         break
20       fi
21       if [ -x $HpScript ]; then
22         su "$UserName" -c "$HpScript add" &
23       fi
24     fi
25   done
26 done

Die Zeilen 1 bis 3 stellen sicher, dass das, was Hotplug gemeldet hat, ein echtes Gerät und nicht nur das Feature eines Geräts ist. Die Unterscheidung ist einfach, Vendor- und Produkt-ID gibt es nur bei echten USB-Geräten. Die Zeilen 5 bis 7 lesen diese Informationen nebst Seriennummer auch gleich ein.

Die Schleife ab Zeile 9 arbeitet die Datei »/etc/passwd« zeilenweise ab und sucht sich für jeden Benutzer dessen Homeverzeichnis heraus. Gibt es dort im Unterverzeichnis ».hotplug« ein User-Hotplug-Skript, dessen Name mit der Vendor- und Product-ID des gerade eingesteckten Geräts beginnt (Zeile 13), vergleicht Zeile 18 noch, ob der Dateiname eine Seriennummer enthält und ob sie mit der des neuen Geräts übereinstimmt.

Ist das User-Hotplug-Skript nicht auf Seriennummer gemünzt oder stimmen die Seriennummern überein, ruft Hotplug das User-Hotplug-Skript in Zeile 22 mit den Rechten des jeweiligen Benutzers auf. Wichtig ist, dass »su« die Umgebungsvariablen von Hotplug übernimmt, also keine Login-Shell bereitstellt, da sonst die Umgebungsvariablen mit den Gerätedaten verdeckt sind. Zudem arbeitet das Skript im Hintergrund, damit Hotplug nicht blockieren kann.

Hotplug-Skripte für User

Listing 7 zeigt das passende User-Hotplug-Skript für einen USB-Speicherriegel. Die Zeile 4 überprüft, ob es sich überhaupt um ein USB-Storage-Gerät handelt, und bestimmt gegebenenfalls den Gerätenamen. Dabei nutzt sie gleich mehrere Besonderheiten aus: So meldet Hotplug in der Variablen »DEVPATH« den Pfad zu den Pseudodateien des neuen Geräts, wobei »/sys« nur noch vorangestellt werden muss.

Listing 7:
User-Hotplug-Skript

01 #!/bin/bash
02 case $1 in
03 add)
04   BlockDev=`readlink -f /sys${DEVPATH}/*:*/host*/[0-9]*/block 2>/dev/null`
05   if [ -z "${BlockDev}" ]; then
06     exit 1
07   fi
08 
09   DevName=${BlockDev##*/}
10 [...]

Bei einem USB-Storage-Gerät befinden sich unterhalb dieses Pfads mehrerer Unterverzeichnisse, die die Anschlussposition und die Host-Nummer im Namen tragen. Enthält das unterste Verzeichnis einen relativen symbolischen Link »block«, kennzeichnet dies ein Blockgerät. Diesen relativen symbolische Link wandelt »readlink -f« in eine absolute Pfadangabe um, zum Beispiel »/sys/block/sda«. Aus dieser Angabe wiederum gewinnt Zeile 9 den Gerätenamen. In »/sys/block/sda« gibt es übrigens weitere Einträge, zum Beispiel »sda1«, die auf dem USB-Stick angelegte Partitionen repräsentieren.

Individuelle Behandlung

Ab Zeile 10 kann der Benutzer eigene Befehle einfügen, die Hotplug automatisch unter seiner Identität ausführt, wann immer der USB-Stick angeschlossen wird. Nahe liegende Möglichkeiten sind, die Partition zu mounten und dann mit »rsync« oder anderen Verfahren die Daten abzugleichen. Bei einem USB-Scanner hingegen kann der Benutzer veranlassen, dass »xsane« automatisch startet oder dass ein Skript die Bilder der Digitalkamera nach Datum geordnet auf der Festplatte einsortiert.

Der Benutzer muss das Skript im Unterverzeichnis ».hotplug« in seinem Home speichern – natürlich ausführbar. Der Dateiname folgt dem Muster » Vendor-ID.Product-ID:Seriennummer«, wobei Vendor- und Product-ID vierstellig und mit kleinen Hexadezimal-Buchstaben einzugeben sind – zum Beispiel »0d7d.1600:075218833456«. Der Doppelpunkt und die Seriennummer entfallen, falls das User-Hotplug-Skript bei allen Geräten mit der entsprechenden Vendor- und Product-ID starten soll.

Dieser automatisierte Datenaustausch funktioniert nicht nur bei USB-Geräten, die Kombination von Listing 6 und 7 mit der Bluetooth-Geräteerkennung aus Listing 5 ermöglicht es Hotplug sogar, regelmäßig die MP3-Dateien auf den Handys aller Benutzer in Reichweite zu aktualisieren oder den Abgleich von Terminkalender oder Adressbuch automatisch durchzuführen. Dazu braucht niemand sein Handy an den Computer anzuschließen oder ein Synchronisationsprogramm zu starten, es funktioniert sogar, wenn kein Benutzer am Rechner eingeloggt ist.

Infos

[1] Netplug-Daemon: [http://www.red-bean.com/~bos/]

[2] Skripte: [https://www.linux-magazin.de/Service/Listings/2006/09/hotplug]

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 5 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben