Der Seagate FreeAgent DockStar ist ein Netzwerkadapter (NAS), der USB-Speichermedien im lokalen Netzwerk und - über den kostenpflichtigen Pogoplug-Service - auch per Internet zugänglich macht. Das Gerät verfügt über einen 1,2 GHz ARM Prozessor, 128 MB RAM, 1x GBit LAN und 4 USB 2.0 Schnittstellen, von denen eine zum Anschluss kompatibler Festplatten (FreeAgent Go) als Mini-USB-Stecker ausgeführt ist. Das Betriebssystem, ein angepasstes Linux - im folgenden Pogoplug Linux genannt -, befindet sich auf dem internen 256 MB Flash Speicher. Es können aber auch andere für die ARM-Architektur verfügbare Linux-Distributionen eingesetzt werden, wodurch sich der Verwendungszweck vielfältig erweitern lässt.
Im folgenden dokumentiere ich die Einrichtung des Seagate FreeAgent DockStar als DVB-T Rekorder. Als Betriebssystem nutze ich Arch Linux ARM, das aus PlugApps Linux (vormals Plugbox Linux) und ArchMobile hervorgegangen ist und auf dem seit längerem für die i686- und x86_64-Architekturen verfügbaren Arch Linux basiert. Zur Programmierung und Aufnahme von TV-Sendungen dient der VDR. An den DockStar angeschlossen sind
Ein weiteres, sekundäres, Aufnahmeverzeichnis auf dem USB-Stick ermöglicht einen zeitweilig lautlosen Betrieb ohne Zugriff auf die Festplatte. Beide Verzeichnisse werden mit dem Aufs-Dateisystem übereinander gelegt und per NFS im lokalen Netzwerk freigegeben. Die VDR-Oberfläche ist dort per Remote Frontend (xineliboutput) zugänglich. Zum Anlegen von Aufnahmetimern, auch via Internet, dient ein Webinterface (vdradmin-am).
Die Installationsanleitung für Arch Linux ARM (Stand Juni 2011) beschreibt die Formatierung eines USB-Sticks mit Ext2 und das Aufspielen das Betriebssystem-Images am DockStar unter Pogoplug Linux. Von dieser Vorgehensweise weiche ich in einigen Punkten ab:
Die Formatierung eines Datenträgers birgt stets die Gefahr eines Datenverlustes durch irrtümliche Angabe eines falschen Devices. Es ist deshalb wichtig das Device des USB-Sticks zweifelsfrei zu identifizieren, etwa anhand der Ausgabe von dmesg. Im folgenden wird stellvertretend /dev/sdx verwendet. Mit fdisk lege ich auf dem Stick drei primäre Partitionen an. Man beachte, dass es Vorteile haben kann, stattdessen gdisk zu verwenden, dazu mehr im Forum und im Abschnitt 6.2.
[root@linux ~]# fdisk /dev/sdx
Neben Bootpartition (32 MB) und Rootpartition (1200 MB) nimmt eine dritte (Home-)Partition den Rest des 16 GB-Sticks ein. Sie wird das sekundäre VDR-Aufnahmeverzeichnis beherbergen. Auf eine Swap-Partition verzichte ich, 128 MB RAM sollten für den beschriebenen Verwendungszweck genügen. Hier das Ergebnis der Partitionierung:
Disk /dev/sdc: 16.0 GB, 16001269760 bytes
64 Köpfe, 32 Sektoren/Spur, 15260 Zylinder, zusammen 31252480 Sektoren
Einheiten = Sektoren von 1 × 512 = 512 Bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Gerät boot. Anfang Ende Blöcke Id System
/dev/sdx1 2048 67583 32768 83 Linux
/dev/sdx2 67584 2525183 1228800 83 Linux
/dev/sdx3 2525184 31252479 14363648 83 Linux
Beim Anlegen der Dateisysteme erhält jede Partition zur einfacheren Identifikation zugleich ein Label. Um keinen Speicherplatz zu verschwenden, wird auf der home-Partition der für root reservierte Speicherplatz (5% per Voreinstellung) auf 1% reduziert.
[root@linux ~]# mkfs.ext2 -L boot /dev/sdx1
[root@linux ~]# mkfs.ext4 -L root /dev/sdx2
[root@linux ~]# mkfs.ext4 -L home -m 1 /dev/sdx3
Um Schreibzugriffe zu minimieren, kann man das Journal der ext4-Partitionen mit der Option -O ^has_journal deaktivieren, riskiert damit bei Stromunterbrechung aber ein inkonsistentes Dateisystem.
Der Stick wird nun gemountet und das Image von Arch Linux ARM darauf entpackt. Man achte sorgsam darauf, dieses im richtigen Verzeichnis zu tun, um keine Dateien des laufenden Systems zu überschreiben.
[root@linux ~]# mount /dev/sdx2 /mnt/
[root@linux ~]# cd /mnt/
[root@linux mnt]# mkdir boot
[root@linux mnt]# mount /dev/sdx1 boot/
[root@linux mnt]# tar -xf /pfad/zu/ArchLinuxARM-armv5te-latest.tar.gz
Da der Bootloader uBoot das Kernel-Image auf der ersten Partition im Verzeichnis /boot erwartet (so wie es ohne separate Bootpartition wäre), legen wir einfach einen gleichnamigen Link auf das aktuelle Verzeichnis an. Das ist etwas einfacher als die Umgebungsvariablen des Bootloaders anzupassen (Abschnitt 3.2).
[root@linux mnt]# cd boot
[root@linux boot]# ln -s . boot
Es werden noch einige Konfigurationsdateien auf dem Stick - also unterhalb von /mnt - editiert. In /etc/fstab sind die Partitionen des USB-Sticks einzutragen, andernfalls wird nur die Rootpartition gemountet. Da sich die Zuordnung der Gerätedateien nach einen Reboot ändern kann, empfiehlt sich die Verwendung der oben vergebenen Label. Alternativ können UUIDs (laut blkid) genutzt werden, für die Rootpartition auch /dev/root. Die Optionen noatime und nodiratime unterbinden das unnötige Speichern von Lese-Zugriffszeiten auf dem Stick.
#/etc/fstab
LABEL=root / ext4 noatime,nodiratime 0 0
LABEL=boot /boot ext2 noatime,nodiratime 0 0
LABEL=home /home ext4 noatime,nodiratime 0 0
Temporäre Verzeichnisse wie /tmp, deren Inhalt nach einem Reboot ohnehin gelöscht wird, können in den RAM verlagert werden. Auch diverse Verzeichnisse unter /var/ bieten sich dafür an.1
#/etc/fstab (fortgesetzt)
tmp /tmp tmpfs nodev,nosuid,mode=1777,size=8M 0 0
varlock /var/lock tmpfs nodev,nosuid,mode=1777,size=1M 0 0
varrun /var/run tmpfs nodev,nosuid,mode=0755,size=2M 0 0
varlog /var/log tmpfs nodev,nosuid,mode=0755,size=8M 0 0
Unter Umständen kann es hilfreich sein, den DockStar per USB-Tastatur herunterfahren zu können. Die Tastenkombination Strg+Alt+Entf bewirkt dies zwar per Voreinstellung, ruft aber auch einen Neustart hervor, der sich durch folgende Änderung in /etc/inittab unterbinden lässt:
#/etc/inittab
ca::ctrlaltdel:/sbin/shutdown -t3 -h now
Nach diesen Vorbereitungen kann der USB Stick ausgehängt werden.
[root@linux mnt]# cd / && umount /mnt/boot/ /mnt
Um Arch Linux ARM vom USB-Stick starten zu können, muss der Bootloader uBoot aktualisiert und angepasst werden. Dazu wird zunächst das auf dem internen Flash-Speicher befindliche Pogoplug-Linux gebootet. Um ein ungewolltes Firmwareupdate auszuschließen, das u.U. den SSH-Zugang deaktiviert, sollte man zuvor den Router physisch vom Internet trennen.
Nach Stromzufuhr können einige Minuten vergehen, bis der DockStar vom Router eine IP Adresse anfordert und der Zugang per SSH (Login: root, Passwort: stxadmin) möglich ist. Als erstes beendet man dann den Pogoplug Client:
Pogoplug:$ killall hbwd
Danach kann die Internetverbindung wieder hergestellt werden. Anschließend wird das Installationsscript von Jeff Doozan heruntergeladen und ausgeführt:
Pogoplug:~$ cd /tmp
Pogoplug:/tmp$ wget http://jeff.doozan.com/debian/uboot/install_uboot_mtd0.sh
Pogoplug:/tmp$ chmod +x install_uboot_mtd0.sh
Pogoplug:/tmp$ ./install_uboot_mtd0.sh
Bevor das Script eine neue Version von uBoot installiert, deaktiviert es den Pogoplug Client permanent durch Auskommentieren einer Zeile im Startscript /etc/init.d/rcS:
#Uncomment the line below to enable the pogoplug service
#/etc/init.d/hbmgr.sh start
Zur Konfiguration von uBoot dienen Scripte und Umgebungsvariablen, die man sich mit fw_printenv anzeigen lassen und mit fw_setenv manipulieren kann. Das Script usb_set_bootargs generiert die Kernel-Bootparameter. Die dort verwendete Variable für die Rootpartition $usb_root wird im Script usb_scan ermittelt. Folgende Anpassungen habe ich vorgenommen, um sicherzustellen, dass hier nicht die erste, sondern die zweite Partition des USB-Sticks zugeordnet wird:
Pogoplug:/tmp$ fw_setenv usb_scan_1 'usb=0:1 dev=sda2'
Pogoplug:/tmp$ fw_setenv usb_scan_2 'usb=1:1 dev=sdb2'
Pogoplug:/tmp$ fw_setenv usb_scan_3 'usb=2:1 dev=sdc2'
Pogoplug:/tmp$ fw_setenv usb_scan_4 'usb=3:1 dev=sdd2'
Ist das Device der Rootpartition bekannt (z.B. bei fester Anordnung von USB-Datenträgern), kann stattdessen auch das Script usb_set_bootargs direkt editiert werden, siehe Abschnitt 6. Vorläufig behelfen wir uns aber wie beschrieben. Weiterhin müssen noch die Angaben betreffs des root-Dateisystems und der arcNumber (zur Ansteuerung der LEDs) angepasst werden:
Pogoplug:/tmp$ fw_setenv usb_rootfstype ext4
Pogoplug:/tmp$ fw_setenv arcNumber 2998
Idealerweise aktiviert man auch die Netzkonsole, um die Meldungen des Bootloaders mit netcat verfolgen zu können. Schließlich wird der vorbereitete USB-Stick angeschlossen und der DockStar neu gebootet:
Pogoplug:/tmp$ /sbin/reboot
Wie man ggf. den Bootmeldungen entnehmen kann, scheitert der Start von Arch Linux ARM u. U. zunächst. In diesem Fall wird spätestens nach einigen Minuten erneut das weiterhin auf dem internen Flash-Speicher residierende Pogoplug Linux geladen. Nach einem weiteren Neustart sollte es dann gelingen. Da sich der SSH-Schlüssel nun geändert hat, ist vor der nächsten Anmeldung (Login: root, Passwort: root) der alte Schlüssel zu löschen.
[user@linux ~]$ ssh-keygen -R <IP-Adresse>
Je nach verwendetem USB-Stick führt jede künftige Unterbrechnung der Stromzufuhr u.U. dazu, dass zunächst wieder Pogoplug Linux gestartet wird. Um einen Reboot per SSH herbeizuführen, muss der neue Schlüssel dann wieder gelöscht werden. Eine Möglichkeit diesen Zyklus zu unterbinden und zuverlässig auch nach einem Kaltstart Arch Linux ARM zu booten findet sich im Forum von Jeff Doozan.
Pogoplug:/tmp$ fw_setenv bootcmd 'usb start; usb stop; usb start; run force_rescue_bootcmd; run ubifs_bootcmd; run usb_bootcmd; usb stop; run rescue_bootcmd; run pogo_bootcmd; reset'
Bei Problemen kann man via Netzkonsole auch mit uBoot interagieren. Unter Arch Linux starte ich dazu netcat (Paket gnu-netcat) wie folgt. Nach Beginn des Countdowns gelangt man durch mehrmaliges Drücken der Tastenkombination Strg+J an den Marvell Bootprompt.
[root@linux ~]# netcat -l -u -p 6666
U-Boot 2010.09 (Oct 23 2010 - 11:49:22)
Marvell-Dockstar/Pogoplug by Jeff Doozan
Hit any key to stop autoboot: 9
8
0
Marvell>>
Wurde Arch Linux ARM gebootet und Zugang per SSH gewährt, sind noch einige Konfigurationsdateien anzupassen, ich verweise dazu auf die First Steps und das Wiki von Arch Linux. Hier in kürze die zuerst von mir vorgenommenen Einstellungen:
Anpassen der Lokalisierung, Aktivieren der benötigten Locales (de_DE.UTF–8 UTF–8).
Einrichten einer statischen IP-Adresse
Update - man beachte dazu Abschnitt 4.2
Installation von OpenNTPD
Benutzerverwaltung: Anlegen eines Useraccounts, neues Passwort für root.
SSH absichern: Login für root verbieten, evtl. Passwort-Login deaktivieren.
Neustart.
Die Steuerung der LEDs über das /sys-Verzeichnis erfordert root-Rechte, soll möglichst aber auch anderen Nutzern offenstehen. Der direkte Einsatz von sudo ist in diesem Zusammenhang etwas umständlich. Ich habe deshalb ein einfaches C-Programm geschrieben, das sich auf herkömmliche Weise mit sudo ausführen lässt. Auch kann es einfach innerhalb eines Scriptes genutzt werden, das seinerseits mit sudo aufgerufen wurde (Abschnitt 8.4). Das Programm wird mit gcc, der im gleichnamigen Paket enthalten ist, kompiliert:
[user@alarm ~]$ gcc -o led led.c
Es manipuliert jeweils nur eine der beiden LEDs und ermittelt diese anhand des Namens, unter dem das Programm aufgerufen wurde. Deshalb werden zwei Dateien erstellt, die auf denselben Inode zeigen (Hardlink):
[root@alarm ~]# cp led /usr/local/bin/led_green
[root@alarm ~]# ln /usr/local/bin/led_green /usr/local/bin/led_orange
Ohne Parameter werden verfügbare Zustände und aktueller Status angezeigt. Als erster Parameter kann der gewünschte Status angegeben werden. Der Status timer benötigt zusätzlich die Parameter delay_on und delay_off, hier ein Beispiel:
[root@alarm ~]# led_green
none nand-disk timer heartbeat [default-on]
[root@alarm ~]# led_green timer 1000 1000
Die eingangs erwähnte USB-Festplatte ist bereits formatiert und bleibt (vorerst) permanent angeschlossen. Sie wird deshalb wie der USB-Stick fest über /etc/fstab eingebunden. Die verwendete Festplatte geht nach 30 Minuten ohne Zugriff automatisch in den Standby (unabhängig von mit sdparm oder hdparm eigenstellten Werten).
Neben ihrer eigentlichen Aufgabe nutze ich die Festplatte zur Erweiterung des Speicherplatzes für das Betriebssystem. Dazu werden Verzeichnisse auf der Festplatte mit der mount-Option --bind zusätzlich an geeigneter Stelle im Verzeichnisbaum eingebunden. Damit dennoch ein längerer Standby der Festplatte möglich bleibt, berücksichtige ich nur Verzeichnisse, auf die selten zugegriffen wird: Der Paket-Cache und das ABS-Wurzelverzeichnis (Abschnitt 4.3):
#/etc/fstab (fortgesetzt)
LABEL=usbhdd /hdd ext4 defaults 0 0
/hdd/pkg /var/cache/pacman/pkg none bind 0 0
/hdd/abs /var/abs none bind 0 0
Alternativ wären natürlich auch symbolische Links oder ein Anpassung der Pfade in /etc/pacman.conf und /etc/abs.conf möglich. Die Paketdatenbank /var/lib/pacman/sync verbleibt auf dem Stick, andernfalls würde jeder Aufruf von pacman die Festplatte aus dem Standby holen. Die angegebenen Verzeichnisse müssen, falls nicht bereits vorhanden, vor dem Mounten natürlich angelegt werden.
Mit der Paketverwaltung des Systems sollte man, wie bei jeder Linux-Distribution, vertraut sein. Arch Linux macht überdies auch das Erstellen von Software-Paketen relativ leicht. In den folgenden Abschnitten mache ich davon mehrfach gebrauch ohne auf das Vorgehen im Detail einzugehen, deshalb hier ein kurzer Überblick mit obligatorischen Links zum Wiki.
pacman installiert. Die Repositories und Mirror-Server von Arch Linux (i686/x86_64) sind auf der ARM Architektur nicht nutzbar.makepkg. Die Quellen der für Arch Linux ARM modifizierten Pakete befinden sich separat in einem Git-Repository und sind stets vorzuziehen.Als Git- und Paketbauverzeichnis bietet sich wiederum die Festplatte an. Die PKGBUILDs aus dem abs-Verzeichnis und dem AUR sind auf die von Arch Linux unterstützen Architekturen (i686/x86_64) abgestimmt. Zum Kompilieren auf dem DockStar kann man das arch-Array im PKGBUILD editieren oder einfacher mit der makepkg-Option -A ignorieren. Bei Paketen aus dem AUR sind u.U. weitere Anpassungen des PKGBUILD an die ARM-Architektur erforderlich.
Da keine Swap-Partition angelegt wurde, macht sich beim Paketbau mitunter der begrenzte RAM bemerkbar:
xz: /home/user/abs/foobar/foobar-0.1-1-arm.pkg.tar: Nicht genügend Hauptspeicher verfügbar
Zumeist genügt es dann Programme mit erhöhtem Bedarf an RAM (wie z.B. vdradmind, Abschnitt 8.2.1) vorübergehend zu beenden. Anschließend kann die Zusammenstellung und Komprimierung des betroffenen Paketes mit makepkg -Rf erneut veranlasst werden. Eine zusätzliche Maßnahme wäre die Verwendung einer Kompressionsart, die weniger Arbeitsspeicher beansprucht:
#/etc/makepkg.conf
PKGEXT='.pkg.tar.gz'
Die Fehlermeldung bei erschöpftem RAM ist selten so eindeutig wie im vorherigen Abschnitt, oft werden Programme, deren Bedarf an RAM nicht gestillt werden kann, einfach beendet. Die Ursache findet man dann mit dmesg, hier z.B. bei einer abgebrochenen Datensicherung mit rsync:
[ 3901.497857] Out of memory: Kill process 1262 (rsync) score 272 or sacrifice child
[ 3901.497872] Killed process 1263 (rsync) total-vm:74980kB, anon-rss:24844kB, file-rss:0kB
Zwar könnte man in dieser Situation vorübergehend ein swapfile, vorzugsweise auf der USB-Festplatte, einrichten. Alternativ - oder zusätzlich - gibt es aber auch die Möglichkeit, den verfügbaren RAM besser auszunutzen: Dazu wird mithilfe des Kernelmoduls zram eine virtuelle Swap-Partition /dev/zram0 angelegt und eingebunden. Die in diesen Swap ausgelagerten Daten werden komprimiert und im RAM gespeichert. Die Swap-Partition beansprucht dabei jederzeit nur die den komprimierten Daten entsprechende Menge das RAMs. Im Endeffekt werden also umso mehr Daten im RAM komprimiert, je höher der tatsächliche Bedarf an RAM ist. Der Preis dafür ist eine erhöhte CPU-Belastung.
Zur Konfiguration kann das im AUR verfügbare Paket compcache genutzt werden. Das Paket enthält ein Initscript, das die notwendigen Schritte vereinfacht. Die maximale Menge an unkomprimierten Daten, die /dev/zram0 aufnehmen soll, beträgt per Voreinstellung 25% des RAM, also 32 MB. Ich habe diesen Wert auf ca. 96 MB erhöht:
#/etc/conf.d/compcache
SIZE="96000"
Mit dieser Einstellung konnte ich auch große Pakete mit xz komprimieren und z.B. eine umfangreiche rsnapshot-Sicherung samt ihrer unzähligen Hardlinks mit rsync auf ein anderes, mit dm-crypt/LUKS verschlüsseltes Medium übertragen. Erstellt und eingebunden wird der virtuelle Swap mit dem erwähnten Initscript
[root@alarm ~]# /etc/rc.d/compcache start
Mit zram_stats lässt sich u.a. ermitteln, wieviele Daten momentan im Swap gespeichert werden (orig_data_size) und wieviel Platz diese Daten im RAM einnehmen (compr_data_size).
Zur Aufnahme von Fernsehsendungen soll ein vom Linux-Kernel unterstützter DVB-T Stick genutzt werden. Das Paket linux aus dem archlinuxarm-Repository enthält jedoch nur eine kleine Auswahl der im Kernel insgesamt verfügbaren dvb-usb Module. Wird der DVB-Stick nicht erkannt, kann man versuchen weitere Module nachträglich aus dem v4l-dvb Repository zu installieren, mehr dazu im Abschnitt 7.1.
Eine andere Möglichkeit besteht darin, die Kernelkonfiguration anzupassen: Das Vorgehen ist im Artikel Kernel Compilation beschrieben (das zu modifizierende Kernelpaket befindet sich jedoch im Git-Repository, siehe Abschnitt 4.3), hier das überarbeitete Paket:
Das Aufs-Dateisystem, das zur Verlagerung des VDR-Aufnahmeverzeichnisses zum Einsatz kommen soll, habe ich in das Kernelpaket integriert. Neben den Kernelquellen werden also auch die passenden Kernelpatches und Quelldateien aus dem Aufs-Git-Repository heruntergeladen. Damit erübrigt sich die Erstellung eines zusätzlichen Paketes für das aufs-Kernelmodul, es werden nur die aufs-utils benötigt:
Edit: Aufs ist mittlerweile im Paket linux als integraler Bestandteil des Kernels enthalten (CONFIG_AUFS_FS=y), es wird also auch für den vorinstallierten Kernel kein weiteres Modulpaket benötigt. Allerdings besteht aufgrund der zugrundegelegten Kernelkonfiguration keine Möglichkeit das Aufs-Verzeichnis per NFS zu exportieren (CONFIG_AUFS_EXPORT is not set).
Um die Kompilierzeit zu reduzieren, verwende ich im PKGBUILD des Kernels das make-Target localmodconfig. Es deaktiviert in der Kernelkonfiguration sämtliche Module, die momentan nicht geladen sind 2. Als Basis dient die Konfiguration des laufenden Kernels aus /proc/config.gz. Im Anschluss werden neu hinzugekommene Kerneloptionen einzeln abgefragt. Man kann hier die Vorgaben zunächst bestätigen und hat dann im letzten Schritt via make menuconfig Gelegenheit in einer textbasierten Oberfläche die Konfigurationen zu überarbeiten (NFS, Aufs) und bislang nicht aktivierte Treiber auszuwählen (DVB).
Falls make localmodconfig ausgeführt wurde, sind ggf. die folgenden Optionen wieder zu aktivieren:
File systems --->
[*] Network File Systems --->
<M> NFS server support
[*] NFS server support for NFS version 4 (EXPERIMENTAL)
Das IPv6 Modul sollte automatisch geladen und folglich in jedem Fall ausgewählt sein, andernfalls findet man es unter
[*] Networking support --->
Networking options --->
[*] TCP/IP networking
<M> The IPv6 protocol --->
Hier die von mir gewählte Konfiguration. Wichtig ist, wie oben erwähnt, die Option “NFS-exportable aufs”.
File systems --->
[*] Miscellaneous filesystems --->
<M> Aufs (Advanced multi layered unification filesystem) support
Maximum number of branches (127) --->
[*] Detect direct branch access (bypassing aufs)
method (fsnotify) --->
[*] NFS-exportable aufs
[*] Respect the attributes (mtime/ctime mainly) of special files
[*] Show whiteouts
[*] Ramfs (initramfs/rootfs) as an aufs branch
Die Einstellungen für DVB-Sticks findet man wie folgt. Der gewählte Treiber (letzte Zeile) muss natürlich zu dem verwendeten DVB-Stick passen. Bei hybriden Sticks befinden sich die nötigen Optionen auch im Menüpunkt “Video capture adapters”. Dieser steht nur dann zur Auswahl, wenn auch “Video For Linux” ausgewählt ist.
Device Drivers --->
<M> I2C support --->
<M> Multimedia support --->
<M> DVB for Linux
[*] DVB/ATSC adapters (NEW) --->
<M> Support for various USB DVB device
<M> WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)
Sofern der benötigte Treiber nicht auszumachen ist, kann man diesen mithilfe eines Linux-PCs oder anhand seiner ID identifizieren und in den Kernelquellen die zugehörige CONFIG-Variable finden. Im Abschnitt 7.1 wird das Vorgehen an einem Beispiel gezeigt. Durch Eingabe eines Schrägstrichs startet man innerhalb der Kernelkonfiguration eine Suchmaske und gibt dort die Variable ein, im Beispiel DVB_USB_DTT200U. Das Ergebnis liefert den gesuchten Prompt.
Auch der angepasste Kernel soll das Komprimieren von Daten im RAM ermöglichen. Der Treiber befindet sich noch im Staging-Bereich.
Device Drivers --->
[*] Staging drivers --->
<M> Compressed RAM block device support
Das in dem Paket compcache enthaltene Initscript und die Konfigurationsdateien können auch mit dem angepassten Kernel genutzt werden. Mehr dazu im Abschnitt 4.4.
Im Standardkernel von Arch Linux ARM bis Version 3.1.4 war CONFIG_DEVTMPFS nicht gesetzt. Diese Option wird von udev ab Version 176 benötigt und muss natürlich auch im Custom Kernel aktiviert sein.
Device Drivers --->
Generic Driver Options --->
[*] Maintain a devtmpfs filesystem to mount at /dev
[*] Automount devtmpfs at /dev, after the kernel mounted the rootfs
Ist der Kernel konfiguriert, bestätigt man das Speichern der .config-Datei. Nach dem Kompilieren entstehen die Pakete linux-custom und linux-custom-headers, letzteres wird zum Bau von aufs2-util-git benötigt. Die Pakete lassen sich parallel zu linux und linux-headers installieren, das Kernelimage befindet sich unter /boot/uImage-custom. Um dieses Image zu booten, kann man behelfsweise /boot/uImage damit ersetzen3:
[root@alarm ~]# mv /boot/uImage /boot/uImage-alarm
[root@alarm ~]# cp /boot/uImage-custom /boot/uImage
Sollte nach einem Reboot der eigene Kernel nicht starten, stellt man das ursprüngliche Image wieder her (den Stick dazu an einen anderen PC anschließen) und kann so wieder den offiziellen Kernel nutzen. Ein unbeabsichtigtes Überschreiben von /boot/uImage durch ein Update - pacman geht ja davon aus, das diese Datei zum Paket linux gehört - lässt sich mit der Option NoUpgrade vermeiden, die neue Datei wird dann mit der Endung .pacnew versehen. Alternativ kann man natürlich auch die Kernelpakete vom Update ausschließen:
#/etc/pacman.conf
NoUpgrade = boot/uImage
#IgnorePkg = linux linux-headers
Neben dem Erkennen und Laden des Kernelimages ist uBoot dafür verantwortlich dem Kernel das richtige Device der Rootpartition zu übergeben. Die in Abschnitt 3.2 beschriebene Methode schlägt u.U. fehl, wenn sich Anzahl und/oder Reihenfolge der von uBoot bzw. Kernel erkannten Speichermedien unterscheiden4. Solche Vermittlungsprobleme lassen sich ausschließen, indem der Kernel veranlasst wird, die Rootpartition anhand eindeutiger Merkmale eigenständig zu erkennen. Diese sind:
UUID oder Label des Dateisystems auf der Rootpartition. Um diese beim Booten zu Erkennen ist der Kernel auf eine initial ramdisk angewiesen.
PARTUUID der Rootpartition. Diese steht nur dann zur Verfügung wenn der USB-Stick über eine GUID-Partitionstabelle (GPT) verfügt. Eine initial ramdisk ist nicht erforderlich.
Beide Möglichkeiten werden nachfolgend beschrieben. Um die Bootloaderkonfiguration auch von Arch Linux ARM aus durchführen zu können, muss zunächst von dort aus wie in Abschnitt 3.1 beschrieben das Script install_uboot_mtd0.sh erneut aufgerufen werden. Die Frage Would you like to reset the uBoot environment? [N/y] beantworte man mit “Nein”.
Normalerweise wird eine initrd benötigt, um die zum Mounten der Rootpartition benötigten Treiber für Datenträger und Dateisysteme zur Verfügung zu stellen. Diese sind bei Arch Linux ARM jedoch fest in den Kernel integriert, weshalb das Kernelpaket keine initrd bereitstellt. Sie muss folglich nachträglich erstellt werden.
Unter Arch Linux (i686/x86_64) wird anstelle von initrd der Nachfolger initramfs genutzt, das mit mkinitcpio konfiguriert wird. Es werden nur zwei Hooks benötigt:
#/etc/mkinitcpio.conf
HOOKS="base udev"
Das initramfs für den angepassten Kernel wird wie folgt generiert:
[root@alarm ~]# mkinitcpio -v -k 3.0-custom -g /tmp/initramfs-linux.img
Es kann unter Arch Linux ARM nicht direkt genutzt werden, mit mkimage (aus dem Paket uboot-mkimage) lässt sich daraus aber die eigentliche initial ramdisk erstellen:
[root@alarm ~]# mkimage -A arm -O linux -T ramdisk -C gzip -a 0x00000000 -e 0x00000000 -n initramfs -d /tmp/initramfs-linux.img /boot/uInitrd
Die Datei /boot/uInitrd wird von uBoot ohne weitere Konfiguration erkannt und eingebunden. Sodann sorgt udev für das Anlegen eines dem Label der Rootpartition (hier: root) entsprechenden Links unter /dev/disk/by-label/, der als Kernelparameter genutzt werden kann. Außerdem setze ich rootwait anstelle von rootdelay ein:
[root@alarm ~]# fw_setenv usb_set_bootargs 'setenv bootargs console=$console root=/dev/disk/by-label/root rootwait rootfstype=ext4 $mtdparts $usb_custom_params'
Anstelle des Labels sollte auch die UUID über den Link unter /dev/disk/by-uuid/ genutzt werden können, ich habe dies jedoch nicht ausprobiert. Problematisch ist dagegen die Verwendung der Schreibweisen root=LABEL=... und root=UUID=.... Beide haben nicht zuverlässig funktioniert, näheres im Forum.
Speichermedien mit GPT können vom Linux Kernel ab Version 2.6.37 genutzt werden. Die notwendige Option CONFIG_EFI_PARTITION=y ist im ARCH-Kernel aktiviert und sollte natürlich auch beim Custom-Kernel ausgewählt sein.
Zum Anlegen einer GPT dient das Programm gdisk. Wurde der Stick bereits mit fdisk formatiert, kann gdisk die GPT unter Verwendung der im MBR vorhandenen Partitionstabelle auch nachträglich anlegen. Die notwendigen Schritte habe ich an meinem Linux-PC durchgeführt. Wie schon in Abschnitt 2.1 verwende ich wieder sdx stellvertretend als Device des USB-Sticks (von dem ich zuvor sicherheitshalber ein Backup angelegt habe).
[root@linux ~]# gdisk /dev/sdx
Warnhinweise sollte man beachten und das Programm ggf. mit 'q' abbrechen. Insgesamt gab es zwei Hürden zu nehmen, die ich hier genauer beschreibe:
Aus Redundanzgründen beansprucht die GPT auch einen Bereich am Ende des Speichermediums, der jedoch bereits Bestandteil der dritten Partition ist. Folglich vermeldet gdisk zunächst:
Warning! Secondary partition table overlaps the last partition by
33 blocks!
You will need to delete this partition or resize it in another utility.
Es war also erforderlich zunächst die letzte (dritte) Partition um 33 Blöcke (gemeint sind Sektoren á 512 Byte) zu verkürzen. Bei der Größenangabe für resize2fs ist die Blockgröße des Dateisystems zu berücksichtigen:
[root@linux ~]# dumpe2fs /dev/sdx3|grep "^Block"
dumpe2fs 1.41.14 (22-Dec-2010)
Block count: 3590912
Block size: 4096
Blocks per group: 32768
Die Anzahl der Blöcke muss folglich um 33*512/4096, also mindestens 5, reduziert werden5. Vor dem Verkleinern der Partition ist das Dateisystem zu überprüfen. Zuletzt kann schließlich mit fdisk auch die zugehörige Partition verkleinert werden.
[root@linux ~]# e2fsck -f /dev/sdx3
[root@linux ~]# resize2fs /dev/sdx3 3590907
[root@linux ~]# fdisk /dev/sdx
Das Verkleinern der Partition erfolgt einfach durch Löschen und erneutes Anlegen (d–3-n-p–3). Der vorgeschlagene Startsektor kann übernommen werden, der letzte Sektor ist jedoch um 33 auf 31252446 zu verringern, vgl. Abschnitt 2.1.
Anschließend genügt ein erneuter Aufruf von gdisk /dev/sdx zur Umwandlung des MBR in eine GPT. Sollten keine Warnungen erscheinen, beendet man dazu einfach mit 'w'.
Der Versuch den so manipulierten Stick nun testweise wieder am DockStar zu booten schlug fehl. Vermittels netcat stellte sich heraus, dass uBoot die Partitionen das Sticks nicht mehr zu lesen vermochte:
Loading file "/boot/uImage" from usb device 1:1 (usbdb1)
Failed to mount ext2 filesystem...
** Bad ext2 partition or disk - usb 1:1 **
Abhilfe sollte laut eines Forumsbeitrags das Erstellen eines hybriden MBR bringen, der nur die Bootpartition als erste Partition enhält. Hier die genaue Vorgehensweise mit gdisk unter Zuhilfenahmen der GPT Dokumentation.
Command (? for help): r
Recovery/transformation command (? for help): h
WARNING! Hybrid MBRs are flaky and dangerous! If you decide not to use one,
just hit the Enter key at the below prompt and your MBR partition table will
be untouched.
Type from one to three GPT partition numbers, separated by spaces, to be
added to the hybrid MBR, in sequence: 1
Place EFI GPT (0xEE) partition first in MBR (good for GRUB)? (Y/N): n
Creating entry for GPT partition #1 (MBR partition #1)
Enter an MBR hex code (default 83):
Set the bootable flag? (Y/N): y
Unused partition space(s) found. Use one to protect more partitions? (Y/N): n
Recovery/transformation command (? for help): w
Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!
Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT).
The operation has completed successfully.
Erfreulicherweise erkannte uBoot den Stick nun wie bisher. Um den Vorteil der GPT zu nutzen brauchen wir noch die “Partition unique GUID” der Rootpartition. Diese bringt - unter Arch Linux ARM - ein erneuter Aufruf von gdisk nach Eingabe von 'i' und Partitionsnummer zu Vorschein:
Command (? for help): i
Partition number (1-3): 2
Partition GUID code: 8EC76FBA-2272-45AF-A844-94ED164A1B86 (Unknown)
Partition unique GUID: 43152BE8-EA6D-47EE-A014-59C52C383DE0
First sector: 67584 (at 33.0 MiB)
Last sector: 2525183 (at 1.2 GiB)
Partition size: 2457600 sectors (1.2 GiB)
Attribute flags: 0000000000000000
Partition name: Linux filesystem
Mit dieser Information kann die Bootvariable wie folgt angepasst werden:
[root@alarm ~]# fw_setenv usb_set_bootargs 'setenv bootargs console=$console root=PARTUUID=43152BE8-EA6D-47EE-A014-59C52C383DE0 rootwait rootfstype=ext4 $mtdparts $usb_custom_params'
Vor dem Reboot sollte man eine etwaig vorhandene /boot/uInitrd wieder löschen oder umbenennen. Andernfalls wird der Bootvorgang nach Laden des Kernels nicht fortgesetzt.
Ich betreibe am DockStar einen älteren DVB-T Stick von Freecom und beziehe mich im folgenden konkret auf diesen. Das Vorgehen bei anderen Sticks ist aber ähnlich, sofern im Linux-Kernel ein Treiber existiert.
Besteht Unsicherheit bezüglich des benötigten Treibers (Abschnitt 5.1.3), kann man den DVB-Stick zunächst an einen anderen Linux-PC anschließen 6. Falls dort ein geeigneter Treiber vorhanden ist, werden die benötigten Kernelmodule i.d.R. automatisch geladen und lassen sich z.B. mit lsusb|grep dvb aufzeigen, oder auch mit usb-devices:
P: Vendor=14aa ProdID=0221 Rev=06.02
S: Manufacturer=Digital TV Receiver
S: Product=Digital TV Receiver
I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=dvb_usb_dtt200u
Hier ist also dvb_usb_dtt200u das benötigte Modul. Danach lässt sich gezielt in den Quelldateien des Linux-Kernels Abschnitt 5 suchen, vgl. auch Linux Kernel in a Nutshell Kapitel 7. Man beachte die Ersetzung der Unterstriche durch Minuszeichen. In der Ausgabe findet man die gesuchte Kernelvariable CONFIG_DVB_USB_DTT200U.
[user@alarm linux-2.6.37]$ find -type f -name Makefile | xargs grep dvb-usb-dtt200u
./drivers/media/dvb/dvb-usb/Makefile:dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
./drivers/media/dvb/dvb-usb/Makefile:obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
Möchte man keinen eigenen Kernel kompilieren, kann man auch die Treiber aus dem v4l-dvb Repository von linuxtv.org nutzen. Im AUR befindet sich ein Paket, das sämtliche Treiber installiert. Um die Auswahl auf die tatsächlich benötigten Treiber beschränken zu können, habe ich das PKGBUILD angepasst.
Ob der (entsprechend konfigurierte) Kernel den DVB-Stick unterstützt, kann man z.B. anhand der (nachfolgend gekürzten) Ausgabe von dmesg feststellen. Wird nur eine (die oberste) Zeile ausgegeben, hat man entweder nicht den richtigen Treiber aktiviert oder dieser muss u.U. mit modprobe manuell geladen werden. Falls sich gar keine Module laden lassen, sollte ein Aufruf von depmod helfen.
usb 1-1.4: new high speed USB device using orion-ehci and address 5
dvb-usb: found a 'WideView WT-220U PenType Receiver (Typhoon/Freecom)' in cold state, will try to load a firmware
dvb-usb: did not find the firmware file. (dvb-usb-wt220u-02.fw) Please see linux/Documentation/dvb/ for more details on firmware-problems. (-2)
Eine benötigte Firmwaredatei ist offensichtlich nicht vorhanden. Zwar enthält das Paket linux-firmware einige solcher Dateien, die hier gesuchte ist jedoch nicht dabei. Sie ist mit einer Suchmaschine schnell gefunden und wird im (ggf. zu erstellenden) Verzeichnis /lib/firmware/ gespeichert. Nach erneutem Anschluss des Sticks vermeldet dmesg
dvb-usb: found a 'WideView WT-220U PenType Receiver (Typhoon/Freecom)' in warm state.
dvb-usb: will use the device's hardware PID filter (table count: 15).
DVB: registering new adapter (WideView WT-220U PenType Receiver (Typhoon/Freecom))
DVB: registering adapter 0 frontend 0 (WideView USB DVB-T)...
input: IR-receiver inside an USB DVB receiver as /devices/platform/orion-ehci.0/usb1/1-1/1-1.4/input/input0
Um die hiesigen TV-Sender zu ermitteln, lässt sich scan aus dem Paket linuxtv-dvb-apps einsetzen.
[root@alarm ~]# scan /usr/share/dvb/dvb-t/de-Bundesland > channels.conf
Die im Paket enthaltenen Frequenzdateien sind u.U. nicht aktuell, ggf. findet man eine aktuellere Version hier. Alternativ kann man auch w_scan einsetzen, das ohne Frequenzdateien auskommt.
Die linuxtv-dvb-apps bieten auch eine primitive Möglichkeit der Aufnahme von Sendungen, dazu wird zunächst mit tzap im Hintergrund (z.B. via screen) ein Sender eingestellt
[root@alarm ~]# tzap -c channels.conf -r ZDF
Den Datenstrom leitet man dann einfach in eine Datei
[root@alarm ~]# cat /dev/dvb/adapter0/dvr0 > recording.ts
Komfortabler geht es mit dem VDR, mehr dazu in Abschnitt 8.
Wie die Ausgabe von dmesg in Abschnitt 7.2 zeigt, besitzt der Stick einen Infrarot-Empfänger. In /proc/bus/input/devices wird er als Eingabegerät (HID) aufgeführt:
I: Bus=0003 Vendor=14aa Product=0221 Version=0602
N: Name="IR-receiver inside an USB DVB receiver"
H: Handlers=kbd event0
Folglich stehen die Chancen gut, dass sich die Fernbedienung mit dem devinput-Treiber von LIRC in Betrieb nehmen lässt. Die benötigte Konfigurationsdatei ist im dem Paket lirc-utils enthalten, muss aber noch an die richtige Stelle kopiert werden.
[root@alarm ~]# cp /usr/share/lirc/remotes/devinput/lircd.conf.devinput /etc/lirc/lircd.conf
Das Paket lirc-utils deckt eine Vielzahl von Fernbedienungen ab und setzt deshalb weitere Pakete voraus, die eigentlich nicht benötigt werden. Zur Kompilierzeit lässt sich LIRC aber durchaus auf einen einzelnen Treiber beschränken. Ich habe das PKGBUILD aus dem ABS entsprechend angepasst, /etc/lirc/lircd.conf ist in dem Paket dann bereits integriert.
Zur Konfiguration wird noch das Device des IR-Empfängers benötigt, gemäß obiger Ausgabe ist dies /dev/input/event0, langfristig wird man aber einen von udev erzeugten eindeutigen Link auf das Device nutzen wollen:
#/etc/udev/rules.d/99-lirc.rules
SUBSYSTEM=="input", ATTRS{idVendor}=="14aa", ATTRS{idProduct}=="0221", SYMLINK="input/ir"
Mit udevadm trigger --subsystem-match=input wird der gewünschte Symlink erzeugt. LIRC-Device und -Treiber sind in der Konfigurationsdatei einzutragen
#/etc/conf.d/lircd.conf
LIRC_DEVICE="/dev/input/ir"
LIRC_DRIVER="devinput"
Nach Start des LIRC-Daemons findet man mit irw die Tastencodes heraus. In einer lircrc-Datei können sie bestimmten Aktionen zuordnet7 werden.
[root@alarm ~]# /etc/rc.d/lircd start
[root@alarm ~]# irw
0000000080010074 00 KEY_POWER devinput
Die Codes lassen sich auch - unabhängig von LIRC - mit evtest ermitteln. Im Gegensatz zu irw listet es zunächst sämtliche Codes auf, die der IR-Empfänger erzeugen kann. U.U. sind dies mehr als die mitgelieferte Fernbedienung auszulösen vermag.
Fertige PKGBUILDs für die aktuelle (Developer-)Version des VDR und eine Vielzahl an Plugins findet man im svn Repository des archvdr-Projekts. Diese sind jedoch relativ komplex und ziehen z.T. weit reichende Paketabhängigkeiten nach sich, um Funktionen zu realisieren, die auf dem DockStar nicht ohne weiteres genutzt werden können. Ich habe deshalb eigene, auf den gegebenen Einsatzzweck abgestimmte Pakete erstellt.
Fürs erste genügt es, lediglich den VDR ohne weitere Plugins zu installieren. Auch die bereits integrierten Plugins werden nicht benötigt. Der Liemikuutio-Patch ermöglicht ein Umbenennen von Aufnahmen, ein weiterer Patch behebt ein Problem mit dem EPG Scan in Version 1.7.27.
In der Konfigurationsdatei /etc/conf.d/vdr sind die zu verwendenden Plugins (Abschnitt 8.3) und ggf. weitere Optionen einzutragen (siehe man vdr), nötigenfalls auch die Funktionen zum (Ent-)Laden der DVB-Treiber zu implementieren. Um VDR mit eingeschränkten Nutzerrechten zu betreiben und die regelmäßige Abspeicherung der EPG-Daten zu unterbinden8, habe ich folgende Optionen hinzugefügt:
#/etc/conf.d/vdr
VDROPTIONS='... -E- -u vdr'
Soll VDR über eine am DockStar angeschlossene Fernbedienung gesteuert werden, fügt man noch die Option --lirc hinzu und erstellt im Verzeichnis /etc/vdr/ eine Datei remote.conf. Die Keycodes (zweite Spalte) müssen ggf. angepasst werden, vgl. Abschnitt 7.4.
Der User vdr muss noch angelegt werden. Als Mitglied der Gruppe video erhält er Zugriff auf die DVB-Devices unter /dev/dvb/adapter0/. Des weiteren benötigt er Schreibrechte auf die Konfigurationsdateien unter /etc/vdr.
[root@alarm ~]# useradd -m -G video -s /bin/bash vdr
[root@alarm ~]# chown -R vdr.vdr /etc/vdr
VDR legt Aufnahmen per Voreinstellung unter /video ab. Vorerst hängen wir dort das Homeverzeichnis des Users vdr ein. Dieser besitzt dort bereits die benötigten Schreibrechte. Zusätzlich erhalten andere Nutzer Lesezugriff.
[root@alarm ~]# chmod a+rx /home/vdr/
[root@alarm ~]# mkdir /video && mount -o bind /home/vdr/ /video
Die mitgelieferte DVB-S Kanalliste kann mit den linuxtv-dvb-apps (Abschnitt 7.3) durch eine lokal gültige ersetzt werden.
[root@alarm ~]# scan -o vdr /usr/share/dvb/dvb-t/de-Bundesland > /etc/vdr/channels.conf
Damit VDR die Lokalisierung des Systems berücksichtigt, muss die Variable DAEMON_LOCALE auf 'yes' gesetzt sein.
#/etc/rc.conf
LOCALE="de_DE.UTF-8"
DAEMON_LOCALE="yes"
Anschließend wird VDR gestartet. Die Warnung aufgrund der fehlenden Fonts kann erst einmal ignoriert werden.
[root@alarm ~]# /etc/rc.d/vdr start
:: Starting vdr daemon [DONE]
[root@alarm ~]# vdr: no fonts available - OSD will not show any text!
Im Problemfall nützliche Logmeldungen des VDR erscheinen in /var/log/user.log. Zur ersten Kontaktaufnahme kann man svdrpsend einsetzen.
Das in Perl geschriebene Programm Vdradmin-AM bietet eine komfortable Möglichkeit zur Interaktion mit dem VDR per Webbrowser
Das im AUR verfügbare Paket habe ich wie folgt überarbeitet:
install.sh Script wird nicht für die Installation verwendet (also kein Patch nötig)tmpfs, Abschnitt 2.3)/videoNach dem Start des Daemons ist die Weboberfläche im lokalen Netz unter http://ip.adresse.des.dockstar:8001 erreichbar (Benutzername: vdradmin, Passwort: vdradmin).
[root@alarm ~]# rc.d start vdradmind
Im Menüpunkt Konfiguration kann man die wichtigsten Einstellungen vornehmen, zumindest das Passwort sollte geändert werden. Innerhalb eines angegebenen lokalen Netzes, z.B. 172.16.1.0/24, erlaubt vdradmind einen Zugang ohne Passwort. Die Einstellungen werden in /etc/vdradmin/vdradmind.conf gespeichert. Man muss die Datei evtl. auch manuell editieren, z.B. um den in SERVERPORT definierten Port (Voreinstellung: 8001), auf den der Daemon lauscht, zu ändern. Für etwaige Kommandozeilenoptionen ist eine Datei im conf.d-Verzeichnis vorgesehen.
#/etc/conf.d/vdradmind
VDRADMIND_OPTS="--ssl --log 4 -L /var/log/vdradmind.log"
Die in diesem Beispiel aktivierte Beschränkung auf HTTPS-Verbindungen empfiehlt sich, wenn VDRAdmin-AM übers Internet erreichbar sein soll. Dazu muss das Paket perl-io-socket-ssl installiert, ein Verzeichnis /etc/vdradmin/certs angelegt und darin Zertifikat und Schlüssel hinterlegt werden. Letzteres ist in der Manpage von vdradmind anhand eines Beispiels beschrieben.
Um zur Überbrückung von Werbung automatisch Schnittmarken setzen zu lassen, hat sich das das im AUR verfügbare Programm noad bewährt. Wird die Option --asd nicht benötigt (audio silence detection), kann man vor dem Paketbau im PKGBUILD ffmpeg aus der Liste der Abhängigkeiten (depends) herausnehmen und die configure-Option --with-ffmpeg entfernen. Die sonst unnötige Installation von ffmpeg würde samt weiterer Abhängigkeiten knapp 70 MB beanspruchen.
Damit das Programm schon während der Aufnahme seiner Tätigkeit nachkommen kann, lässt man es am besten direkt vom VDR starten. Dieser kennt für solche Zwecke die Option -r. Ein darüber angegebenes Script wird vor Aufnahmebeginn und nach der Aufnahme mit entsprechendem Parameter (before/after) aufgerufen.
#/etc/conf.d/vdr (fortgesetzt)
OPTIONS=" ... -r /usr/local/bin/vdrcmd.sh"
Der erste Parameter wird direkt weitergereicht, der zweite enthält das Aufnahmeverzeichnis, in dem noad auch die Datei marks, die die Schnittmarken enthält, ablegt.
#/usr/local/bin/vdrcmd.sh
#!/bin/bash
case "$1" in
before)
noad before --online=2 --comments "$2"
;;
esac
So aufgerufen, beginnt Noad seine Tätigkeit 60 Sekunden nach Aufnahmebeginn mit einem nice-Wert von 19.
Bei der Installation von Plugins werden unter /etc/vdr/plugins weitere Konfigurationsdateien angelegt. Die Zugriffsrechte müssen dann erneut angepasst werden, auch nach einem Update bereits installierter Plugins:
[root@alarm ~]# chown -R vdr.vdr /etc/vdr
Außerdem müssen die Plugins explizit aktiviert werden, ggf. mit eigenen Optionen:
#/etc/conf.d/vdr (fortgesetzt)
VDRPLUGINS='-Pepgsearch -Pstreamdev-server -P"xineliboutput --primary --local=none --remote=37890" -P"graphlcd -d ax206dpf"'
Mit dem Epgsearch-Plugin können Suchtimer erstellt werden. Aufnahmetimer werden dann automatisch angelegt, sobald ein passender Eintrag im EPG erscheint. Das Plugin informiert zudem per E-Mail über Timerkonflikte. Es wird auch von VDRAdmin-AM unterstützt.
Das Streamdev-Plugin stellt Live-TV als HTTP-Stream bereit, der z.B mit VLC oder MPlayer auf anderen Rechnern (Clients) im Netzwerk abgespielt werden kann. Auch Smartphones/Tablets können den Stream darstellen, auf Android-Geräten empfiehlt sich dafür VPlayer, der komfortabel aus AndroVDR heraus gestartet werden kann.
Auf dem DockStar wird nur das Streamdev-Server Plugin benötigt, das Streamdev-Client Plugin ist für andere Instanzen des VDR vorgesehen, die den Server als zusätzliche Empfangsquelle einbinden können.
Die IP-Adressen der Clients, die Zugriff auf den DockStar haben sollen, sind dort in der Datei streamdevhosts.conf im Unterverzeichnis des Plugins einzutragen. Dabei kann, wie in folgendem Beispiel, auch einfach das zugehörige Subnetz angegeben werden:
#/etc/vdr/plugins/streamdev-server/streamdevhosts.conf
172.16.1.0/24
Nach Aktivierung des Plugins findet man unter http://ip.adresse.des.dockstar:3000 ein spartanisches Interface mit URLs zu den verfügbaren Sendern. VDRAdmin-AM zeigt bei aktiviertem Plugin Links (m3u-Playlists) zu den Streams an.
Bei Bedarf kann der Stream on-the-fly in ein Format mit höherer Kompression umgewandelt werden, um trotz beschränkter Bandreite auch eine Übertragung via Internet zu realisieren, siehe Abschnitt 5 im README des Plugins.
Das Xineliboutput-Plugin generiert - ähnlich wie das Streamdev-Plugin - einen HTTP-Stream, erlaubt bei Verwendung spezieller Frontends wie vdr-sxfe aber auch eine Darstellung und Steuerung der kompletten Oberfläche des VDR samt OSD wie sie am TV-Ausgang einer DVB-Karte mit MPEG-Decoder erscheinen würde, so dass beispielsweise auch Einstellungen vorgenommen und Aufnahmen abgespielt werden können. VDRAdmin-AM unterstützt Xineliboutput seit Version 3.6.9.
Die Frontends sind normalerweise Bestandteile des Plugins. Da ein lokales Frontend auf dem DockStar mangels Monitorausgang nicht sinnvoll ist, habe ich dieses im Paket deaktiviert, die xine-lib wird daher nicht benötigt. Frontends (und folglich xine-lib) müssen nur auf den Clients installiert sein. Dazu lässt sich xineliboutput ggf. auch ohne VDR kompilieren:
Edit: Leider beendet sich vdr-sxfe bei einem ohne VDR kompiliertem Frontend seit geraumer Zeit mit einem Speicherzugriffsfehler.
Die Zugriffskontrolle erfolgt ähnlich wie beim Streamdev-Plugin.
#/etc/vdr/plugins/xineliboutput/allowed_hosts.conf
172.16.1.0/24
Um den VDR auf den Clients per Tastatur oder Fernbedienung9 steuern zu können, muss auf dem DockStar die Datei /etc/vdr/remote.conf angelegt bzw. erweitert werden. Für das OSD wird ferner ein Font benötigt, z.B. ttf-bitstream-vera. Auf einem Client startet man das Frontend beispielsweise mit
vdr-sxfe -A alsa -f --post tvtime:method=Linear,cheap_mode=1,pulldown=0,use_progressive_frame_flag=1 xvdr+tcp://ip.adresse.des.dockstar:37890
Mit dem Graphlcd-Plugin lassen sich EPG und Menü des VDR auf einem graphischen Display darstellen. Ich nutze dafür diesen beliebten digitalen Bilderrahmen (DPF) und folgende Pakete.
Eine in graphlcd-base enthaltene udev-Regel sorgt dafür, dass Mitglieder der Gruppe uucp Schreibrecht auf die Devicedateien des DPF erhalten, vdr ist folglich dieser Gruppe hinzuzufügen.
[root@alarm ~]# usermod -a -G uucp vdr
Der Bilderrahmen muss vor dem Einsatz gehackt und in den Developer-Modus gebracht werden. Letzerer aktiviert sich 10 Minuten nach dem Anschließen auch selbständig, das Display kann also problemlos vorübergehend getrennt werden (z.B. per schaltbarem USB-Hub), das graphlcd-plugin greift dann beizeiten wieder darauf zu, ohne dass der VDR neu gestartet werden muss.
Das Display kann auch unabhängig vom VDR via lcd4linux bzw. lcdproc als Statusdisplay oder Konsole dienen, Einzelheiten siehe z.B. hier.
Das Aufs-Dateisystem ermöglicht das gleichzeitige Einbinden mehrerer Verzeichnisse unter einem einzigen Mountpunkt. So lässt sich neben dem auf dem USB-Stick befindlichen Verzeichnis /home/vdr zusätzlich ein Verzeichnis auf der externen Festplatte als Aufnahmeverzeichnis nutzen. Im Gegensatz zur VDR-eigenen Lösung mit nummerierten Verzeichnissen erlaubt diese Vorgehensweise in gewissen Grenzen eine Steuerung dahingehend, auf welchem Datenträger die einzelnen Aufnahmen jeweils tatsächlich abgelegt werden. Bei nur einem Verzeichnis entspricht des Mounten mit Aufs im Ergebnis dem oben verwendeten mount --bind:
[root@alarm ~]# umount /video
[root@alarm ~]# mount -v -t aufs -o br:/home/vdr/ none /video/
none on /video type aufs (rw,relatime,si=eb4b663e)
Ein Verzeichnis auf der Festplatte wird nun einfach als weitere Schicht darüber gelegt10.
[root@alarm ~]# mkdir /hdd/video
[root@alarm ~]# chown vdr.vdr /hdd/video
[root@alarm ~]# mount -o remount,prepend:/hdd/video,xino=/hdd/video/.aufs.xino none /video/
Unter /video erscheinen jetzt die Inhalte von /hdd/video und /home/vdr gemeinsam, wobei ersteres als oberste Schicht (Branch) gleichlautende Dateien und Verzeichnisse des letzteren ggf. überdeckt. Die aktuelle Zusammensetzung des Aufs-Verbundes kann man aus dem sys-Verzeichnis auslesen:
[root@alarm]# cat /sys/fs/aufs/si_eb4b663e/br[01]
/hdd/video=rw
/home/vdr=rw
Neue (Aufnahme)-Verzeichnisse werden stets auf der obersten beschreibbaren Schicht br0, hier nun also unter /hdd/video, angelegt11. Beide Branches sind schreibbar eingebunden, damit z.B. auch bestehende Aufnahmen auf dem USB-Stick per Webfrontend gelöscht werden können. Beim gleichzeitigen Mounten mehrerer Verzeichnisse ist per Voreinstellung nur die oberste Schicht beschreibbar, der den obigen Befehlen entsprechende fstab Eintrag erfordert deshalb die Angabe der rw-Option:
#/etc/fstab (fortgesetzt)
none /video aufs br:/hdd/video=rw:/home/vdr=rw 0 0
Sollen auf der Festplatte vorerst keine weiteren Aufnahmen gespeichert werden, damit diese in absehbarer Zeit in den Standby geht und verbleibt, kann man das Verzeichnis /hdd/video aus dem Aufs-Verbund wieder entfernen. Letzteres ist jedoch nicht möglich, wenn momentan (via Aufs) auf das Verzeichnis zugegriffen wird, z.B. weil gerade eine Aufnahme angefertigt wird. In diesem Fall kann man die Branches aber vertauschen. Eine entsprechende Option kennt aufs leider (noch?) nicht, man muss stattdessen den unteren Branch entfernen und als oberen Branch wieder einbinden.
[root@alarm ~]# mount -o remount,del:/home/vdr,prepend:/home/vdr=rw,xino=/home/vdr/.aufs.xino none /video
Die ggf. laufende Aufnahmen wird nun weiterhin unter /hdd/video gespeichert, die nächsten hingegen unter /home/vdr angefertigt. Überschneiden sich die Aufnahmen zeitlich (gleiches Bouquet oder Twin-Receiver), wird also auf beide Datenträger gleichzeitig geschrieben. Sind die Aufnahmen auf der Festplatte abgeschlossen, kann diese schließlich aus dem Verbund genommen werden:
[root@alarm ~]# mount -o remount,del:/hdd/video/,xino=/home/vdr/.aufs.xino none /video
Die ursprüngliche Reihenfolge wird dann später wieder durch Hinzufügen von /hdd/video als oberstem Branch (prepend) erreicht. Für die nötigen Schritte nutze ich ein Script aufs_switch.sh, das auch die LED dem Status entsprechend anpasst12. Letzteres erfolgt unter Zuhilfenahmen des C-Programms aus Abschnitt 4.1. Der optional zu übergebende Parameter des Scriptes impliziert die gewünschte Anzahl und Rangfolge der Branches:
| Status | –2 | –1 | 0 | 1 | 2 |
|---|---|---|---|---|---|
| br0 | /home/vdr | /home/vdr | - | /hdd/video | /hdd/video |
| br1 | /hdd/video | - | - | - | /home/vdr |
| LED | abwechselnd | grün | grün heartbeat | orange blinkend | orange |
Bei erfolgreichen Statuswechsel liefert das Script den Rückgabewert 0, andernfalls 1, den aktuellen Status gibt es auf /dev/stdout aus. Das Script wird per cron aufgerufen, hier meine derzeitigen (mit crontab -e) vorgenommenen Einträge:
@reboot /usr/local/bin/aufs_switch.sh
0 21 * * * /usr/local/bin/aufs_switch.sh -1 || /usr/local/bin/aufs_switch.sh -2
0 0 * * * /usr/local/bin/aufs_switch.sh -1
0 9 * * * /usr/local/bin/aufs_switch.sh 2
Die erste Zeile sorgt lediglich für eine Anpassung der LED. Lässt sich /hdd/video um 21 Uhr nicht aushängen (üblicherweise wegen einer laufenden Aufnahme), werden die Branches zunächst getauscht (–2). Um Mitternacht wird der beabsichtigte Zustand (–1) ggf. erneut in die Wege geleitet, zusätzlich aber auch schon direkt nach der Aufnahme: Dies lässt sich durch Erweiterung des in Abschnitt 8.2.2 angelegten Scriptes realisieren.
#/usr/local/bin/vdrcmd.sh (erweitert)
#!/bin/bash
case "$1" in
before)
noad before --online=2 --comments "$2"
;;
after)
h=$(date +%k)
if [ $h -ge 21 -o $h -lt 9 ]; then
if [ -e $2/noad.pid ]; then
screen -dm bash -c "inotifywait -e delete $2/noad.pid ; $0 $@"
else
sudo /usr/local/bin/aufs_switch.sh -1
fi
fi
;;
esac
Das Script wird mit den Rechten des Users vdr ausgeführt, der Aufruf von aufs_switch.sh erfordert aber Rootrechte und erfolgt daher via sudo. Der zugehörige Eintrag in /etc/sudoers wird mit visudo angelegt:
vdr ALL=NOPASSWD: /usr/local/bin/aufs_switch.sh
Neben der Uhrzeit überprüft das Script vor Aufruf von aufs_switch.sh, ob im Aufnahmeverzeichnis eine Datei noad.pid existiert. Ist dies der Fall, greift noad noch auf den Branch zu, ein Aushängen würde also fehlschlagen. Das Script startet dann einen Hintergrundprozesses, der das Script mit denselben Parametern erneut aufruft, sobald die pid-Datei entfernt wurde. Zu diesem Zweck müssen die Pakete screen und inotify-tools installiert sein.13
Die Aufnahmen sollen im lokalen Netzwerk zur Weiterverarbeitung (ggf. demultiplexen, Schnitt) verfügbar sein. Die Einrichtung des NFSv4-Servers ist im Wiki ausführlich erklärt. Es wäre möglich die beiden Verzeichnisse separat per NFS freizugeben, man kann aber auch den Aufs-Mountpunkt /video insgesamt zur Verfügung stellen. Bei entsprechend dimensionierter Festplatte wird man gewiss auch weitere darauf befindliche Verzeichnisse freigeben wollen, nachfolgend als Beispiel /hdd/share. Die Freigaben werden zunächst an Verzeichnisse unter /export/ gebunden
#/etc/fstab (fortgesetzt)
/hdd/share /export/share none bind 0 0
/video /export/video none bind 0 0
und per /etc/exports konfiguriert. Da das Aufs-Dateisystem keine UUID besitzt, muss zur Identifizierung eine id>0 zugeordnet werden.
#/etc/exports
/export 172.16.1.0/24(rw,no_subtree_check,async,no_root_squash,fsid=0)
/export/share 172.16.1.0/24(rw,no_subtree_check,async,no_root_squash,nohide)
/export/video 172.16.1.0/24(rw,no_subtree_check,async,no_root_squash,nohide,fsid=1)
Danach kann der NFS-Server gestartet werden. Damit dies automatisch beim Booten geschieht, wird er schließlich, wie alle oben erwähnten Daemons, in /etc/rc.conf eingetragen:
#/etc/rc.conf
DAEMONS=(syslog-ng network openntpd sshd !netfs compcache crond vdr rpcbind nfs-common nfs-server lircd irexecd vdradmind)
Edit: In util-linux 2.20–2 gab es einen Bug, der das Exportieren verschiedener Dateisysteme, einschließlich Aufs, verunmöglicht. Der Fehler ist in Version 2.20–3 behoben.
Olaf Bauer <obauer (at) freenet (dot) de>
In den aufgeführten Verzeichnissen befinden sich evtl. von einigen Programmen benötigte Unterverzeichnisse, die (von diesen Programmen) nach einem Reboot u.U. nicht erneut angelegt werden. Auch stehen die Logdateien ohne weitere Vorkehrungen nach einem Absturz nicht mehr zur Fehlersuche zur Verfügung.
Die Gesamtgröße der Logdateien (und also der RAM-Bedarf) lässt sich durch geeignete Einstellungen in /etc/logrotate.conf reduzieren. Evtl. lohnt auch eine Modifizierung von /etc/syslog-ng/syslog-ng.conf. Ratsam ist in diesem Zusammenhang auch eine Änderung des SSH-Ports in /etc/ssh/sshd_config auf einen Wert oberhalb von 1024. Andernfalls wird /var/log/auth.log und evtl. /var/log/btmp bald vor Hinweisen auf fehlgeschlagene Login-Versuche bersten. Wohlgemerkt bringt diese Maßnahme keine Sicherheit, sie hält lediglich die Logdateien klein, spart beim Einsatz von tmpfs also wertvollen RAM.
Falls erforderlich, lässt sich eine Sicherung der Logdateien vor und Wiederherstellung nach dem Reboot leicht mit ramlog realisieren. Das zugehörige Script übernimmt auch das Einrichten des temporären Dateisystems, der Eintrag für /var/log muss beim Einsatz von ramlog also aus /etc/fstab entfernt werden. Die Kopien der Logdateien werden unter /var/log.hdd abgelegt. ramlog versucht per Cronjob auch eine tägliche Abgleichung im laufenden Betrieb vorzunehmen, die jedoch regelmäßig fehlschlägt, da die Logdateien von den laufenden Daemons zum Schreiben geöffnet sind. Ich habe deshalb den Programmaufruf in /etc/cron.daily/ramlog auskommentiert. ↩
Man sollte also vor Aufruf von makepkg sämtliche Hardware, die man nutzen möchte, anschließen (ggf. nacheinander) und in Betrieb nehmen, sowie Programme und Daemons starten, die auf Kernelmodule angewiesen sind (z.B. der NFS Server). Möchte man diese Funktion nicht nutzen, kann man make localmodconfig auch auskommentieren. Das Abfragen neuer Optionen erfolgt dann über make prepare. ↩
Eine andere Möglichkeit den zu bootenen Kernel festzulegen, besteht darin die uBoot Umgebungsvariablen usb_scan und usb_boot anzupassen (Abschnitt 3.2). Ich habe dazu ein Script fw_setuimage erstellt, das als optionalen Parameter den Suffix des Kernelimages erwartet:
[root@alarm ~]# fw_setuimage custom
Ohne Parameter werden die Variablen zurückgesetzt. Das Script benötigt die Programme fw_printenv und fw_setenv, aus dem uBoot environment von Jeff Doozan, siehe Abschnitt 6. ↩
Nachdem ich jüngst eine der speziell für den Betrieb am oberen USB-Anschluss der DockStar vorgesehenen 2,5" Festplatten “FreeAgent Go” erworben hatte, musste ich mittels Netzkonsole festellen, dass diese von uBoot nicht zuverlässig erkannt wurde: War beispielsweise neben der Festplatte nur der USB-Stick angeschlossen, wurde dieser von uBoot als erstes/einziges Device erkannt und gemäß Abschnitt 3.2 folglich sda2 als Rootpartition übermittelt. Aus Kernelsicht stellte sda jedoch die Festplatte dar, so dass der Bootvorgang nicht fortgesetzt werden konnte. ↩
Es schadet nichts das Dateisystems zunächst stärker zu verkleinern. Nach Verkürzen der Partition mit resize2fs kann es automatisch auf die dann maximale Größe erweitert werden. Bei der beschriebenen Vorgehensweise erübrigt sich dies:
[root@linux ~]# resize2fs /dev/sdx3
resize2fs 1.41.14 (22-Dec-2010)
Das Dateisystem ist schon 3590907 Blöcke groß. Nichts zu tun!
↩Hat man keinen Linux-PC zur Verfügung, kann man auch Hersteller- und Produkt-ID als Anhaltspunkte nehmen:
[user@alarm linux-2.6.37]$ lsusb
Bus 001 Device 006: ID 14aa:0222 WideView Technology Inc.
Die dvb-Treiber befinden sich im Unterverzeichnis drivers/media/dvb/dvb-usb/. In dvb-usb-ids.h werden den IDs symbolische Namen zugeordnet:
[user@alarm linux-2.6.37]$ cd drivers/media/dvb/dvb-usb
[user@alarm dvb-usb]$ grep -i -E "14aa|0222" dvb-usb-ids.h
#define USB_VID_WIDEVIEW 0x14aa
#define USB_PID_WT220U_COLD 0x0222
#define USB_PID_PCTV_450E 0x0222
Nun sucht man nach einer Datei, die den symbolischen Namen des Herstellers und eines der Produkte innerhalb einer Zeile enthält
[user@alarm dvb-usb]$ grep -E "USB_VID_WIDEVIEW.*(USB_PID_WT220U_COLD|USB_PID_PCTV_450E)" *
dtt200u.c: { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD) },
und wiederum im Makefile nach dieser Datei (ohne Endung). Die Ausgabe beinhaltet die gesuchte CONFIG-Variable.
[user@alarm dvb-usb]$ grep dtt200u Makefile
dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
↩Beispielsweise könnte der Power-Knopf genutzt werden, um via irexec einen anderen Rechner per Wake-on-LAN zu booten:
#/etc/lirc/lircrc
begin
button = KEY_POWER
prog = irexec
repeat = 0
config = wol 00:11:22:33:44:55
end
Diese Datei ist noch in der Konfiguration von irexec anzugeben
#/etc/conf.d/irexec.conf
IREXEC_OPTS="/etc/lirc/lircrc"
bevor der zugehörige Daemon gestartet wird
[root@alarm ~]# /etc/rc.d/irexecd start
↩Per Voreinstellung speichert VDR die EPG-Daten alle 30 Minuten in /video/epg.data. Diese Datei wird von VDR selbst nicht benötigt und ihre regelmäßige Aktualisierung würde den USB-Stick nur unnötig belasten bzw. die Festplatte regelmäßig wecken. Fehlt die Datei, stehen allerdings die EPG-Daten nach einem Neustart des VDR (der z.B. dann erforderlich ist, wenn man ein Plugin ausprobieren möchte) nicht sofort wieder zur Verfügung. Als Kompromiss kann man die Datei in den RAM verlegen (siehe Abschnitt 2.3):
#/etc/conf.d/vdr
VDROPTIONS='... -E /tmp ...'
Um die Datei /tmp/epg.data auch über einen Reboot hinaus zu bewahren, verwende ich einen custom hook, der sie beim Herunterfahren unter /home/vdr/epg.data sichert und beim Booten wiederherstellt:
#/etc/rc.d/functions.d/epg_save
epg_save() {
[ -e /tmp/epg.data ] && install -o vdr -g vdr -m 644 -t /home/vdr/ /tmp/epg.data
}
epg_restore() {
[ -e /home/vdr/epg.data ] && install -o vdr -g vdr -m 644 -p -t /tmp /home/vdr/epg.data
}
add_hook shutdown_postkillall epg_save
add_hook multi_start epg_restore
↩Zur Steuerung des VDR über einen am Client angeschlossenen IR-Empfänger sind in remote.conf die auf dem Client(!) ausgelösten Keycodes einzutragen. LIRC muss auf dem Client eingerichtet und gestartet sein. Außerdem ist dem Aufruf von vdr-sxfe die Option --lirc hinzuzufügen. ↩
Die Verlagerung der von Aufs intern zur Inode-Verwaltung genutzen xino-Datei muss jeweils explizit angegeben werden. Andernfalls würde diese Datei je nach Anfangsstatus permanent auf einem der beiden Datenträger verbleiben und folglich den USB-Stick auch dann mit Schreibvorgängen belasten, wenn die Festplatte verfügbar ist, bzw. die Festplatte auch dann in Rotation versetzen, wenn für Aufnahmen lediglich der USB-Stick vorgesehen ist. Die eigentlich überflüssige Angabe none soll einer Verwechslung mit dem letzten Eintrag in /etc/fstab (Abschnitt 8.5) vorbeugen. ↩
Genauer gesagt werden - gemäß der Default Policy von Aufs bei mehreren beschreibbaren Branches - neue Dateien und Verzeichnisse stets in dem höchsten Branch, in dem sich das zugehörige Unterverzeichnis befindet, geschrieben: Existiert also auf br1 bereits eine dem Titel der anzufertigenden Aufnahme entsprechendes Verzeichnis, unter br0 jedoch nicht, so wird diese Aufnahme auf br1 gespeichert. Dieser Fall kann leicht bei Wiederholungen und Serien eintreten. ↩
Zudem stellt das Script sicher, dass die Aufnahmen tatsächlich auf br0 angefertigt werden. Dazu legt es vor einer Rotation der Verzeichnisse auf dem unteren bzw. nicht eingebundenen Branch zunächst sämtliche Aufnahmeverzeichnisse des oberen Branches als leere Verzeichnisse an. Leere Verzeichnisse aus vorherigen Aktionen sowie Whiteout-Dateien werden entfernt. Letztere entstehen beim Löschen von (Aufnahme-)Verzeichnissen, die in beiden Branches existieren. ↩
Im Zusammenhang mit Aufs gibt es noch ein ungelöstes Problem: Weist man VDR an, eine Aufnahme zu löschen, markiert er diese zunächst nur als gelöscht, um sie erst später, wenn keine Aufnahme läuft, tatsächlich zu entfernen. Ist zu diesem Zeitpunkt der Branch, auf dem die Aufnahme liegt, nicht eingebunden, schlägt der Löschvorgang fehl und wird nicht wiederholt, die Aufnahme beansprucht also weiterhin unbemerkt Speicherplatz und muss manuell gelöscht werden. ↩