Pourquoi rsync ne parvient-il pas à copier des fichiers depuis / sys sous Linux?

12

J'ai un script bash qui permet rsyncde sauvegarder des fichiers dans Archlinux. J'ai remarqué qu'il rsyncn'a pas été possible de copier un fichier à partir de /sys, alors qu'il cpfonctionnait très bien:

# 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

Je me demande pourquoi rsyncéchoue et est-il possible de copier le fichier avec?

Eugene Yarmash
la source
4
Pourquoi voulez-vous copier /sys/?
frostschutz
1
@frostschutz J'utilise la commande dans l'OP pour copier l'adresse MAC d'une carte réseau (sous forme de fichier)
Eugene Yarmash
@eugeney Alors, pourquoi ne suffit-il pas de sauvegarder le fichier de configuration à partir duquel l'adresse MAC est définie?
depquid
@eugeney Est-il même possible d'écrire /sys/class/net/*/address(j'obtiens une "autorisation refusée" lorsque je l'essaye)? Sinon, vous ne faites pas de sauvegarde réelle / utile car elle ne peut pas être restaurée.
depquid

Réponses:

12

Rsync a un code qui vérifie spécifiquement si un fichier est tronqué pendant la lecture et donne cette erreur - ENODATA. Je ne sais pas pourquoi les fichiers /sysont ce comportement, mais comme ce ne sont pas de vrais fichiers, je suppose que ce n'est pas trop surprenant. Il ne semble pas y avoir de moyen de dire à rsync d'ignorer cette vérification particulière.

Je pense que vous feriez probablement mieux de ne pas synchroniser /syset d'utiliser des scripts spécifiques pour sélectionner les informations particulières que vous souhaitez (comme l'adresse de la carte réseau).

mattdm
la source
Pfft, où est le plaisir de ne pas comprendre pourquoi rsync en particulier échoue?
Bratchley
Désolé, je n'étais pas clair. Rsync vérifie spécifiquement les fichiers tronqués lors de la lecture et renvoie cette erreur.
mattdm
4
Je suppose qu'ils ont ce comportement parce que jusqu'à ce que vous les lisiez réellement, ce qui est "là" n'est pas absolument certain; la lecture est vraiment une demande d'informations dynamiques du noyau. Ainsi, le noyau n'essaie pas de donner à l'avance des détails précis sur la taille du fichier, etc., et comme vous le faites remarquer, rsync prend une telle différence comme un mauvais signe.
goldilocks
11

Tout d'abord, /sysun pseudo système de fichiers . Si vous regardez, /proc/filesystemsvous trouverez une liste des systèmes de fichiers enregistrés où un bon nombre ont nodev en face. Cela indique qu'il s'agit de pseudo-systèmes de fichiers . Cela signifie qu'ils existent sur un noyau en cours d'exécution en tant que système de fichiers basé sur la RAM. De plus, ils ne nécessitent pas de dispositif bloc.

$ cat /proc/filesystems
nodev   sysfs
nodev   rootfs
nodev   bdev
...

Au démarrage, le noyau monte ce système et met à jour les entrées le cas échéant. Par exemple, lorsqu'un nouveau matériel est détecté au démarrage ou par udev.

En /etc/mtabvous trouvez généralement la monture par:

sysfs /sys sysfs rw,noexec,nosuid,nodev 0 0

Pour un bon article sur le sujet, lisez Patric Mochel's - The sysfs Filesystem .


fichiers stat / sys

Si vous allez dans un répertoire sous /syset faites un, ls -lvous remarquerez que tous les fichiers ont une taille. En général, 4096 octets. Ceci est rapporté par 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
...

De plus, vous pouvez faire une statsur un fichier et remarquer une autre fonctionnalité distincte; il occupe 0 blocs. L'inode de la racine (stat / sys) est également 1. a /stat/fsgénéralement l'inode 2. etc.

rsync vs cp

L'explication la plus simple de l'échec rsync de la synchronisation des pseudo-fichiers est peut-être par exemple.

Supposons que nous ayons un fichier nommé de address18 octets. Un lsou statdu fichier rapporte 4096 octets.


rsync

  1. Ouvre le descripteur de fichier, fd.
  2. Utilise fstat (fd) pour obtenir des informations telles que la taille.
  3. Partez pour lire les octets de taille, c'est-à-dire 4096. Ce serait la ligne 253 du code lié par @mattdm .read_size == 4096
    1. Demander; lire: 4096 octets.
    2. Une courte chaîne est lue, c'est-à-dire 18 octets. nread == 18
    3. read_size = read_size - nread (4096 - 18 = 4078)
    4. Demander; lire: 4078 octets
    5. 0 octet lu (comme la première lecture a consommé tous les octets du fichier).
    6. nread == 0, ligne 255
    7. Impossible de lire les 4096octets. Zéro tampon.
    8. Définir l'erreur ENODATA.
    9. Revenir.
  4. Signaler une erreur.
  5. Retenter. (Au-dessus de la boucle).
  6. Échouer.
  7. Signaler une erreur.
  8. BIEN.

Au cours de ce processus, il lit en fait le fichier entier. Mais sans taille disponible, il ne peut pas valider le résultat - donc l'échec n'est qu'une option.

cp

  1. Ouvre le descripteur de fichier, fd.
  2. Utilise fstat (fd) pour obtenir des informations telles que st_size (utilise également lstat et stat).
  3. Vérifiez si le fichier est susceptible d'être clairsemé. C'est-à-dire que le fichier a des trous, etc.

    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);
    

    En tant statque fichier de rapports ne contenant aucun bloc, il est classé comme clairsemé.

  4. Tente de lire le fichier par extension-copie (un moyen plus efficace de copier des fichiers clairsemés normaux ), et échoue.

  5. Copie par copie clairsemée.
    1. Commence avec une taille de lecture maximale de MAXINT.
      Généralement 18446744073709551615octets sur un système 32 bits.
    2. Demander; lire 4096 octets. (Taille du tampon allouée en mémoire à partir des informations statistiques.)
    3. Une courte chaîne est lue, c'est-à-dire 18 octets.
    4. Vérifiez si un trou est nécessaire, non.
    5. Écrire le tampon dans la cible.
    6. Soustrayez 18 de la taille de lecture maximale.
    7. Demander; lire 4096 octets.
    8. 0 octet car tous ont été consommés lors de la première lecture.
    9. Retour du succès.
  6. Tout va bien. Mettre à jour les drapeaux du fichier.
  7. BIEN.
Runium
la source
2

Peut être lié, mais les appels d'attributs étendus échoueront sur sysfs:

[root @ hypervisor eth0] # adresse lsattr

lsattr: ioctl inapproprié pour le périphérique lors de la lecture des indicateurs sur l'adresse

[root @ hypervisor eth0] #

En regardant ma strace, il semble que rsync essaie de récupérer des attributs étendus par défaut:

22964 <... getxattr repris>, 0x7fff42845110, 132) = -1 ENODATA (Aucune donnée disponible)

J'ai essayé de trouver un drapeau pour donner rsync pour voir si sauter les attributs étendus résout le problème mais n'a pas été en mesure de trouver quoi que ce soit ( --xattrsles tourne sur à la destination).

Bratchley
la source
0

Rsync lit normalement les informations du fichier, transfère le contenu du fichier ou les delta vers un fichier temporaire dans le répertoire de destination, puis après avoir vérifié les données du fichier, il le renomme en nom de fichier de destination.

Je crois que le problème avec sysfs est que tous les fichiers s'affichent en 4k (une page mémoire) mais qu'ils ne contiennent que quelques octets. Pour éviter de copier un fichier potentiellement corrompu vers la destination, rsync annule la copie lorsqu'il voit un décalage entre les métadonnées du fichier et ce qui a été réellement copié.

Au moins sur rsync v3.0.6, ce comportement peut être évité en utilisant le --inplacecommutateur. Rsync détectera toujours les erreurs, mais comme les fichiers de destination auront déjà été écrasés au moment où il le fera, il laissera les fichiers potentiellement corrompus.

Notez cependant qu'un effet secondaire est que les fichiers finissent par être remplis de zéro à 4k car c'est la taille que rsync pense que les fichiers sont. Cela ne devrait pas faire de différence dans la plupart des cas, car les octets nuls sont généralement ignorés.

Thomas Guyot-Sionnest
la source