Perché rsync non riesce a copiare i file da / sys in Linux?


12

Ho uno script bash che utilizza rsyncper il backup dei file in Archlinux. Ho notato che rsyncnon è riuscito a copiare un file da /sys, mentre ha cpfunzionato bene:

# 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

Mi chiedo perché non rsyncriesca, ed è possibile copiare il file con esso?


4
Perché vuoi copiare /sys/?
frostschutz,

1
@frostschutz Uso il comando nell'OP per copiare l'indirizzo MAC di una scheda di rete (come file)
Eugene Yarmash

@eugeney Quindi, perché non è sufficiente eseguire il backup del file di configurazione da cui è impostato l'indirizzo MAC?
depquid

@eugeney È anche possibile scrivere /sys/class/net/*/address(ricevo "permesso negato" quando lo provo)? In caso contrario, non stai eseguendo un backup reale / utile poiché non può essere ripristinato.
depquid

Risposte:


12

Rsync ha un codice che controlla specificamente se un file viene troncato durante la lettura e fornisce questo errore - ENODATA. Non so perché i file /sysabbiano questo comportamento, ma dal momento che non sono file reali, immagino non sia troppo sorprendente. Non sembra esserci un modo per dire a rsync di saltare questo particolare controllo.

Penso che probabilmente stai meglio non sincronizzare /syse utilizzare script specifici per selezionare le informazioni particolari che desideri (come l'indirizzo della scheda di rete).


Pfft, dov'è il divertimento nel non capire perché rsync in particolare fallisce?
Bratchley,

Scusa, non ero chiaro. Rsync controlla specificamente i file troncati durante la lettura e genera questo errore.
mattdm,

4
Presumo che abbiano questo comportamento perché fino a quando non li leggi, ciò che è "lì" non è assolutamente certo; la lettura è davvero una richiesta di informazioni dinamiche dal kernel. Quindi il kernel non cerca di fornire dettagli accurati WRT sulla dimensione del file, ecc., In anticipo, e come fai notare, rsync prende una tale discrepanza come un brutto segno.
Riccioli d'oro

11

Prima di tutto /sysè un pseudo file system . Se guardi /proc/filesystemstroverai un elenco di file system registrati in cui un bel po 'ha nodev davanti. Ciò indica che sono pseudo filesystem . Ciò significa che esistono su un kernel in esecuzione come filesystem basato su RAM. Inoltre non richiedono un dispositivo a blocchi.

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

All'avvio il kernel monta questo sistema e aggiorna le voci quando necessario. Ad esempio, quando viene trovato nuovo hardware durante l'avvio o da udev.

In /etc/mtabgenere trovi il mount di:

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

Per un bel documento sull'argomento leggi Patric Mochel's - The sysfs Filesystem .


stat dei file / sys

Se vai in una directory sotto /syse fai un ls -lnoterai che tutti i file hanno una dimensione. In genere 4096 byte. Questo è segnalato da 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
...

Inoltre puoi fare un statsu un file e notare un'altra caratteristica distinta; occupa 0 blocchi. Anche l'inode di root (stat / sys) è 1. in /stat/fsgenere ha inode 2. ecc.

rsync vs. cp

La spiegazione più semplice dell'errore rsync di sincronizzazione dei pseudo file è forse l'esempio.

Supponiamo di avere un file denominato di address18 byte. Uno lso statdel file riporta 4096 byte.


rsync

  1. Apre il descrittore di file, fd.
  2. Usa fstat (fd) per ottenere informazioni come le dimensioni.
  3. Inizia a leggere byte di dimensioni, ovvero 4096. Sarebbe la riga 253 del codice collegato da @mattdm .read_size == 4096
    1. Chiedi; leggi: 4096 byte.
    2. Viene letta una stringa breve, ovvero 18 byte. nread == 18
    3. read_size = read_size - nread (4096 - 18 = 4078)
    4. Chiedi; leggi: 4078 byte
    5. 0 byte letti (come prima lettura consumati tutti i byte nel file).
    6. nread == 0, linea 255
    7. Impossibile leggere i 4096byte. Azzerare il buffer.
    8. Imposta errore ENODATA.
    9. Ritorno.
  4. Segnala errore.
  5. Riprova. (Sopra il ciclo).
  6. Fallire.
  7. Segnala errore.
  8. FINI.

Durante questo processo legge effettivamente l'intero file. Ma senza dimensioni disponibili non è possibile convalidare il risultato, quindi il fallimento è solo un'opzione.

cp

  1. Apre il descrittore di file, fd.
  2. Usa fstat (fd) per ottenere informazioni come st_size (usa anche lstat e stat).
  3. Controlla se è probabile che il file sia scarso. Questo è il file ha buchi ecc.

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

    Poiché il statfile di report ha zero blocchi, è classificato come scarso.

  4. Cerca di leggere il file con estensione-copia (un modo più efficiente per copiare i normali file sparsi) e fallisce.

  5. Copia con copia sparsa.
    1. Inizia con la dimensione massima di lettura di MAXINT.
      In genere 18446744073709551615byte su un sistema a 32 bit.
    2. Chiedi; leggere 4096 byte. (Dimensione del buffer allocata in memoria dalle informazioni sulle statistiche.)
    3. Viene letta una stringa breve, ovvero 18 byte.
    4. Controlla se è necessario un foro, no.
    5. Scrivi buffer sul target.
    6. Sottrai 18 dalla dimensione massima di lettura.
    7. Chiedi; leggere 4096 byte.
    8. 0 byte poiché tutti sono stati consumati in prima lettura.
    9. Ritorna successo.
  6. Tutto ok. Aggiorna flag per il file.
  7. FINI.

2

Potrebbe essere correlato, ma le chiamate di attributi estese non riusciranno su sysfs:

[root @ hypervisor eth0] # indirizzo lsattr

lsattr: ioctl inappropriato per il dispositivo durante la lettura di flag sull'indirizzo

[root @ hypervisor eth0] #

Guardando la mia striscia sembra che rsync cerchi di inserire attributi estesi per impostazione predefinita:

22964 <... getxattr resumed>, 0x7fff42845110, 132) = -1 ENODATA (Nessun dato disponibile)

Ho provato a trovare un flag per dare a rsync di vedere se saltare gli attributi estesi risolve il problema ma non sono riuscito a trovare nulla ( --xattrsli accende a destinazione).


0

Rsync normalmente legge le informazioni del file, trasferisce il contenuto del file o delta in un file temporaneo nella directory di destinazione, quindi dopo aver verificato i dati del file lo rinomina nel nome del file di destinazione.

Credo che il problema con sysfs sia che tutti i file mostrino 4k (una pagina di memoria) ma possono contenere solo pochi byte. Per evitare di copiare un file potenzialmente corrotto nella destinazione, rsync annulla la copia quando rileva una discrepanza tra i metadati del file e ciò che è stato effettivamente copiato.

Almeno su rsync v3.0.6 questo comportamento può essere evitato usando l' --inplaceinterruttore. Rsync rileverà comunque errori ma poiché i file di destinazione saranno già stati sovrascritti quando lo farà, lascerà lì i file potenzialmente corrotti.

Si noti tuttavia che un effetto collaterale di ciò è che i file finiscono per essere riempiti di zero a 4k poiché questa è la dimensione che rsync pensa che siano i file. Nella maggior parte dei casi non dovrebbe fare la differenza poiché i byte null vengono generalmente ignorati.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.