Netzwerkfreigabe mounten mit systemd Mount Unit

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Einleitung / Ziel

    Die folgende Anleitung soll eine Hilfestellung geben, wie ein Netzlaufwerk mit dem Raspberry Pi erfolgreich gemountet werden kann.

    Es handelt sich beispielhaft um eine Samba Netzwerkfreigabe die von einer Fritz!Box bereitgestellt wird.

    Ein möglicher Weg führt über einen Eintrag in der Datei /etc/fstab. Da ich oft Probleme, mit zur Bootzeit noch nicht erreichbaren Freigaben im Netz, hatte und sich diese auch nicht mit Parametern wie _netdev lösen ließen, beschreibe ich hier jedoch den Weg mit einer Systemd Mount Unit. Auf aktuellen Systemen werden im Hintergrund die Einträge in der Datei /etc/fstab automatisch in eine Mount Unit gewandelt.

    Der schnelle Weg

    Um die wiederkehrende Arbeit zur Einrichtung zu erleichtern, habe ich ein kleines Hilfsskript erstellt.

    https://github.com/Hofei90/create_automount

    Hier kann man sich auch eine Konfigurationsdatei erstellen lassen, um bei einer zukünftigen Erstellung alles automatisiert erstellen lassen zu können. Praktisch bei einer erneuten Einrichtung oder wiederholten Einrichtung, wenn mehrere Raspberry Pi auf die Netzwerkfreigabe zugreifen sollen.

    Es empfiehlt sich jedoch, den Thread trotzdem vollständig zu lesen, um auch zu verstehen was gemacht wird!

    Das Skript weicht an einem Punkt ab, es verwendet ein anderes Skript um das Ziel zu pingen.

    Vorbereitungen

    Zum Ausführen der meisten Befehle werden root Rechte benötigt. Es empfiehlt sich, das Tutorial komplett als root umzusetzen.

    Verzeichnis erstellen

    Zunächst muss das Verzeichnis, auf dem später gemountet werden soll, erstellt werden. Existiert das Verzeichnis nicht, schlägt das mounten fehl.

    mkdir /media/fritz_nas

    Der hier vergebene Verzeichnisname kann bei Bedarf abgeändert werden, muss dann jedoch in den folgenden Pfadangaben auch angepasst werden. Außerdem ist der Pfad- und Verzeichnisname die Vorgabe für den Namen der Mount Unit.

    Zugangsdaten hinterlegen

    Als Nächstes werden die entsprechenden Zugangsdaten für die Authentifizierung bei der Gegenstelle (Fritz!Box) in einer Datei gespeichert. Der verwendete Benutzer muss natürlich in der Gegenstelle eingerichtet und der Zugriff auf die NAS Funktion freigegeben sein.

    nano /etc/smbcredentials

    Code: /etc/smbcredentials
    username=<USERNAME>
    password=<PASSWORD>

    Rechte der erstellten Datei an root übergeben und Zugriff beschränken:

    Code
    chown root:root /etc/smbcredentials
    chmod 600 /etc/smbcredentials

    Manuellen Mount durchführen

    Vor der Erstellung des automatischen Mounts führe ich zuvor einen manuellen Mount aus, um sicher sein zu können, dass die Verbindung zum Netzlaufwerk mit den übergebenen Optionen prinzipiell funktioniert.

    mount -t cifs -o credentials=/etc/smbcredentials,uid=1000,gid=1000 //192.168.178.1/fritzbox/ /media/fritz_nas

    Erfolgreichen Mount mit df überprüfen.

    Hinweis: Im Beispiel wird eine Freigabe der Fritz!Box gemounted.

    Ist die Firmware der Fritzbox < Fritz!OS V7.2 so wird nur die smb Version 1.0 unterstützt.

    In diesem Fall muss der Mountbefehl bei den Optionen erweitert werden mit vers=1.0. Diese Option ist abhängig vom Server, der die Freigabe zur Verfügung stellt. Weiteres hier.

    Muss nicht auf vers=1.0 zurückgegriffen werden, so empfiehlt es sich, diesen Parameter nicht mit anzugeben.

    Verlief der Test erfolgreich, müssen wir den Mount wieder rückgängig machen:

    umount /media/fritz_nas


    Erstellung der Mount Unit mit Abhängigkeiten

    systemd Mount Unit

    Wie schon erwähnt, ist der Name der Mount Unit abhängig vom gewählten Einhängepunkt.

    Mit folgendem Befehl bekommt man die Ausgabe, wie der Name der Mount Unit zu vergeben ist:

    systemd-escape --suffix=mount --path <EINHÄNGEPUNKT>

    In unserem Beispiel ist der Name: media-fritz_nas.mount

    nano /etc/systemd/system/media-fritz_nas.mount

    Abhängigkeit serverctl.service

    nano /etc/systemd/system/serverctl.service

    Bash Skript serverctl

    nano /usr/local/sbin/serverctl

    Kurze Erklärung

    Die IP Adressen sind bitte den entsprechenden eigenen IP Adressen anzupassen.

    Das bash Skript, welches durch serverctl aufgerufen wird, prüft, ob das Ziel erreichbar ist. Wenn ja, gibt serverctl grünes Licht, womit die Mount Unit die Freigabe bekommt, um den Mount auszuführen. Wer die einzelnen Befehle in den Units genau erklärt haben möchte, den verweise ich an diese Stelle an den Punkt Nützliche Links.

    Rechte anpassen

    Anschließend passen wir die Rechte für die erstellten Dateien an:

    Code
    chown root:root /usr/local/sbin/serverctl /etc/systemd/system/serverctl.service /etc/systemd/system/media-fritz_nas.mount
    chmod 644 /etc/systemd/system/serverctl.service /etc/systemd/system/media-fritz_nas.mount
    chmod 755 /usr/local/sbin/serverctl

    Inbetriebnahme

    Mount Unit testen

    Nun starten wir den Mount über die Mount Unit:

    systemctl start media-fritz_nas.mount

    Ob das ganze erfolgreich verlief, kann wieder mit df oder mittels systemctl status media-fritz_nas.mount überprüft werden

    Damit das ganze nun abschließend bei jedem Systemstart ausgeführt wird, muss die Mount Unit enabled werden:

    systemctl enable media-fritz_nas.mount

    Ab diesem Punkt wird bei jedem Neustart die Freigabe automatisch eingehängt.

    Problembehandlung

    Kommt es zu Fehlern beim Mounten, so ist es unbedingt notwendig vor einem erneuten Versuch das Ziel mittels umount /media/fritz_nas wieder auszuhängen.

    Bekannte Fehler

    • Bei Zugriff auf eine Datei im gemounteten Ordner kommt die Meldung: "<Dateiname> kann nicht zum Lesen geöffnet werden: Veraltete Dateizugriffsnummer (file handle)"
      Lösung: Options ergänzt mit Parameter noserverino


    Nützliche Links

    Mount Units

    Mount

    Service_Units

    systemd

    systemd Units

    Wo funktioniert es?

    Tutorial wurde am 26. August 2018 erstellt

    Zuletzt wesentlich angepasst: 12. Januar 2021

    Getestet auf folgenden Systemen:

    • Linux Mint 19 Tara
      4.15.0-33-generic #36-Ubuntu SMP Wed Aug 15 16:00:05 UTC 2018 x86_64 x86_64 x86_64 GNU/Linu
    • Raspbian 9 Stretch
      4.14.52-v7+ #1123 SMP Wed Jun 27 17:35:49 BST 2018 armv7l GNU/Linux
    • Raspbian 10 Buster
      5.4.72-v7+ #1356 SMP Thu Oct 22 13:56:54 BST 2020 armv7l GNU/Linux

    Danksagung

    Ein spezieller Dank geht von mir an ThomasL , von ihm stammt die serverctl Datei und das zugehörige Bash Skript.

    Außerdem für die Ermittlung des notwendigen Aufbaus der Mount Unit.

    Ebenfalls Danke an STF der das Tutorial Korrekturgelesen hat und es besser lesbar gemacht hat


    Weiteres

    Es wird immer hier der Beitrag #1 aktuell gehalten bei neuen Erkenntnissen.

    Konstruktive Kritik und Anmerkungen zum Tutorial sind hier im Thread gerne willkommen. Sollte es aber Probleme bei der Umsetzung des Ganzen geben, so bitte ich darum, dass du für deine Fragen/Probleme einen separaten Thread eröffnest.

  • :thumbup:Für die Mühe, aber eine Kleinigkeit:

    <meckermode>

    Systemweite Konfigurationsdateien gehören nicht in ein User-Home.

    Imho wäre es sauberer das credentials-File in /etc oder /usr/local/etc zu lagern.

    </meckermode>

    Grund 1: #isso

    Grund 2: Lass Leute diese Anleitung nehmen, um gedankenlos ihr seperates /home so zu mounten ...(zugegeben, beim rpi sicher seltener)

    Wenn du nichts zu sagen hast, sag einfach nichts.

    Einmal editiert, zuletzt von llutz (26. August 2018 um 17:52)

  • Das betrachte ich nicht als meckern sondern als konstruktive Kritik und diese ist immer gern Willkommen.

    Wie sonst, könnte man was dazu lernen, vorallem wenn man das ganze nur als Hobby betreibt.

    Dann müssen wir aber bei ubuntuusers auch meckern ^^ https://wiki.ubuntuusers.de/Samba_Client_c…aeres-Einbinden

    /etc oder /usr/local/etc

    Welches von beiden ist sinnvoller?


    Grund 2: Lass Leute diese Anleitung nehmen, um gedankenlos ihr seperates /home so zu mounten ...(zugegeben, beim rpi sicher seltener)

    Weil ansonsten die Zugangsdaten per Netzwerk erreichbar sind, oder wie meinst du das?

    Könnte das ganze beim Gedankenlos sein... nicht auch bei /etc passieren?

  • Zitat



    Welches von beiden ist sinnvoller?

    Ich bin für /etc, weil es ein Systemereignis zur Bootzeit betrifft.

    Weil ansonsten die Zugangsdaten per Netzwerk erreichbar sind, oder wie meinst du das?

    Du willst /home mit Credentials mounten, die auf /home liegen? Henne-Ei ;)

    Wie gesagt, dieser Fall (/home noch dazu auf cifs) ist wohl eher theoretischer Natur, aber nach einiger Zeit des hier Mitlesens... be prepared.

    Wenn du nichts zu sagen hast, sag einfach nichts.

  • Eine Belanglosigkeit: Im Mount Befehl hast du den User "Hofei" stehen. Sollte bestimmt "pi" sein

    Richtig, da ist mir wohl ein Kopierfehler passiert....Machte das ganze parallel auf dem Mint System mit...


    Ich bin für /etc, weil es ein Systemereignis zur Bootzeit betrifft.

    Abschließende Frage zu diesem Thema...unter /etc noch einen eigenen Ordner oder direkt ablegen?

  • Hofei Sorry, bisschen was hab ich noch, alles nur Kosmetik:

    - In /etc sollten keine versteckten Dateien liegen, besser /etc/smbcredentials.

    - Systembefehle/Hilfsscripte für diese: FHS-konform in /usr/local/sbin/serverctl statt /usr/local/bin

    Wenn du nichts zu sagen hast, sag einfach nichts.

  • Also was die passenden Orte angeht, da bin ich atm noch viel zu unerfahren, und nehme jede Verbesserung/Hinweis gerne an.

    FHS-konform

    Wenn ich danach suche, finde ich zwar viele Threads wo auch dieser Begriff verwendet wird, aber wo finde ich denn eine Aufstaffelung was wo hingehört?

  • Vielleicht hilft dir das und man hier. Ich finde die FHS auch nicht so super übersichtlich/selbsterklärend. Z.B. einen Sinn für versteckte Dateien habe ich noch nicht gefunden. Die FHS ist, wenn ich das richtig verstanden haben, auch gewachsen und es gibt Altlasten. Einige Programme schreiben ihre Konfigurationsdateien im Home Verzeichnis, danstatt in ~/.config.

  • enn ich danach suche, finde ich zwar viele Threads wo auch dieser Begriff verwendet wird, aber wo finde ich denn eine Aufstaffelung was wo hingehört?

    https://de.wikipedia.org/wiki/Filesystem_Hierarchy_Standard. Es ist mehr eine Empfehlung, der ich als alter Sack aber gern immernoch Folge. Erspart Suchererei. ;)

    Z.B. einen Sinn für versteckte Dateien habe ich noch nicht gefunden

    In Home-Verzeichnissen werden Konfigurationsdateien versteckt (dotfiles, dotdirs), damit der User, wenn er einfach ein "ls -l" macht oder seinen Dateimanager aufruft, nicht von der Fülle existierender Einträge erschlagen wird. Will er Configs sehen, spendiert er ein "a" oder aktiviert die entsprechende Option im Dateimanager.

    In /etc/ liegen default ohnehin nur Konfigurationen und keine "Nutzdaten", deshalb ist es übersichtlicher dort reguläre Dateien statt dotfiles anzulegen. Die würde man dort nicht erwarten.

    Einige Programme schreiben ihre Konfigurationsdateien im Home Verzeichnis, danstatt in ~/.config.

    Weil das früher so üblich war und es wahrscheinlich noch Jahre dauern wird, bis sich ~/.local und ~/.config flächendeckend etabliert haben.

    Stichwort Rückwärtskompatibilität. Es gibt Leute, die haben ihr $HOME seit Jahren, da will man nicht "einfach so" den Speicherort von Konfigurationen geändert haben.

    Die Idee/Einführung von ~/.config geht auf freedesktop.org (früher xdg) zurück, da obiges Problem erst vermehrt auftrat als Linuxsysteme "deppendesktoptauglich" wurden. Davor hat es keinen Interessiert. "War halt so". Deshalb findet man Konfigurationen von non-X Anwendungen auch seltener in dieser neuen Hierarchie.

    Wenn du nichts zu sagen hast, sag einfach nichts.

    Einmal editiert, zuletzt von llutz (28. August 2018 um 08:03)

  • Hofei Danke für diese Superanleitung ;)

    Du hast geschrieben das Sie für Stretch funktioniert.

    Gibt es eine Möglichkeit dies auch für Jessie umzusetzen ? Dort scheitere ich an dem fehlendem systemctl.


    Wenn ich zwei NAS einbinden möchte erstelle ich mir zwei .mount und eine serverctl2.service ?

    Gruß

    Micha

    Einmal editiert, zuletzt von mfeske (21. Februar 2019 um 18:34)

  • So, ich habe nun endlich nach dieser Anleitung eine Mount Unit am RPi angelegt. Motivation war, das am Debian PC mit nur WLAN der Fritz.NAS Mount über die fstab nicht funktioniert, trotz _netdev. Dort muss ich das noch umsetzen. Am RPi funktioniert es schon mal. Danke Hofei und auch ThomasL und STF für die Mitarbeit!

    Ein paar Fragen habe ich aber noch. Warum ist der Einhängepunkt /media und nicht /media/pi (also /media/<Benutzer>)?

    Bei der Mount Unit könnte man ggf. Description= kürzen, bzw. anpassen? Zumindest erschien mir der Text doppelt gemoppelt mit Blick auf die Ausgabe von systemctl status <>.mount.

    Zum Bash Skript serverctl:

    Kann man die Variablen in Zeile 16/17 nicht weglassen, da sie in der While Schleife deklariert werden? Oder den IF-ELSE Block in die Schleife packen um das doppelte Abfragen von HomeNetIsConnect zu vermeiden?

  • Ein paar Fragen habe ich aber noch. Warum ist der Einhängepunkt /media und nicht /media/pi (also /media/<Benutzer>)?

    Weil auf einem Server der gleiche Share von verschiedenen Usern mit individuellen Sambarechten gemountet werden kann. Weil auf einem bestimmten Client die von einem Samba-Server angebotenen Shares durch unterschiedliche lokale Client-User der Share ebenfalls mit individuellen Rechten gemountet werden kann... in diesem Fall aber immer auf einen neutralen Mount-Point. In Netzwerken gibts es mitunter viele User, die alle nicht "pi" heissen. BTW, das Entfernen des Users 'pi' war bei mir immer der erste Schritt bei der Inbetriebnahme eines Raspberry Pi's.

    Zu 16/17.... entferne es doch einfach und überführe die Bedingungsabfrage direkt in den Loop... wenns geht und Du mit solcher Praxis auch bei anderen Scripten hinsichlich möglicher Subshells keine Probleme kriegst, spricht nichts dagegen. Man muss das nicht 1:1 übernehmen.

    Allerdings folgt der Aufbau des Scripts ganz klar meiner Direktive "bestmögliche Lesbarkeit" und "hohe Eindeutigkeit". Ich halte eine ordentliche Variablendeklaration für zwingend notwendig, auch wenn man das bei der Bash nicht immer benötigt. Mit undeklarierten Variablen in eine Funktion zu gehen halte ich für unsauber. Aber das ist Linux, das ist Bash, das ist gpl ... du kannst es einrichten, wie Du magst. Nur bei Problemen sollten die dann nicht hier diesen Thread kaputtmachen.

    Ganz nebenbeibemerkt betrachte ich Gedanken über solcherart Optimierungen an einem solchen unwichtigen Mini-Script für reine Zeitverschwendung. :P

  • Wegen dem Mountpunkt. So in etwa habe ich es vermutet. Danke für die Erklärung!

    Die Fragen wegen dem Skript kamen mir halt, als ich es durchgegangen bin und versucht habe es im Detail zu verstehen. Bin mit Bash (noch) nicht vertraut. Gute Lesbarkeit/Einfachheit sind/waren auch meine Motivation. Auch wenn es sich um ein "Mini-Skript" handelt. Zumindest auf meiner Seite ist ein Lernfaktor vorhanden und dadurch nicht unbedingt Zeitverschwendung. Z.B. würde ich das rc=0 eindeutig platzieren, anstatt "mitten" im Skript ohne Bezug. Als Erfahrener Benutzer sieht man das sicher anders. Aber so weit bin ich noch nicht.

    Btw., wenn ich mich nicht täusche, dann ist laut systemd-analyze time im Vergleich zum mounten in der fstab, die Bootzeit ein paar Sekunden kürzer. :^^: Falls das jemand verifizieren kann, könnte man das als (weiteren) Vorteil/Pluspunkt angeben für eine Mount-Unit.

  • Z.B. würde ich das rc=0 eindeutig platzieren, anstatt "mitten" im Skript ohne Bezug.

    Genau an der Stelle ist es eindeutig.... und zwar als Default-Wert für die nachfolgende Bedingung. Und eben diesen Charakter als Default-Wert kriegt es nur an dieser Stelle.

    BTW, 'rc' steht als Abkürzung für Return-Code, das ist also eine Bezeichnung, die ich auch in längeren Scripten mit gleicher Absicht häufiger verwende. Insofern ist es bei dem Ziel unmittelbar und begrenzt gültiger Default-Wert sogar zwingend notwendig, genau an dieser Stelle initialisiert zu werden. Der Umstand, dass sie nicht oben und somit pauschal deklariert ist, lässt einen Entwickler auch erahnen, dass der Wert in 'rc' hier nur eine lokale Bedeutung haben soll. Und darüber hinaus sichert die Zuweisung an dieser Stelle, dass sie nicht noch einen Wert aus einer anderen Zuweisung von anderer Stelle im Code hat.

    Das betrifft natürlich ein solches Miniscript nur rudimentär... für mich handelt es sich aber um das Verfolgen einer grundsätzliche Code-Hygiene, sauberer Stil, hohe Reproduzierbareit (auch nach längerer Zeit), selbstdokumentierender Quelltext durch den Code-Aufbau.... also kontinuierliches Verfolgen von (durchaus auch eigenen) Regeln, um das alles zu gewährleisten.... im großen wie im kleinen.

    Einmal editiert, zuletzt von WinterUnit16246 (29. März 2019 um 15:40)

  • Das RC für Return Code steht ist mit bekannt. Kenne ich als System Variable unter AmigaDOS (Tripos) wo eben der Return Code abgelegt wird.

    Zugegeben, das Skript ist ein schlechtes Beispiel hierfür, da es so klein ist und man es erkennen kann, wofür rc=0 sein soll. Richtiger wäre, technisch gesehen, rc=0 in die IF Anweisung zu packen. Also in den IF ... THEN Teil. Denn an genau der Stelle wird entschieden, das der Return Code 0 sein soll. Also lokal, wie du geschrieben hast, nur wirklich (noch) lokal(er). IF -> rc=0 und ELSE -> rc=1. Ist meinem Verständnis nach sauberer. Ein Return Code hat oder braucht keinen Default Wert. Zumindest nicht in diesem Beispiel. Ich bin auch voll bei dir, was "Code-Hygiene, sauberer Stil" betrifft. So, genug abgedriftet von mir. :^^:

  • Ist meinem Verständnis nach sauberer.

    Nach meinem Verständnis wäre es sauber, einen solchen Tutorial-Thread nicht mit völlig sinnbefreiten Aspekten zu zerfleddern. Einen konstruktiven Nutzen kann ich bisher jedenfalls nicht ausmachen. Offensichtlich weisst Du besser als andere, wie 'sauberer' geht und was richtig ist, was hält Dich davon ab, es einfach zu tun, statt nur drüber zu reden ... denn so kommt offensichtlich nix dabei rum.

    Ich wiederhole das noch mal... das ist Linux, das ist Bash, das ist unter gpl eingestellt... wenn Dir das Beispiel nicht genügt, kannst Du es beliebig nach eigenem Maßgaben ändern und dann in einem eigenen Tutorial veröffentlichen und erklären, warum das die bessere Lösung ist. Ich bin raus..... :fies:

    Hofei, ich entschuldige mich bei Dir, mich hier beteiligt zu haben.

Jetzt mitmachen!

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