UDEV-Regel: Daten von USB-Stick kopieren

L I V E Stammtisch ab 20:30 Uhr im Chat
  • In deinem Script oben, warum einmal mit at now, einmal ohne?

    Code
    echo mount /dev/disk/by-label/$ID_FS_LABEL /media/pi/$ID_FS_LABEL
    echo mount /dev/disk/by-label/$ID_FS_LABEL /media/pi/$ID_FS_LABEL | at now

    Auch kritisch ist, dass du in einem Script ein weiteres Script aufrufst. Das ganze über udev ist nicht robust und du läufst in merkwürdige Fehler, wie du aktuell siehst. Versuch's lieber über eine systemd-unit. Du kannst dir auch ganz schnell dein System mit dem herumgefrickel zerlegen.

    Wenn du jetzt abschließend noch (unsauber) lösen möchtest, versuche mal alles in ein Script zu packen.

    “Don’t comment bad code - rewrite it.”

    Brian Kernighan

  • Um die Scripte geht es mir noch gar nicht. Ich möchte zunächst, dass überhaupt ein Script beim Einstecken ausgeführt wird. Selbst ein Script mit "echo test" wird nicht gestartet. Bisher bin ich noch keinen Schritt weiter. Die systemd-unit muss ich mir erst ansehen. Für andere Lösungsvorschläge bin ich aber weiterhin dankbar.

  • Wenn Du den User pi automatisch anmeldest und automatisch ins Grafiksystem bootest, wird jeder angesteckte Stick (nur) für den User pi für jedes Filesystem unter seinem Label (in Ermangelung eines Labels unter der UUID) automatisch gemounted.

    Das (automatische Einbinden) lässt sich in der Datenträgerverwaltung des Dateibrowsers deaktivieren.

    Servus !

    RTFM = Read The Factory Manual, oder so

  • Um die Scripte geht es mir noch gar nicht. Ich möchte zunächst, dass überhaupt ein Script beim Einstecken ausgeführt wird. Selbst ein Script mit "echo test" wird nicht gestartet.

    Du hast doch ein paar Beiträge vorher selbst geschrieben dass udev in ein timeout läuft, siehe logzeile. Die Regel greift, das Skript wird ausgeführt, blockiert aber und läuft in ein timeout.

    Ergänzung: du willst mit `at now` was erreichen, wenn du eine Zeile drüber udev offensichtlich nicht bewahrst dass die Routine blockiert?

    “Don’t comment bad code - rewrite it.”

    Brian Kernighan

  • Wenn Du den User pi automatisch anmeldest und automatisch ins Grafiksystem bootest, wird jeder angesteckte Stick (nur) für den User pi für jedes Filesystem unter seinem Label (in Ermangelung eines Labels unter der UUID) automatisch gemounted.

    Das (automatische Einbinden) lässt sich in der Datenträgerverwaltung des Dateibrowsers deaktivieren.

    Servus !

    Ok, das ist ein hilfreicher Hinweis. Sollte ich das automatische Mounten deaktivieren? Warum?

    Einmal editiert, zuletzt von Gismor1212 (16. Dezember 2022 um 14:32)

  • Du hast doch ein paar Beiträge vorher selbst geschrieben dass udev in ein timeout läuft, siehe logzeile. Die Regel greift, das Skript wird ausgeführt, blockiert aber und läuft in ein timeout.

    Ergänzung: du willst mit `at now` was erreichen, wenn du eine Zeile drüber udev offensichtlich nicht bewahrst dass die Routine blockiert?

    Das verstehe ich nicht ganz. Liegt es am Script, dass die Ausführung nicht gelngt, oder an der rules, die das Script nicht ausführen kann? Es muss die Regel sein, da das unabhängig aufgerufen läuft.

    Kannst du deinen letzten Satz näher erläutern?

  • Sollte ich automatische Mounten deaktivieren? Warum?

    Weil automount genau dort schon den angesteckten Stick (richtig: dessen Filesystem/e ) gemounted hat und ein zweiter mount mit demselben LABEL auf denselben Mountpoint (/media/pi ) nicht möglich ist.

    Wenn Du nicht einmal zum Testen auf den automount verzichten kannst, dann nimm zumindest einen anderen Mountpoint. [z.B. /mnt, oder /mnt/mycopy]

    Servus !

    RTFM = Read The Factory Manual, oder so

  • dass überhaupt ein Script beim Einstecken ausgeführt wird.

    In der ubuntuusers udev-Doku war eine Beschreibung, wie ein Skript beim Stecken eines USB-Sticks aufgerufen wird. Nur der mount funktionierte nicht, mkdir schon.

    • Skript muss ausführbar sein
    • Skript braucht shebang
    • Benutze logger um Ausgaben in /var/log/syslog zu hinterlassen.

    Schönen Gruß, kle

  • Liegt es am Script, dass die Ausführung nicht gelngt, oder an der rules, die das Script nicht ausführen kann? Es muss die Regel sein, da das unabhängig aufgerufen läuft.

    udev erkennt das Event dass du einen USB-Stick, oder was auch immer, einsteckst, und führt dann dein Bash-Skript aus. Das siehst du im logfile. Die logzeile verrät dir aber auch, dass udev in ein Timeout läuft, weil irgendwas in deinem Bashskript nicht funktioniert, oder zu lange brauch um eine Rückmeldung an udev zu geben. Das ist wichtig, da udev sonst für immer blockiert und alle weiteren Aktionen nicht mehr ausführen kann.

    Warum dein Bash-Skript nun nicht funktioniert, kann verschiedene Gründe haben. Zum einen sollte man blockierende Operationen nicht mit udev ausführen. Das kann man in der Shell umgehen, indem man Prozesse im Hintergrund ausführen lässt. Üblicherweise macht man das mit einem &-Zeichen hinter dem Befehl, z.b.:

    Code
    ping google.com &

    Hier werden zwar die einzelnen Antworten auf der Kommandozeile angezeigt, du könntest aber beliebige andere Prozesse in der selben Shell ausführen, was ohne dem &-Zeichen nicht ginge.

    Für Raspbian* gibt es noch das at-Package. Das macht wohl etwas ähnliches, und du verwendest es ja in deinem ersten Skript "start_move_usb_data.sh":

    Bash
    #!/bin/bash
    echo $0: $ID_FS_LABEL>>/tmp/script.log
    if [ -z "$ID_FS_LABEL" ]
    then
    exit 0
    fi 
    mkdir -p /media/pi/$ID_FS_LABEL
    echo mount /dev/disk/by-label/$ID_FS_LABEL /media/pi/$ID_FS_LABEL
    echo mount /dev/disk/by-label/$ID_FS_LABEL /media/pi/$ID_FS_LABEL | at now
    echo /home/pi/data/move-usb-data.sh $ID_FS_LABEL | at now

    Hier jeweils in Zeile 9 und 10. In Zeile 8 machst du das gleiche wie in Zeile 9 jedoch blockierend! Macht keinen Sinn.

    Der erste Schritt ist also, bevor du irgendwas anderes herumprobierst, Zeile 8 loszuwerden:

    Bash
    #!/bin/bash
    echo $0: $ID_FS_LABEL>>/tmp/script.log
    if [ -z "$ID_FS_LABEL" ]
    then
    exit 0
    fi 
    mkdir -p /media/pi/$ID_FS_LABEL
    echo mount /dev/disk/by-label/$ID_FS_LABEL /media/pi/$ID_FS_LABEL | at now
    echo /home/pi/data/move-usb-data.sh $ID_FS_LABEL | at now

    Wenn du das Skript modifiziert hast, starte dein System direkt mal durch. In POSIX soll das zwar alles immer out-of-the-box funktionieren, ich würde mich aber bei diesen ganzen schrottigen Derivaten nicht darauf verlassen :)

    Anschließend sehen wir weiter.

    “Don’t comment bad code - rewrite it.”

    Brian Kernighan

  • Um die Scripte geht es mir noch gar nicht. Ich möchte zunächst, dass überhaupt ein Script beim Einstecken ausgeführt wird.

    Gefunden mit Forensuche: Alles - udev kopieren

    Gestohlen aus RE: Autocopy/ AutoClone

    /etc/udev/rules.d/99-test1.rules [root root 0755]:

    ACTION=="add",KERNEL=="sd[a-g][0-9]",SUBSYSTEMS=="block",RUN+="/usr/local/bin/test1"

    ACTION=="remove",KERNEL=="sd[a-g][0-9]",SUBSYSTEMS=="block",RUN+="/usr/local/bin/test2"

    Servus !

    RTFM = Read The Factory Manual, oder so

  • Danke für die Ausführung. Habe deinen Rat befolgt, konnte aber keine Veränderung feststellen.

    Ich habe die Rechte der Scripte neu gesetzt und konnte nun zumindest erreichen, dass ein Script "Test" in eine Logfile schreibt, sobald ein USB-Stick eingesteckt wird. Die Udev-Regel funktioniert also. $ID_FS_LABEL, bzw. $1 werden in den Scripten aber allen Anschein nach nicht zugeordnet. Hier nochmal Tipps?

  • Ich habe die Rechte der Scripte neu gesetzt und konnte nun zumindest erreichen, dass ein Script "Test" in eine Logfile schreibt, sobald ein USB-Stick eingesteckt wird. Die Udev-Regel funktioniert also. $ID_FS_LABEL, bzw. $1 werden in den Scripten aber allen Anschein nach nicht zugeordnet. Hier nochmal Tipps?

    Kannst du mal folgendes testen:

    Code
    udevadm monitor --env

    Wenn du den USB-Stick einsteckst, sollten hier nun sämtliche Label erscheinen. Wird ID_FS_LABEL hier auch angezeigt?

    ERGÄNZUNG: das Problem ist, dass du das ID_FS_LABEL über die udev-Regel nicht an dein Bash-Skript weiterreichst.

    Hier hatte ich ja gezeigt, wie man das in der udev-Regel macht:

    Code
    ACTION=="add", RUN+="/etc/udev/scripts/start-move-usb-data.sh '%E{ID_FS_LABEL}'"

    start-move-usb-data.sh muss diesen Übergabeparameter dann natürlich setzen:

    Bash
    #!/bin/bash
    ID_FS_LABEL=$1
    echo $0: $ID_FS_LABEL>>/tmp/script.log
    [...]

    “Don’t comment bad code - rewrite it.”

    Brian Kernighan

    Einmal editiert, zuletzt von sls (19. Dezember 2022 um 13:20)

  • Wieso muss $1 deklariert werden, $0 hingegen nicht?

    Weil:

    -> $0 der Name deiner Bash-Datei ist

    -> $1 der Name des ersten Übergabeparameters an das Skript ist

    Beispiel:

    Bash: parameter_uebergabe.sh
    #!/bin/bash
    echo 0: $0
    echo 1: $1

    ./parameter_uebergabe.sh

    0: parameter_uebergabe.sh

    1:

    ./parameter_uebergabe.sh abcd

    0: parameter_uebergabe.sh

    1: abcd

    “Don’t comment bad code - rewrite it.”

    Brian Kernighan

  • Nur zur Sicherheit: zeig mal bitte den Inhalt der udev-Regel und des modifizierten Bashskripts.

    Hast du auch parallel mal weiter mit journalctl -f geprüft, was udev so macht?

    “Don’t comment bad code - rewrite it.”

    Brian Kernighan

  • Code
    KERNEL!="sd[a-z]*", GOTO="script_end"
    ACTION=="add", PROGRAM!="/sbin/blkid %N", GOTO="script_end"
    ACTION=="add", RUN+="/etc/udev/scripts/start-move-usb-data.sh '%E{ID_FS_UUID}'"
    LABEL="script_end"

    journalctl -f gibt einen Fehler für die dritte Zeile der Regel aus: Invalid key/value pair

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!