Ich habe ein Bash-Skript, das rsync
zum Sichern von Dateien in Archlinux verwendet wird. Mir ist aufgefallen, dass rsync
das Kopieren einer Datei von fehlgeschlagen ist /sys
, während cp
es problemlos funktioniert hat:
# rsync /sys/class/net/enp3s1/address /tmp
rsync: read errors mapping "/sys/class/net/enp3s1/address": No data available (61)
rsync: read errors mapping "/sys/class/net/enp3s1/address": No data available (61)
ERROR: address failed verification -- update discarded.
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1052) [sender=3.0.9]
# cp /sys/class/net/enp3s1/address /tmp ## this works
Ich frage mich, warum das rsync
fehlschlägt und ob es möglich ist, die Datei damit zu kopieren?
Antwort1
Zunächst einmal /sys
ist einPseudodateisystem. Wenn Sie sich das ansehen, /proc/filesystems
finden Sie eine Liste registrierter Dateisysteme, bei denen ziemlich viele nodev
vorne stehen. Das zeigt an, dass siePseudodateisysteme. Das bedeutet, dass sie auf einem laufenden Kernel als RAM-basiertes Dateisystem existieren. Außerdem benötigen sie kein Blockgerät.
$ cat /proc/filesystems
nodev sysfs
nodev rootfs
nodev bdev
...
Beim Booten mountet der Kernel dieses System und aktualisiert die Einträge bei Bedarf. Zum Beispiel wenn während des Bootens oder durch neue Hardware gefunden wird udev
.
/etc/mtab
Normalerweise finden Sie die Halterung hier :
sysfs /sys sysfs rw,noexec,nosuid,nodev 0 0
Einen guten Artikel zu diesem Thema finden Sie hier: Patric Mochel – Das sysfs-Dateisystem.
stat von /sys-Dateien
Wenn Sie in ein Verzeichnis unter gehen /sys
und ein ausführen, ls -l
werden Sie feststellen, dass alle Dateien die gleiche Größe haben. Normalerweise 4096 Bytes. Dies wird von gemeldet sysfs
.
:/sys/devices/pci0000:00/0000:00:19.0/net/eth2$ ls -l
-r--r--r-- 1 root root 4096 Apr 24 20:09 addr_assign_type
-r--r--r-- 1 root root 4096 Apr 24 20:09 address
-r--r--r-- 1 root root 4096 Apr 24 20:09 addr_len
...
Außerdem können Sie eine stat
Datei ausführen und ein weiteres deutliches Merkmal feststellen: Sie belegt 0 Blöcke. Außerdem ist der Inode von Root (stat /sys) 1. /stat/fs
Normalerweise hat er Inode 2 usw.
rsync im Vergleich zu cp
Die einfachste Erklärung für das Fehlschlagen der Synchronisierung von Pseudodateien mit rsync ist vielleicht ein Beispiel.
Angenommen, wir haben eine Datei mit dem Namen address
18 Bytes. Ein ls
OR stat
der Datei meldet 4096 Bytes.
rsync
- Öffnet den Dateideskriptor fd.
- Verwendet fstat(fd), um Informationen wie die Größe abzurufen.
- Legen Sie fest, dass Sie size bytes lesen möchten, also 4096. Das wäreZeile 253des Codes, der durch@mattdm.
read_size == 4096
- Fragen; gelesen: 4096 Bytes.
- Es wird ein kurzer String gelesen, also 18 Bytes.
nread == 18
read_size = read_size - nread (4096 - 18 = 4078)
- Fragen; gelesen: 4078 Bytes
- 0 Bytes gelesen (da beim ersten Lesen alle Bytes in der Datei verbraucht wurden).
nread == 0
,Zeile 255- Bytes können nicht gelesen werden
4096
. Puffer auf Null setzen. - Fehler festlegen
ENODATA
. - Zurückkehren.
- Fehler melden.
- Erneut versuchen. (Oben genannte Schleife).
- Scheitern.
- Fehler melden.
- BUSSGELD.
Während dieses Vorgangs wird tatsächlich die gesamte Datei gelesen. Da jedoch keine Größe verfügbar ist, kann das Ergebnis nicht validiert werden. Daher ist ein Fehler die einzige Option.
cp
- Öffnet den Dateideskriptor fd.
- Verwendet fstat(fd), um Informationen wie st_size zu erhalten (verwendet auch lstat und stat).
Überprüfen Sie, ob die Datei wahrscheinlich spärlich ist. Das heißt, die Datei hat Löcher usw.
copy.c:1010 /* Use a heuristic to determine whether SRC_NAME contains any sparse * blocks. If the file has fewer blocks than would normally be * needed for a file of its size, then at least one of the blocks in * the file is a hole. */ sparse_src = is_probably_sparse (&src_open_sb);
Da
stat
die Berichtsdatei keine Blöcke enthält, wird sie als spärlich kategorisiert.Versucht, die Datei per Extent-Copy zu lesen (eine effizientere Methode zum Kopierennormal Sparse-Dateien) und schlägt fehl.
- Kopie durch Sparse-Kopie.
- Beginnt mit der maximalen Lesegröße von MAXINT.
Normalerweise18446744073709551615
Bytes auf einem 32-Bit-System. - Fragen; 4096 Bytes lesen. (Puffergröße im Speicher aus Statistikinformationen zugewiesen.)
- Es wird ein kurzer String gelesen, also 18 Bytes.
- Überprüfen Sie, ob ein Loch erforderlich ist. Nein.
- Schreibpuffer zum Ziel.
- Subtrahieren Sie 18 von der maximalen Lesegröße.
- Fragen; 4096 Bytes lesen.
- 0 Bytes, da alles beim ersten Lesen verbraucht wurde.
- Rückgabe erfolgreich.
- Beginnt mit der maximalen Lesegröße von MAXINT.
- Alles OK. Flags für Datei aktualisieren.
- BUSSGELD.
Antwort2
Rsync hatCodedas speziell prüft, ob eine Datei beim Lesen abgeschnitten wird und diesen Fehler ausgibt — ENODATA
. Ich weiß nichtWarumdie Dateien in /sys
zeigen dieses Verhalten, aber da es keine echten Dateien sind, ist das wohl nicht allzu überraschend. Es scheint keine Möglichkeit zu geben, rsync anzuweisen, diese spezielle Prüfung zu überspringen.
Ich denke, es ist wahrscheinlich besser, auf Rsync zu verzichten /sys
und stattdessen bestimmte Skripte zu verwenden, um gezielt die gewünschten Informationen herauszupicken (wie etwa die Adresse der Netzwerkkarte).
Antwort3
Könnte damit zusammenhängen, aber erweiterte Attributaufrufe schlagen auf Sysfs fehl:
[root@hypervisor eth0]# lsattr-Adresse
lsattr: Unangemessenes ioctl für Gerät beim Lesen von Flags an der Adresse
[root@hypervisor eth0]#
Wenn ich mir mein Strace anschaue, sieht es so aus, als ob rsync standardmäßig versucht, erweiterte Attribute einzubinden:
22964 <... getxattr resumed> , 0x7fff42845110, 132) = -1 ENODATA (Keine Daten verfügbar)
Ich habe versucht, ein Flag zu finden, das ich rsync geben kann, um zu sehen, ob das Überspringen erweiterter Attribute das Problem löst, konnte aber nichts finden ( --xattrs
macht sieAnam Zielort).
Antwort4
Normalerweise liest Rsync die Dateiinformationen, überträgt Dateiinhalte oder Deltas in eine temporäre Datei im Zielverzeichnis und benennt sie dann nach der Überprüfung der Dateidaten in den Zieldateinamen um.
Ich glaube, das Problem mit sysfs besteht darin, dass alle Dateien als 4 KB (eine Speicherseite) angezeigt werden, obwohl sie möglicherweise nur wenige Bytes enthalten. Um das Kopieren einer möglicherweise beschädigten Datei in das Ziel zu vermeiden, bricht rsync den Kopiervorgang ab, wenn es eine Nichtübereinstimmung zwischen den Metadaten der Datei und dem, was tatsächlich kopiert wurde, feststellt.
Zumindest bei rsync v3.0.6 kann dieses Verhalten mit dem --inplace
Schalter vermieden werden. Rsync erkennt zwar immer noch Fehler, aber da die Zieldateien zu diesem Zeitpunkt bereits überschrieben wurden, verbleiben die möglicherweise beschädigten Dateien dort.
Beachten Sie jedoch, dass ein Nebeneffekt davon darin besteht, dass Dateien mit Nullen auf 4 KB aufgefüllt werden, da dies die Größe ist, die rsync für die Dateien hält. In den meisten Fällen sollte dies keinen Unterschied machen, da Nullbytes normalerweise ignoriert werden.