Layer 8Ehrlicher Tech-Support

Linux: Symlink mit relativem Ziel zeigt ins Leere

ln -s mit relativem Ziel aus einem anderen Verzeichnis zeigt ins Leere? Der Pfad gilt relativ zum Ort des Links, nicht zum Ort des Aufrufs.

Aufwand:
ca. 10 Min.
Voraussetzung:
ln, readlink, ls, Handbuchseiten ln(1) und symlink(7)
Gilt für:
Linux mit GNU coreutils (ln(1)) und den Linux man-pages (symlink(7)), beide in der am 2026-10-15 abrufbaren Fassung, Die Option -r/--relative ist eine GNU-Erweiterung und auf anderen Systemen nicht zwingend vorhanden

Das Symptom

Jemand steht im Projektordner und tippt ln -s config.yml /etc/dienst/config.yml, um die Datei dort zu verlinken. Der Link entsteht ohne Fehlermeldung, aber der Dienst findet seine Konfiguration nicht, und ls zeigt ihn rot oder blinkend an. Die Annahme dahinter: ln löse den relativen Namen beim Anlegen vom aktuellen Verzeichnis aus auf und speichere das Ergebnis. Tatsächlich speichert der Link nur den Text config.yml, und der wird erst beim Zugriff ausgewertet, relativ zum Verzeichnis, in dem der Link liegt, also /etc/dienst/. Dieselbe Falle schlägt zu, wenn ein funktionierender relativer Link später mit mv in ein anderes Verzeichnis geschoben wird.

Die „Layer 8“-Wahrheit

Die Handbuchseite ln(1) sagt es in einem Satz: „Symbolic links can hold arbitrary text; if later resolved, a relative link is interpreted in relation to its parent directory.“ Beliebiger Text, später aufgelöst, in Bezug auf das Elternverzeichnis des Links. Nichts davon hat mit dem Verzeichnis zu tun, in dem der Befehl ausgeführt wurde, und ln prüft beim Anlegen nicht einmal, ob das Ziel existiert.

symlink(7) ergänzt beides ausdrücklich. Zum Anlegen: „There is no requirement that the pathname referred to by a symbolic link should exist. A symbolic link that refers to a pathname that does not exist is said to be a dangling link.“ Und zum Verschieben: „if the symbolic link references a file via a relative path, moving it to another directory may very well cause it to stop working, since the path may no longer be correct.“ Der Link ist also kein Zeiger auf eine Datei, sondern ein gespeicherter Text, der bei jedem Zugriff neu gelesen und vom Ort des Links aus interpretiert wird.

Praktisch heißt das: Entweder ein absolutes Ziel angeben, oder den relativen Pfad vom Speicherort des Links aus denken, oder ln -sr verwenden, das laut ln(1) den Link relativ zum Ort des Links erzeugt („-r, –relative with -s, create links relative to link location“). Die dritte Variante ist die bequemste, weil man das Ziel so schreiben darf, wie man es vor sich sieht, und trotzdem einen Link bekommt, der dort stimmt, wo er liegt.

Der Irrtum ist verständlich, weil fast jeder andere Befehl relative Pfade sofort und vom Arbeitsverzeichnis aus auflöst. cp, mv und cat tun das, und man gewöhnt sich daran, dass ein relativer Name immer das meint, was man gerade vor sich hat. ln -s ist die Ausnahme: Es schreibt den Namen auf und überlässt die Auflösung dem, der den Link später öffnet, von dort aus, wo der Link dann liegt.

Die echte, verifizierte Lösung

1000 % faktenbasiert. Jeder Befehl ist real, jeder Pfad existiert. Schritt für Schritt:

  1. 1.

    Den gespeicherten Text des Links ansehen

    readlink linkname gibt den Text aus, den der Link enthält, ls -l zeigt ihn hinter dem Pfeil. Steht dort ein relativer Name ohne führenden Schrägstrich, gilt er ab dem Verzeichnis, in dem der Link liegt. Das ist der Moment, in dem die meisten den Fehler sehen: Der Text ist richtig, nur der Bezugspunkt ist ein anderer.

    readlink /etc/dienst/config.yml
    ls -l /etc/dienst/config.yml
    
  2. 2.

    Prüfen, ob der Link auflösbar ist

    readlink -f linkname liefert den vollständig aufgelösten Pfad, wenn es einen gibt, und ls -L folgt dem Link. Eine Meldung, dass die Datei nicht existiert, heißt: dangling link. test -e linkname gibt in Skripten denselben Befund als Rückgabewert, ohne Ausgabe.

    readlink -f /etc/dienst/config.yml
    test -e /etc/dienst/config.yml && echo ok || echo "zeigt ins Leere"
    
  3. 3.

    Den Link neu anlegen: absolut oder mit -r

    Mit -f überschreibt ln den vorhandenen Link. Entweder das Ziel absolut angeben, oder ln -sr verwenden, das den relativen Pfad vom Ort des Links aus berechnet. Beide Varianten ergeben einen Link, der dort stimmt, wo er liegt; die zweite bleibt auch dann gültig, wenn das ganze Verzeichnis samt Ziel später umzieht.

    ln -sf /srv/projekt/config.yml /etc/dienst/config.yml
    ln -sfr /srv/projekt/config.yml /etc/dienst/config.yml
    
  4. 4.

    Beim Verschieben das Ziel mitdenken

    Ein relativer Link, der mit mv in ein anderes Verzeichnis wandert, rechnet ab dort neu. Entweder Link und Ziel gemeinsam verschieben, sodass die relative Beziehung erhalten bleibt, oder den Link nach dem Verschieben neu setzen. Ein absoluter Link ist davon nicht betroffen, zeigt dafür aber ins Leere, wenn das Ziel umzieht.

  5. 5.

    Vor dem Dienststart den Link prüfen, nicht den Dienst

    Findet ein Dienst seine Konfiguration nicht, zuerst test -e auf dem Link ausführen, bevor man in Logdateien und Dienstoptionen sucht. Ein dangling link erzeugt dieselbe Fehlermeldung wie eine fehlende Datei, und die Ursache steht in readlink, nicht im Dienst.

Häufige Fragen (FAQ)

?Ich stand im Projektordner und habe ln -s config.yml /etc/dienst/config.yml getippt. Warum zeigt der Link ins Leere?

Weil der Link nur den Text config.yml speichert und dieser Text erst beim Zugriff ausgewertet wird, und zwar relativ zum Verzeichnis, in dem der Link liegt. Die Handbuchseite ln(1) sagt es in einem Satz: „Symbolic links can hold arbitrary text; if later resolved, a relative link is interpreted in relation to its parent directory.“ Der Link in /etc/dienst/ sucht also /etc/dienst/config.yml, nicht die Datei im Projektordner. Dass ln beim Anlegen keine Fehlermeldung gibt, liegt daran, dass es das Ziel gar nicht prüft.

?Muss das Ziel beim Anlegen überhaupt existieren?

Nein. symlink(7) hält fest: „There is no requirement that the pathname referred to by a symbolic link should exist. A symbolic link that refers to a pathname that does not exist is said to be a dangling link.“ Ein Link ins Leere ist aus Sicht des Dateisystems vollkommen in Ordnung; erst der Dienst, der ihn öffnen will, bekommt die Fehlermeldung. ls zeigt solche Links je nach Farbschema rot oder blinkend, und readlink -f liefert den aufgelösten Pfad oder gar nichts.

?Der Link hat funktioniert, bis ich ihn mit mv verschoben habe. Warum?

Weil der gespeicherte relative Text nach dem Verschieben von einem anderen Verzeichnis aus ausgewertet wird. symlink(7) warnt genau davor: „if the symbolic link references a file via a relative path, moving it to another directory may very well cause it to stop working, since the path may no longer be correct.“ Ein relativer Link und sein Ziel gehören zusammen; wer nur den Link verschiebt, verschiebt den Ausgangspunkt der Rechnung, nicht das Ergebnis.

?Wie lege ich den Link richtig an?

Entweder mit absolutem Ziel, oder mit einem relativen Ziel, das vom Speicherort des Links aus gedacht ist, oder mit ln -sr, das den Pfad relativ zum Ort des Links selbst berechnet. ln(1) beschreibt die Option als „-r, --relative with -s, create links relative to link location“. Damit kann man im Projektordner stehen, das Ziel so angeben, wie man es sieht, und bekommt trotzdem einen Link, der vom Ort des Links aus stimmt.

Belege

Diese Seite ist gegen die folgenden Primärquellen geprüft – Hersteller, Standard oder Gesetzestext. Wer es nicht glaubt, muss es nicht: Da steht, wo es nachzulesen ist.

Zuletzt geprüft am . Dokumentation altert – ein Datum daneben ist der einzige ehrliche Umgang damit.

Auch zu finden unter

Verwandte Fehler

OSLästigPermission denied

Permission denied, obwohl man root ist

Selbst als root verweigert das System den Zugriff. Meist ist das Dateisystem schreibgeschützt eingehängt oder die Datei ist unveränderlich.