MRW

Automatischer Datenabgleich zwischen Linux und einem iAudio X5

Wäre es nicht toll, man könnte Abends das iAudio an den Computer anschlissen, und am anderen Morgen hätte man die neuesten Pod-Casts (z.B. mit Amarok runtergeladen) und die gerade neu gerippten CDs und konvertierten Videos automatisch auf dem iAudio, ohne dass man ausser dem abendlichen einstecken in und morgendlichen ausziehen aus der Ladestation auch nur einen Finger krumm machen muss? Linux sei dank geht das problemlos mit nur ein klein wenig Vorarbeit. Dasselbe Verfahren kann man natürlich auch anwenden, wenn man eine Sicherungskopie automatisch anlegen will, wann immer eine Sicherungsharddisk angeschlossen wird. Somit lohnt sich der Lernaufwand gleich mehrfach.

Einführung

Mit dem Linux udev-System ist es sehr einfach, auf Hotplugereignisse, wie einstecken oder ausziehen von Geräten zu reagieren, und ein Programm zu starten, oder unter /dev einen Link anzulegen, sodass z.B. ein iAudio immer unter /dev/iaudio angesprochen werden kann, egal ob es aktuell unter /dev/sda1 oder /dev/sde1 liegt. (Gleiches geht auch mit CD/DVD-ROM/RW, usw.). Eine sehr gute Übersicht, die nicht nur für Ubuntu gilt, sondern uneingeschränkt auch auf meinem SuSE funktioniert, gibt es unter: http://wiki.ubuntuusers.de/udev

Ich beschränke mich hier auf den iAudio.

Vorarbeit: Was ist meine Seriennummer

Der iAudio kann unter anderem an seiner Seriennummer erkannt werden. Mittels lsusb erhält man eine Liste der angeschlossenen USB-Geräte. Darunter soll man den iAudio suchen. Dazu schliesst man ihn erst mit dem USB-Kabel an den PC und startet dann lsusb (Ausgabe auf die wesentliche Zeile gekürzt):

> lsusb
Bus 001 Device 013: ID 0e21:0510 Cowon Systems, Inc.

Nun weiss man, wonach man suchen muss: entweder nach "Device 013", nach "0e21:0510" oder "Cowon", ganz wie es beliebt. Diesen Text sucht man nun in der Ausgabe von lsusb -v. Man kann hierzu z.B. die Ausgabe mit lsusb -v > dateiname in eine Textdatei umlenken, die man dann in einem Editor untersucht, oder natürlich mittels lsusb -v | less und dem Schrägstrich / den Text suchen.

Achtung: Spätestens hier muss man root sein für die weiteren Arbeiten, da hier z.B. die Seriennummer dem normalen Nutzer verborgen bleibt.

Bei mir sieht es etwa so aus (gekürzt):

> lsusb -v
[...]
Bus 001 Device 013: ID 0e21:0510 Cowon Systems, Inc.
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x0e21 Cowon Systems, Inc.
  idProduct          0x0510
  bcdDevice            1.00
  iManufacturer          73 Cowon Systems, Inc.
  iProduct               93 iAUDIO X5
  iSerial               103 00000CAC362B
  bNumConfigurations      1
[...]

Wichtig für uns ist iSerial: 00000CAC362B ist die gesuchte Seriennummer, an der ich das Gerät beim Anschliessen erkennen kann.

Die udev-Regeln

Nun gibt es unter /etc/udev/rules.d eine Reihe von Regeln, die in alfabetischer Reihenfolge abgearbeitet werden (und daher mit Nummern beginnen). Da ich die normale Abarbeitung nicht behindern will, sondern nur ergänzen, entscheide ich mich für den Dateinamen 92-usb-storage-custom.rules, der beinahe zuletzt abgearbeitet wird. Die man-Seite von udev beschreibt das Dateiformat, und auch unter welcher Bedingung spätere Aktionen ignoriert werden. Normalerweise wird unter SuSE 10.1 das iAudio automatisch unter /media/IAUDIO eingebunden. Das möchte ich so belassen, und nur noch zusätzlich einen Link nach /dev/iaudio anlegen, um nach einem umeont /media/IAUDIO einfacher das Gerät wieder finden zu können. Ausserdem möchte ich ein Skript starten, das mittels rsync einen Abgleich meiner Musik und der ins iAudio konvertierten Videosammlung mit dem iAudio-Gerät macht (nur in eine Richtung, da ich auf dem Gerät selbst keine Daten anzupassen gedenke). Selbstverständlich kann jeder das Skript dem eigenen Geschmack anpassen.

Die Datei /etc/udev/rules.d/92-usb-storage-custom.rules sieht wie folgt aus:

BUS=="usb", KERNEL=="sd?1", SYSFS{serial}=="00000CAC362B", ACTION=="add", SYMLINK+="iaudio" RUN+="/root/bin/iaudio.sh"

Sie enthält nur eine einzige Zeile: Wenn das Ereignis vom USB-Bus kommt und es sich um die erste Partition eins Speicher Geräts handelt und die Seriennummer (eigene eintragen, siehe oben) 00000CAC362B beträgt und das Gerät hinzugefügt wird, dann lege den Link iaudio unter /dev an und starte das Skript /root/bin/iaudio.sh.

Das Synchronisations-Skript

Unter /root/bin/iaudio.sh liegt nun das folgende, für mich passende Skript:

Achtung: Nicht vergessen, das Skript mittels chmod u+x /root/bin/iaudio.sh ausführbar zu machen.

#! /bin/bash
export HOME=/root
export USER=root
export LANG=de_CH.UTF-8
export PATH=/usr/local/bin:/usr/bin:/usr/X11R6/bin:/bin:/opt/gnome/bin

if [ -f /tmp/iaudio ]; then
  echo "$(date +'%d.%m.%Y %H:%M') - Ignoriere iaudio wegen /tmp/iaudio" > /var/log/iaudio
  exit 0
fi
echo "$(date +'%d.%m.%Y %H:%M') - Starte iaudio sync" > /var/log/iaudio
while ! test -d /media/IAUDIO/music ; do
  echo warte >> /var/log/iaudio
  sleep 1
done
nice -n 19 rsync -rcv --delete /home/data/mp3/ /media/IAUDIO/music 2>&1 >> /var/log/iaudio
nice -n 19 rsync -rcv --delete /home/data/video/iaudio/ /media/IAUDIO/movie 2>&1 >> /var/log/iaudio
sync >> /var/log/iaudio
umount /media/IAUDIO 2>&1 >> /var/log/iaudio \
 && fsck.vfat -aw /dev/iaudio 2>&1 >> /var/log/iaudio
echo "$(date +'%d.%m.%Y %H:%M') - Ende iaudio sync" >> /var/log/iaudio

Bei den Skripten, die von udev aufgerufen werden, sind die üblichen Umgebungsvariabeln alle nicht gesetzt. Daher müssen sie erst einmal gesetzt werden.

Zuerst prüft das Skript, ob die Datei /tmp/iaudio existiert. Wenn diese Datei existiert, tut es gar nichts. Dadurch ist es mir möglich, tempörär zu verhindern, dass automatisch eine Synchronisation gestartet wird, wenn ich das einmal aus irgendeinem Grund nicht haben will. Es ist nämlich sehr sehr wichtig, dass das Gerät erst ausgezogen wird, wenn die Synchronistation abgeschlossen und das Gerät freigegeben wurde. Ansonsten kann das ganze DOS-Dateisystem kaputt gehen (was mir durchaus bereits passiert ist, was man aber mit Neuformatieren1) beheben kann).

Mittels touch /tmp/iaudio kann ich also verhindern, dass die Synchronisation beim Einstecken startet und nach einem rm /tmp/iaudio startet die Synchronisation wieder nach dem nächsten Einstecken.

Danach wartet das Skript solange, bis das Gerät unter /media/IAUDIO eingebunden worden ist. Das machten bei mir die Skripte, die von SuSE eingerichtet wurden. Geschieht das nicht automatisch, kann man das stattdessen mittels mount -o rw,nosuid,nodev,noatime,flush,uid=1000,utf8,shortname=mixed /dev/iaudio /media/IAUDIO selbst einbinden (erstmaliges mkdir /media/IAUDIO nicht vergessen).

Wenn es eingebunden worden ist, werden die Musikdateien aus /home/data/mp3/ in das Musikverzeichnis auf dem iAudio kopiert, und danach die vorkonvertierten Videodateien ins Filmverzeichnis.

Am Ende wird zur Sicherheit mittels sync das Dateisystem zurückgeschrieben, das Dateisystem ausgehängt, und ebenfalls zur Sicherheit das DOS-Dateisystem repariert (da es sehr zur Korruption neigt).

Nun kann das iAudio wieder entfernt werden, mit einer aktulisierten Musiksammlung.

Mount-Parameter

Unter SuSE 10.1 kann ich noch folgende Zeile in /etc/fstab eintragen:

/dev/iaudio          /media/IAUDIO        vfat       hotplug,rw,nodiratime,users,fmask=0002,dmask=0002,nosuid,nodev,flush,utf8,shortname=mixed,iocharset=utf8,codepage=850

Wenn shortname=mixed gesetzt ist, werden DOS-Dateinamen gross geschrieben. Daher müssen die rsync Zeilen in /root/bin/iaudio.sh wie folgt angepasst werden:

statt

nice -n 19 rsync -rcv --delete /home/data/mp3/ /media/IAUDIO/music 2>&1 >> /var/log/iaudio
nice -n 19 rsync -rcv --delete /home/data/video/iaudio/ /media/IAUDIO/movie 2>&1 >> /var/log/iaudio

heisst es nun:

nice -n 19 rsync -rcv --delete /home/data/mp3/ /media/IAUDIO/MUSIC 2>&1 >> /var/log/iaudio
nice -n 19 rsync -rcv --delete /home/data/video/iaudio/ /media/IAUDIO/MOVIE 2>&1 >> /var/log/iaudio

Das von SuSE mitgelieferte Skript /lib/udev/mount.sh durchsucht erst /etc/fstab. Wenn dort die Zeile mit der Option hotplug eingetragen ist, werden die Optionen übernommen. Wichtig ist hierbei besonders die Option shortname=mixed, die gemäss http://www.pro-linux.de/t_system/vfat-tipps.html verhindern soll, dass rsync nicht richtig funktioniert. Trotzdem funktioniert es beim mir nicht richtig…

unison statt rsync

Das Problem mit rsync ist, dass ein vfat Dateisystem wegen seiner Limiten nicht so sehr für einen Abgleich geeignet ist. Es werden viele Dateien mit speziellen Namen jedes mal wieder übertragen, weil sie wohl unter vfat nicht gleich benannt werden können. Dies betrifft nach meiner Beobachtung Dateinamen mit Leerzeichen, Komma, Doppelpunkt, Apostrof und ähnlichen Sonderzeichen.

Mit unison statt rsync funktioniert der Abgleich besser. Allerdings ist es immernoch notwendig, minimale Regeln für die Dateinamen einzuhalten. Dies betrifft folgende Zeichen, die nicht erlaubt sind: Ein Punkt (.) am Ende des Dateinamens ist verboten, ebenso dürfen die Zeichen &, " und : nirgens verwendet werden.

Danach läuft es bestens mit folgendem Skript:

#! /bin/bash
export HOME=/root
export USER=root
export LANG=de_CH.UTF-8
export PATH=/usr/local/bin:/usr/bin:/usr/X11R6/bin:/bin:/opt/gnome/bin

if [ -f /tmp/iaudio ]; then
  echo "$(date +'%d.%m.%Y %H:%M') - Ignoriere iaudio wegen /tmp/iaudio" > /var/log/iaudio
  exit 0
fi
echo "$(date +'%d.%m.%Y %H:%M') - Starte iaudio sync" > /var/log/iaudio
while ! test -d /media/IAUDIO/MUSIC ; do
  echo warte >> /var/log/iaudio
  sleep 1
done
echo "Musikabgleich..." >> /var/log/iaudio
/usr/bin/unison -batch -silent \
  -pretendwin -fastcheck true -perms 0 -path . \
  -force /home/data/mp3 \
  /home/data/mp3 /media/IAUDIO/MUSIC 2>&1 \
  >> /var/log/iaudio \
  && echo "Musikabgleich fertig." 2>&1 >> /var/log/iaudio \
  || echo "Fehler beim Musikabgleich! Code=$?" 2>&1 >> /var/log/iaudio
echo "Filmabgleich..." >> /var/log/iaudio
/usr/bin/unison -ui text -batch \
  -pretendwin -fastcheck true -perms 0 -path . \
  -force /home/data/video/iaudio \
  /home/data/video/iaudio /media/IAUDIO/MOVIE 2>&1 \
  >> /var/log/iaudio \
  && echo "Filmabgleich fertig." 2>&1 >> /var/log/iaudio \
  || echo "Fehler beim Filmabgleich! Code=$?" 2>&1 >> /var/log/iaudio
sync >> /var/log/iaudio
umount /media/IAUDIO 2>&1 >> /var/log/iaudio \
 && fsck.vfat -aw /dev/iaudio 2>&1 >> /var/log/iaudio
echo "$(date +'%d.%m.%Y %H:%M') - Ende iaudio sync" >> /var/log/iaudio

Podcasts

Podcasts sind sehr einfach zu handhaben: Mittels amarok melde ich mich bei allen interessanten Podcasts an, und lasse sie automatisch in mein MP3-Verzeichnis runterladen. Von dort aus werden sie beim nächsten Anschluss des iAudio synchronisiert. Probleme bereiten mir nur die Podcasts mit einem : oder so im Dateinamen.

1) Neu formatieren der iAudio Harddisk: mkfs.vfat -F 32 -n iAudio -v /dev/iaudio Das ist allerdings natürlich mit totalem Datenverlust auf dem Gerät verbunden – nicht so schlimm, wenn man die Daten wieder synchronisieren kann