Copyright © 1996 by O'Reilly/International Thomson Verlag

Bitte denken Sie daran: Sie dürfen zwar die Online-Version ausdrucken, aber diesen Druck nicht fotokopieren oder verkaufen.

Wünschen Sie mehr Informationen zu der gedruckten Version des Buches "Linux: Wegweiser durch das Netzwerk" dann klicken Sie hier.


Kapitel 11
Das Network File System

NFS, das »Network File System«, ist wahrscheinlich der bekannteste auf RPC basierende Netzwerkdienst. Er erlaubt Ihnen, auf Dateien von entfernten Hosts so zuzugreifen, wie Sie es mit lokalen Dateien tun. Dies wird durch eine Mischung aus Kernel-Funktionalität auf der Client-Seite und einem NFS-Server auf der Server-Seite realisiert. Der Dateizugriff ist für den Client völlig transparent und funktioniert für eine Reihe von Server- und Host-Architekturen.

NFS bietet eine Reihe nützlicher Features:

Es ist nicht besonders schwer, die grundlegenden NFS-Funktionen für den Client und den Server einzurichten. Dieses Kapitel beschreibt, wie es geht.

Linux-NFS ist größtenteils die Arbeit von Rick Sladkey,(1) der den NFS-Kernel und große Teile des NFS-Servers geschrieben hat. Letzterer wurde vom unfsd-NFS-Server, ursprünglich entwickelt von Mark Shand, und vom hnfs-Harris-NFS-Server, geschrieben von Donald Becker, abgeleitet.

Sehen wir uns an, wie NFS arbeitet. Ein Client versucht, ein Verzeichnis von einem entfernten Host an sein lokales Verzeichnis zu mounten, genau wie er dies mit einem physikalischen Gerät machen würde. Allerdings ist die für ein entferntes Verzeichnis zu verwendende Syntax anders. Soll zum Beispiel das Verzeichnis /home vom Host vlager an /users auf vale gemountet werden, führt der Administrator auf vale den folgenden Befehl ein:(2)

# mount -t nfs vlager:/home /users
mount versucht, über RPC eine Verbindung mit dem Mount-Dämon (mountd) auf vlager herzustellen. Der Server überprüft, ob vale die Erlaubnis besitzt, das fragliche Verzeichnis zu mounten; wenn ja, liefert er einen Datei-Handle zurück. Dieser Handle wird bei allen weiteren Anfragen nach Dateien unter /users verwendet.

Greift jemand über NFS auf eine Datei zu, setzt der Kernel einen RPC-Aufruf an nfsd (den NFS-Dämon) auf der Server-Maschine ab. Dieser Aufruf enthält den Datei-Handle, den Namen der gewünschten Datei und den Benutzer- und Gruppen-ID als Parameter. Diese werden verwendet, um die Zugriffsrechte auf die angegebene Datei zu ermitteln. Um das Lesen und Modifizieren von Dateien durch nicht-autorisierte Benutzer zu verhindern, müssen die Benutzer- und Gruppen-IDs auf beiden Hosts identisch sein.

Bei den meisten UNIX-Implementierungen wird die NFS-Funktionalität sowohl für Clients als auch für Server durch Dämonen realisiert, die auf Kernel-Ebene angesiedelt sind und während der Bootphase vom Benutzerspeicher aus gestartet werden. Dies ist auf dem Serverhost der NFS-Dämon (nfsd) und auf dem Client-Host der Block I/O Dämon (biod). Um den Durchsatz zu verbessern, arbeitet biod mit asynchroner Ein-/Ausgabe unter Gebrauch von Read-Ahead und Write-Behind. Häufig werden auch mehrere nfsd-Dämonen gleichzeitig verwendet.

Die NFS-Implementierung von Linux ist von daher etwas anders, als daß der Client-Kode eng mit dem VFS-Layer (»Virtual File System«) des Kernels verbunden ist und daher keine zusätzliche Kontrolle durch biod benötigt. Auf der anderen Seite läuft der Server vollständig im Benutzerspeicher, d. h. es ist aufgrund der damit verbundenen Synchronisations-Fragen nahezu unmöglich, mehrere Kopien des Servers zur selben Zeit laufen zu lassen. Momentan kennt Linux-NFS auch kein Read-Ahead und Write-Behind, Rick Sladkey plant aber, es eines Tages hinzuzufügen.(3)

Das größte Problem mit dem Linux-NFS-Kode ist, daß bei der Version 1.0 des Linux-Kernel nur Speicherblöcke von maximal 4 K genutzt werden können. Die Konsequenz daraus ist, daß der Netzwerk-Kode nur Datagramme übertragen kann, deren Größe auf ungefähr 3500 Byte beschränkt ist, nachdem man die Header etc. abgezogen hat. Das bedeutet, daß Übertragungen von und zu NFS-Dämonen, die auf Systemen laufen, die per Voreinstellung größere UDP-Datagramme übertragen (z. B. 8 K bei SunOS), künstlich heruntergeschraubt werden müssen. Das hat unter Umständen schmerzliche Auswirkungen auf die Performance.(4) Diese Einschränkung ist in den späten Linux-1.1-Kerneln aufgehoben worden. Der Client-Kode ist entsprechend modifiziert worden, um von diesem Vorteil Gebrauch zu machen.

NFS vorbereiten

Bevor Sie NFS benutzen können, sei es nur als Client oder als Server, müssen Sie zuerst sicherstellen, daß die entsprechende NFS-Unterstützung in den Kernel integriert (kompiliert) ist. Neuere Kernel haben dazu ein einfaches Interface im Dateisystem proc, nämlich die Datei /proc/filesystems, die Sie einfach mit cat ausgeben können:

$ cat /proc/file systems
  minix
  ext2
  msdos
nodev proc
nodev  nfs
Fehlt nfs in dieser Liste, müssen Sie den Kernel neu kompilieren und dabei NFS mit einbinden. Die Konfiguration der Netzwerk-Optionen des Kernel wird im Abschnitt »Kernel-Konfiguration« in Kapitel 3 beschrieben.

Bei älteren Kerneln vor Linux 1.1 ist die einfachste Möglichkeit, um herauszufinden, ob der Kernel NFS unterstützt oder nicht, einfach auszuprobieren, ob sich ein NFS-Dateisystem mounten läßt oder nicht. Dazu können Sie ein Testverzeichnis unter /tmp erzeugen und versuchen, ein Verzeichnis vom NFS-Server (z. B. /home) zu mounten, das dieser an Ihre Maschine exportiert:

# mkdir /tmp/test
# mount server:/home /tmp/test
Schlägt dieser Versuch mit der Meldung »fs type nfs not supported by kernel,« fehl, müssen Sie den Kernel mit eingebundenem NFS neu kompilieren.

Ein NFS-Volume mounten

NFS-Volumes(5) werden fast genauso gemountet wie die normalen Dateisysteme auch. Sie verwenden dabei für mount die folgende Syntax:

# mount -t nfs nfs_volume local_dir options
nfs_volume is given as remote_host:remote_dir. Weil diese Notation nur bei NFS-Dateisystemen gilt, können Sie die Option -t nfs weglassen.

Eine ganze Reihe zusätzlicher Optionen kann beim Mounten eines NFS-Volumes angegeben werden. Diese können entweder auf die Option -o in der Kommandozeile folgen, oder im Optionsfeld von /etc/fstab für dieses Volume stehen. In beiden Fällen werden mehrere Optionen durch Kommata voneinander getrennt. In der Kommandozeile angegebene Optionen überschreiben immer die in fstabstehenden Werte.

Nachfolgend ein Beispiel-Eintrag aus /etc/fstab:

# Volume              Mountpunkt       Typ     Optionen
news:/usr/spool/news  /usr/spool/news   nfs   timeo=14,intr
Dieses Volume kann mit dem folgenden Befehl gemountet werden:
# mount news:/usr/spool/news
Fehlt ein solcher fstab-Eintrag, sehen NFS-mounts wesentlich unangenehmer aus. Nehmen wir zum Beispiel an, daß Sie die Home-Verzeichnisse der Benutzer von einer Maschine namens moonshot aus mounten. Um eine Blockgröße von 4 K für Schreib/Lese-Operationen zu verwenden, benutzen Sie den folgenden Befehl:
# mount moonshot:/home /home -o rsize=4096,wsize=4096
Eine vollständige Liste aller gültigen Optionen ist in der nfs(5)-Manpage beschrieben, die bei Rick Sladkeys NFS-fähigem mount-Tool enthalten ist. (Sie finden es in Rik Faiths util-linux-Paket.) Nachfolgend ein Teil der Optionen, die Sie möglicherweise verwenden möchten:
rsize=n und wsize=n
Bestimmt die bei Schreib- bzw. Leseanforderungen von NFS-Clients verwendete Datagramm-Größe. Im Moment ist diese aufgrund der oben beschriebenen Einschränkungen in der UDP-Datagramm-Größe auf 1024 Byte voreingestellt.
timeo=n
Bestimmt die Zeit (in Zehntelsekunden), die ein NFS-Client auf den Abschluß einer Anforderung wartet. Der voreingestellte Wert ist 7 (0,7 Sekunden).
hard
Markiere dieses Volume explizit als »hart« gemountet. Per Voreinstellung aktiviert.
soft
»Weiches« Mounten des Verzeichnisses (im Gegensatz zu hartem Mounten).
intr
Unterbrechung von NFS-Aufrufen über Signale möglich. Nützlich, wenn ein Server nicht antwortet und der Client abgebrochen werden muß.

Mit Ausnahme von rsize und wsize wirken sich all diese Optionen auf das Verhalten des Client aus, wenn der Server kurzfristig nicht erreichbar sein sollte. Sie spielen auf folgende Weise zusammen: Sendet der Client eine Anforderung an den NFS-Server, erwartet er, daß die Operation innerhalb einer bestimmten Zeit abgeschlossen ist. Diese Zeit kann mit der Option timeout festgelegt werden. Wird innerhalb dieser Zeit keine Bestätigung empfangen, kommt es zu einem sogenannten kleinen Timeout. Die Operation wird nun wiederholt, wobei das Timeout-Intervall verdoppelt wird. Wird der maximale Timeout von 60 Sekunden erreicht, tritt ein großer Timeout auf.

Per Voreinstellung gibt ein Client bei einem schwerwiegenden Timeout eine Fehlermeldung auf der Console aus und versucht es erneut. Dabei wird das ursprüngliche Timeout-Intervall verdoppelt. Theoretisch könnte dies immer so weitergehen. Volumes, die eine Operation störrisch wiederholen, bis der Server wieder verfügbar ist, werden als fest gemountet (hard-mounted) bezeichnet. Die andere Variante wird als weich gemountet (soft-mounted) bezeichnet und generiert einen I/O-Fehler für den rufenden Prozeß, wenn ein schwerwiegender Fehler auftritt.

Ob Sie ein Volume fest mounten oder nicht, ist teilweise von Ihrem Geschmack, teilweise aber auch von der Art der Informationen abhängig, auf die Sie über dieses Volume zugreifen wollen. Wenn Sie etwa Ihre X-Programme über NFS mounten, wollen Sie wahrscheinlich nicht, daß Ihre X-Session verrückt spielt, nur weil jemand das Netzwerk zum Erliegen gebracht hat, indem er sieben Kopien von xv gleichzeitig benutzt, oder weil er kurz den Ethernet-Stecker gezogen hat. Indem Sie diese Programme fest mounten, stellen Sie sicher, daß der Computer so lange wartet, bis die Verbindung mit dem NFS-Server wiederhergestellt ist. Auf der anderen Seite brauchen unkritische Daten wie NFS-gemountete News-Partitionen oder FTP-Archive nicht fest gemountet zu sein. Ist die entfernte Maschine zeitweise nicht erreichbar oder heruntergefahren, hängt sich Ihre Session nicht auf. Ist Ihre Netzwerk-Verbindung etwas instabil, oder läuft sie über einen überlasteten Router, können Sie den anfänglichen Timeout mit Hilfe der Option timeo erhöhen oder die Volumes fest mounten. Dabei sollten Sie es aber ermöglichen, daß Signale die NFS-Aufrufe unterbrechen dürfen, damit Sie einen hängenden Dateizugriff unterbrechen können.

Der mountd-Dämon hält normalerweiße auf die eine oder andere Art fest, welche Verzeichnisse von welchen Hosts gemountet wurden. Diese Information kann mit dem Programm showmount ausgegeben werden, die ebenfalls Teil des NFS-Serverpakets ist. Linux-mountd dagegen kennt diese Möglichkeit noch nicht.

Die NFS-Dämonen

Wenn Sie anderen Hosts NFS-Dienste anbieten wollen, müssen die nfsd- und mountd-Dämonen auf Ihrer Maschine laufen. Als RPC-basierte Programme werden sie nicht von inetd verwaltet, sondern werden während der Bootphase gestartet und registrieren sich selbst beim Portmapper. Daher müssen Sie sicherstellen, daß die Programme erst gestartet werden, wenn rpc.portmap schon läuft. Normalerweise fügen Sie die folgenden Zeilen in Ihr rc.inet2-Script ein:

if [ -x /usr/sbin/rpc.mountd ]; then
        /usr/sbin/rpc.mountd; echo -n " mountd"
fi
if [ -x /usr/sbin/rpc.nfsd ]; then
        /usr/sbin/rpc.nfsd; echo -n " nfsd"
fi
Die Besitzinformationen über Dateien, die ein NFS-Dämon an seine Clients liefert, bestehen üblicherweise nur aus den numerischen Benutzer- und Gruppen-IDs. Wenn der Client und der Server dieselben Benutzer- und Gruppennamen mit diesen numerischen IDs verbinden, spricht man von einem gemeinsamen UID/GID-Raum. Dies ist beispielsweise der Fall, wenn Sie NIS einsetzen, um die passwd-Informationen an alle Hosts in Ihrem LAN weiterzugeben.

In manchen Fällen stimmen sie aber nicht überein. Statt nun die UIDs und GIDs der Clients mit denen auf dem Server abzugleichen, können Sie auf dem Client den ugidd-Dämon einsetzen, um dieses Problem zu umgehen. Mit der nachfolgend erläuterten Option map_daemon können Sie nfsd anweisen, mit Hilfe von ugidd den UID/GID-Raum des Servers auf den UID/GID-Raum des Client abzubilden.

ugidd ist ein RPC-basierter Server, der, ebenso wie nfsd und mountd, aus rc.inet2 heraus gestartet wird.

if [ -x /usr/sbin/rpc.ugidd ]; then
        /usr/sbin/rpc.ugidd; echo -n " ugidd"
fi

Die exports-Datei

Für jeden Client werden die Zugriffsmöglichkeiten bestimmt, über die auf die Dateien auf dem Server zugegriffen werden kann. Dieser Zugriff wird in der Datei /etc/exports festgelegt, die die gemeinsam genutzten Dateien enthält.

Per Voreinstellung erlaubt mount niemandem, Verzeichnisse des lokalen Hosts über NFS zu mounten, was eine sehr vernünftige Einstellung ist. Um einem oder mehreren Hosts den NFS-Zugriff auf ein Verzeichnis zu erlauben, müssen Sie es exportieren, d. h. in der Datei export eintragen. Eine Beispieldatei könnte so aussehen:

# exports-Datei für vlager
/home             vale(rw) vstout(rw) vlight(rw)
/usr/X386         vale(ro) vstout(ro) vlight(ro)
/usr/TeX          vale(ro) vstout(ro) vlight(ro)
/                 vale(rw,no_root_squash)
/home/ftp         (ro)
Jede Zeile definiert ein Verzeichnis und die Hosts, die es mounten dürfen. Ein Hostname ist üblicherweise ein voll qualifizierter Domainname, kann zusätzlich aber auch die Platzhalter * und ? enthalten, die auf dieselbe Weise funktionieren wie bei der Bourne-Shell. Beispielsweise wird bei lab*.foo.com sowohl lab01.foo.com als auch laber.foo.com akzeptiert. Wird wie im obigen Beispiel beim /home/ftp-Verzeichnis kein Hostname angegeben, darf jeder Host dieses Verzeichnis mounten.

Bei der Prüfung eines Client-Host gegen die exports-Datei ermittelt mountd den Hostnamen des Client mit Hilfe eines gethostbyaddr-Aufrufs. Unter DNS liefert dieser Aufruf den kanonischen Hostnamen des Client zurück, d. h. Sie dürfen keine Aliases in exports verwenden. Ohne DNS wird der erste Hostname aus hosts zurückgeliefert, bei dem die Adresse des Client übereinstimmt.

Dem Host-Namen kann eine Liste mit durch Kommata getrennten Optionen folgen, die in eckigen Klammern eingeschlossen sind. Diese Optionen können die folgenden Werte annehmen:

insecure
Auf diese Maschine ist nicht-authentisierter Zugriff erlaubt.
unix-rpc
Von dieser Maschine wird UNIX-Domain RPC-Authentisierung benötigt. Dies bedeutet einfach, daß Anforderungen von reservierten Internet-Ports (die Port-Nummer muß kleiner als 1024 sein) stammen müssen. Diese Option ist per Voreinstellung aktiviert.
secure-rpc
Von dieser Maschine wird Secure-RPC-Authentizierung benötigt. Dies ist bislang noch nicht implementiert. Siehe Suns Dokumentation zu Secure-RPC.
kerberos
Von dieser Maschine wird Kerberos-Authentizierung benötigt. Dies ist bislang noch nicht implementiert. Siehe die MIT-Dokumentation zum Kerberos-Authentizierungssystem.
root_squash
Ein Sicherheits-Feature, das den Super-Usern der spezifizierten Hosts jegliche besonderen Rechte verweigert, indem Anforderungen von UID 0 des Client auf UID 65534 (-2) auf dem Server abgebildet werden. Diese UID sollte dem Benutzer nobody zugewiesen sein. Diese Option ist per Voreinstellung aktiviert.
no_root_squash
Bildet Anforderungen von UID 0 nicht ab.
ro
Mounte die Datei-Hierarchie ohne Schreibmöglichkeit.
rw
Mounte die Datei-Hierarchie mit Schreib-/Leserechten. Diese Option ist per Voreinstellung aktiv.
link_relative
Wandle absolute symbolische Links (die mit einem Slash beginnen) in relative Links um, durch Voranstellen von ../. Der String wird so oft vorangestellt, wie es dauert, von dem Verzeichnis, das den Link enthält, bis zum Root-Verzeichnis zu gelangen. Diese Option macht nur Sinn, wenn das gesamte Dateisystem des Host gemountet ist. Anderenfalls könnten einige Links ins Nirgendwo zeigen, oder, noch schlimmer, auf Dateien, auf die niemals gezeigt werden sollte. Diese Option ist per Voreinstellung aktiviert.
link_absolute
Lasse alle symbolischen Links unverändert (das normale Verhalten bei von Sun abgeleiteten NFS-Servern).
map_identity
Die Option map_identity weist den Server an, gleiche UIDs und GIDs für Clients und Server zu erwarten. Diese Option ist per Voreinstellung aktiv.
map_daemon
Diese Option weist den NFS-Server an, nicht denselben UID/GID-Raum für Clients und Server zu erwarten. nfsd baut dann eine Liste auf, die IDs zwischen Client und Server durch Abfrage des ugidd-Dämons des Client abfragt.

Fehler beim Lesen der exports-Datei wird an syslogds daemon-Einrichtung auf der Ebene notice weitergegeben, wenn nfsd oder mountd hochfährt.

Beachten Sie, daß Hostnamen aus den IP-Adressen des Client durch »Reverse Mapping« ermittelt werden, d. h. der Resolver muß korrekt konfiguriert sein. Wenn Sie mit BIND arbeiten und sicherheitsbewußt sind, sollten Sie den Spoof-Schutz in Ihrer host.conf aktivieren.

Der Linux-Auto-Mounter

Manchmal wäre es Verschwendung, alle NFS-Volumes zu mounten, auf die ein Benutzer möglicherweise zugreifen möchte, sei es wegen der reinen Menge an Volumes, die gemountet werden müßten, sei es wegen der Zeit, die beim Start benötigt würde. Eine gute Alternative hierzu ist ein sogenannter Auto-Mounter. Dabei handelt es sich um einen Dämon, der jedes NFS-Volume automatisch und völlig transparent mountet und nach einer gewissen Zeit wieder unmountet, wenn es nicht verwendet wurde. Einer der besonders kleveren Züge bei einem Auto-Mounter ist seine Fähigkeit, ein bestimmtes Volume von alternativen Servern zu mounten. Sie können beispielsweise Kopien Ihrer X-Programme und Support-Dateien auf zwei oder drei Hosts verteilt haben, die alle anderen Hosts über NFS mounten. Mit dem Auto-Mounter können Sie nun für diese drei angeben, daß sie auf /usr/X386 gemountet werden sollen. Der Auto-Mounter wird dann versuchen, jeden der drei zu mounten, so lange, bis ein Versuch erfolgreich war.

Der unter Linux am häufigsten verwendete Auto-Mounter ist amd. Er wurde ursprünglich von Jan-Simon Pendry geschrieben und von Mitch D'Souza auf Linux portiert. Die aktuelle Version ist amd-5.3.

Die Beschreibung von amd geht über den Rahmen dieses Kapitels hinaus. Für ein gutes Handbuch sei auf die Quellen verwiesen; sie enthalten eine Texinfo-Datei mit sehr detaillierten Informationen.


Fußnoten

(1)
Rick ist unter jrs@world.std.com zu erreichen.
(2)
Sie können das Argument t nfs weglassen, weil mount anhand des Doppelpunkts erkennt, daß ein NFS-Volume gemeint ist.
(3)
Das Problem mit Write-Behind besteht darin, daß der Kernel-Buffercache mit Device/Inode-Paaren indiziert wird und daher nicht für über NFS gemountete Dateisysteme verwendet werden kann.
(4)
Wie Alan Cox mir erklärte: Die NFS-Spezifikation schreibt vor, daß jeder Datenblock auf die Platte geschrieben werden muß, bevor das OK zurückgeliefert wird. Weil BSD-basierte Kernel nur in der Lage sind, an der Pagegröße (4 K) orientierte Schreiboperationen durchzuführen, führt das Schreiben von vier 1 K großen Blöcken an einen BSD-basierten NFS-Server zu vier Schreiboperationen von je 4K.
(5)
Man sagt nicht Dateisystem, weil es kein richtiges Dateisystem ist.

Inhaltsverzeichnis Kapitel 10 Kapitel 12