2.014 Dateien erfolgreich übertragen. Null Fehler im Log. Checksummen bestanden. Daten intakt.
Dann startest du die Verifizierung, und jeder einzelne Timestamp ist falsch. Nicht ein paar. Alle. Die Änderungsdaten auf dem Ziel sind der Zeitpunkt des Transfers, nicht die Originaldaten von der Quelle.
Kein Fehler. Keine Warnung. Das Tool sagte, es sei fertig. Was ist passiert?
Wenn du NFS betreibst, läuft bei dir fast sicher root_squash. Es ist der Standard auf jeder großen NFS-Server-Distribution. Die meisten Admins ändern es nie, weil die meisten Admins nie darüber nachdenken müssen.
So funktioniert es: Wenn ein Client als Root (UID 0) verbindet, mappt der NFS-Server diesen Benutzer auf nobody (UID 65534). Root auf dem Client wird nobody auf dem Server. Das ist ein Sicherheitsfeature. Ohne root_squash hätte ein Root-Benutzer auf jeder Client-Maschine Root-Zugriff auf jede Datei deines NFS-Exports.
# /etc/exports (typische NFS-Server-Konfiguration)
/srv/data 192.168.1.0/24(rw,sync,root_squash)
Dieses root_squash ist der Standard. Du musst es nicht einmal hinschreiben. Wenn deine Exports-Zeile nicht no_root_squash enthält, ist Squashing aktiv.
root_squash ist der stille Standard
Wenn deine /etc/exports nur (rw,sync) sagt, ist root_squash trotzdem aktiv. Es ist nur dann aus, wenn du explizit no_root_squash hinzufügst. Das erwischt viele Leute, weil in der Konfiguration nichts steht, das dir sagt, dass es an ist.
Dein Migrationstool läuft als Root. Das ist normal. Es braucht Root, um Dateien jedes Benutzers auf der Quelle lesen zu können und um Eigentümer auf dem Ziel setzen zu können. Hier ist die Abfolge, wenn es eine Datei auf ein NFS-Ziel mit aktiviertem root_squash schreibt:
nobody:nogroup erstellt, aber die Bytes stimmen.nobody ist nicht in der erwarteten Weise der Eigentümer, und der SETATTR-Aufruf liefert EPERM zurück. Operation nicht erlaubt.chtimes-Aufruf, der den Änderungszeitstempel setzt, steht nach dem chmod-Aufruf. Er wird nie ausgeführt.Die Daten sind da. Die Checksumme stimmt. Das Tool markiert es als erledigt. Aber der Timestamp ist falsch, weil die einzige Funktion, die ihn setzt, durch einen Early Return einer völlig unzusammenhängenden Operation übersprungen wurde.
Die stille Kaskade
chmod-Fehler ist der Auslöser, aber Timestamp-Verlust ist die Folge. Diese beiden Operationen haben keine logische Abhängigkeit. Berechtigungen und Timestamps sind unabhängige Metadaten. Aber in den meisten Implementierungen teilen sie sich einen Fehlerpfad, sodass ein Fehler beide killt.
Dieses Fehlverhalten hat drei Tarnschichten:
Die Daten sind korrekt. Dateigrößen stimmen überein. Checksummen bestehen. Das Wichtigste, der eigentliche Inhalt, ist in Ordnung. Jede Verifizierung, die nur die Datenintegrität prüft, gibt dir grünes Licht.
Der chmod-Fehler geht unter. Er taucht vielleicht in Debug-Logs auf. Es ist kein Transfer-Fehler. Die meisten Tools stufen ihn bestenfalls als Warnung ein. Bei einer Migration von 100.000 Dateien registrierst du 2.000 chmod-Warnungen, die mit Vollgas durchscrollen, einfach nicht.
Der Timestamp-Verlust hinterlässt keine Spur. Es gibt keinen Fehler für chtimes, weil chtimes nie lief. Du kannst nicht nach einem Fehler greppen, der nicht stattgefunden hat. Der einzige Beweis ist die Abwesenheit korrekter Timestamps auf dem Ziel — und du müsstest sie mit der Quelle vergleichen, um es zu bemerken.
NFS-Exports prüfen:
# Auf dem NFS-Server
cat /etc/exports
Wenn du root_squash siehst oder no_root_squash nicht siehst, ist Squashing aktiv.
In den Tool-Logs nach EPERM suchen:
grep -i "EPERM\|operation not permitted\|permission denied" /var/log/migration*.log
Wenn du chmod-Fehler auf dem NFS-Ziel siehst, sind die Timestamps mit ziemlicher Sicherheit auch falsch.
Timestamps zwischen Quelle und Ziel vergleichen:
# Schneller Stichproben-Check
stat -c '%y %n' /source/path/to/file
stat -c '%y %n' /dest/path/to/file
Wenn das Ziel das Datum deines Migrationslaufs zeigt und nicht das Originaldatum, hat es dich erwischt.
Massenvergleich:
find /source -type f -exec stat -c '%Y %n' {} \; | sort > /tmp/src-times.txt
find /dest -type f -exec stat -c '%Y %n' {} \; | sort > /tmp/dst-times.txt
diff /tmp/src-times.txt /tmp/dst-times.txt | head -20
Wenn jeder Timestamp auf der rechten Seite sich um dasselbe Datum clustert (der Tag, an dem du die Migration ausgeführt hast), ist die Kettenreaktion eingetreten.
# /etc/exports
/srv/data 192.168.1.0/24(rw,sync,no_root_squash)
Dann exportfs -ra zum Neuladen. Das gibt dem Client-Root vollen Zugriff auf den Export. chmod funktioniert, chtimes funktioniert, alles funktioniert. Aber du hast eine Sicherheitsgrenze entfernt. Mach das nur in einem vertrauenswürdigen Netzwerk mit vertrauenswürdigen Clients, und aktiviere Squashing idealerweise wieder nach Abschluss der Migration.
Wenn der Benutzer, der das Migrationstool ausführt, dem Dateieigentümer auf dem NFS-Server entspricht, funktioniert chmod ohne Root. Das bedeutet:
Nicht praktikabel für die meisten Migrationen, aber gut zu wissen.
Das ist der eigentliche Fix. chmod und chtimes sind unabhängige Operationen. Es gibt keinen Grund, warum ein Fehler bei einer die andere blockieren sollte. Der Code sollte:
try chmod → Fehler loggen wenn fehlgeschlagen → weiter
try chtimes → Fehler loggen wenn fehlgeschlagen → weiter
berichten, welche Metadaten-Operationen erfolgreich waren und welche nicht
So werden selbst wenn root_squash das chmod blockiert, deine Timestamps trotzdem gesetzt. Und du bekommst ein klares Log, das genau zeigt, welche Operationen fehlgeschlagen sind und welche erfolgreich waren, anstatt einer stillen Kaskade.
syncopio advantage
syncopio behandelt chmod und chtimes als unabhängige Operationen. Wenn chmod fehlschlägt (häufig bei root_squash), loggt es den Fehler und setzt trotzdem den Timestamp. Wenn chtimes fehlschlägt, wird das separat geloggt. Keine Operation kann die andere blockieren. Dein Verifizierungsbericht zeigt genau, welche Metadaten erhalten wurden und welche nicht.
Nach jeder NFS-Migration, besonders bei Ausführung als Root:
1. Prüfe root_squash auf dem Ziel
# Auf dem NFS-Server
grep -v "^#" /etc/exports | grep -v "no_root_squash"
Wenn Ergebnisse auftauchen, ist Squashing auf diesen Exports aktiv.
2. Berechtigungen vergleichen
stat -c '%a %n' /source/somefile
stat -c '%a %n' /dest/somefile
3. Timestamps vergleichen
stat -c '%y %n' /source/somefile
stat -c '%y %n' /dest/somefile
4. Logs auf EPERM prüfen
Jedes EPERM auf dem Ziel-Mount bei Metadaten-Operationen bedeutet, dass die Kettenreaktion ausgelöst worden sein könnte.
5. Abweichungen in großem Maßstab zählen
# Dateien, bei denen der Ziel-mtime von der Quelle abweicht
paste <(find /source -type f -exec stat -c '%Y %n' {} \; | sort -k2) \
<(find /dest -type f -exec stat -c '%Y %n' {} \; | sort -k2) \
| awk '$1 != $3 { count++ } END { print count " timestamp mismatches" }'
Wenn diese Zahl deiner Gesamtdateianzahl entspricht, war jede Datei betroffen. Das ist die Signatur einer vollständigen Kaskade.
Prüfe vor der Migration, nicht danach
Führe einen Testtransfer von 10 Dateien auf das NFS-Ziel durch und vergleiche sofort die Timestamps. Wenn root_squash Probleme verursacht, siehst du es bei Datei Nr. 1. Finde es nicht erst nach zwei Millionen übertragenen Dateien heraus.
Weiterführende Lektüre: