Tengo un script bash que se utiliza rsync
para realizar copias de seguridad de archivos en Archlinux. Noté que rsync
no pude copiar un archivo /sys
, aunque cp
funcionó 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
Me pregunto por qué rsync
falla y ¿es posible copiar el archivo con él?
Respuesta1
En primer lugar /sys
es unpseudo sistema de archivos. Si observa, /proc/filesystems
encontrará una lista de sistemas de archivos registrados donde hay bastantes nodev
al frente. Esto indica que sonpseudo sistemas de archivos. Esto significa que existen en un kernel en ejecución como un sistema de archivos basado en RAM. Además, no requieren un dispositivo de bloqueo.
$ cat /proc/filesystems
nodev sysfs
nodev rootfs
nodev bdev
...
Al arrancar, el kernel monta este sistema y actualiza las entradas cuando sea necesario. Por ejemplo, cuando se encuentra nuevo hardware durante el arranque o mediante udev
.
Normalmente /etc/mtab
encuentras la montura por:
sysfs /sys sysfs rw,noexec,nosuid,nodev 0 0
Para un buen artículo sobre el tema lea Patric Mochel: el sistema de archivos sysfs.
estadísticas de archivos /sys
Si ingresa a un directorio debajo /sys
y hace un, ls -l
notará que todos los archivos tienen un tamaño. Normalmente 4096 bytes. Así lo informa 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
...
Además, puede hacer una revisión stat
en un archivo y notar otra característica distintiva; Ocupa 0 cuadras. Además, el inodo de la raíz (stat /sys) es 1. /stat/fs
normalmente tiene el inodo 2, etc.
rsync vs cp
La explicación más sencilla para el error de rsync al sincronizar pseudoarchivos es quizás mediante un ejemplo.
Digamos que tenemos un archivo llamado address
que tiene 18 bytes. Uno ls
o stat
del archivo informa 4096 bytes.
sincronización
- Abre el descriptor de archivo, fd.
- Utiliza fstat(fd) para obtener información como el tamaño.
- Prepárese para leer bytes de tamaño, es decir, 4096. Eso seríalínea 253del código vinculado por@mattdm.
read_size == 4096
- Preguntar; leer: 4096 bytes.
- Se lee una cadena corta, es decir, 18 bytes.
nread == 18
read_size = read_size - nread (4096 - 18 = 4078)
- Preguntar; leer: 4078 bytes
- 0 bytes leídos (ya que la primera lectura consumió todos los bytes del archivo).
nread == 0
,línea 255- No se pueden leer
4096
bytes. Búfer de salida a cero. - Error de configuración
ENODATA
. - Devolver.
- Informe de error.
- Rever. (Arriba del bucle).
- Fallar.
- Informe de error.
- BIEN.
Durante este proceso, en realidad lee el archivo completo. Pero sin un tamaño disponible no puede validar el resultado, por lo que el fracaso es la única opción.
CP
- Abre el descriptor de archivo, fd.
- Utiliza fstat(fd) para obtener información como st_size (también utiliza lstat y stat).
Compruebe si es probable que el archivo esté disperso. Ese es el archivo que tiene agujeros, 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);
Como
stat
el archivo de informes no tiene bloques, se clasifica como disperso.Intenta leer el archivo por extensión-copia (una forma más eficiente de copiarnormal archivos dispersos) y falla.
- Copiar por copia dispersa.
- Comienza con un tamaño de lectura máximo de MAXINT.
Normalmente18446744073709551615
bytes en un sistema de 32 bits. - Preguntar; leer 4096 bytes. (Tamaño del búfer asignado en la memoria a partir de la información de estadísticas).
- Se lee una cadena corta, es decir, 18 bytes.
- Comprueba si hace falta un agujero, no.
- Escribe el búfer en el destino.
- Resta 18 del tamaño máximo de lectura.
- Preguntar; leer 4096 bytes.
- 0 bytes ya que todos se consumieron en la primera lectura.
- Éxito de regreso.
- Comienza con un tamaño de lectura máximo de MAXINT.
- Todo bien. Actualizar indicadores para el archivo.
- BIEN.
Respuesta2
Rsync tienecódigoque verifica específicamente si un archivo se trunca durante la lectura y genera este error: ENODATA
. No sépor quéLos archivos /sys
tienen este comportamiento, pero como no son archivos reales, supongo que no es demasiado sorprendente. No parece haber una manera de decirle a rsync que omita esta verificación en particular.
Creo que probablemente sea mejor no sincronizar /sys
y usar scripts específicos para seleccionar la información particular que desea (como la dirección de la tarjeta de red).
Respuesta3
Puede estar relacionado, pero las llamadas de atributos extendidos fallarán en sysfs:
[root@hypervisor eth0]# dirección lsattr
lsattr: ioctl inapropiado para el dispositivo mientras se leen indicadores en la dirección
[raíz@hipervisor eth0]#
Mirando mi ruta, parece que rsync intenta extraer atributos extendidos de forma predeterminada:
22964 <... getxattr resumed> , 0x7fff42845110, 132) = -1 ENODATA (No hay datos disponibles)
Intenté encontrar una bandera para dar rsync para ver si omitir atributos extendidos resuelve el problema pero no pude encontrar nada ( --xattrs
los convierteenen el destino).
Respuesta4
Rsync normalmente lee la información del archivo, transfiere el contenido del archivo o delta a un archivo temporal en el directorio de destino y luego, después de verificar los datos del archivo, le cambia el nombre al nombre del archivo de destino.
Creo que el problema con sysfs es que todos los archivos se muestran como 4k (una página de memoria) pero pueden contener solo unos pocos bytes. Para evitar copiar un archivo potencialmente corrupto al destino, rsync cancela la copia cuando detecta una discrepancia entre los metadatos del archivo y lo que realmente se copió.
Al menos en rsync v3.0.6, este comportamiento se puede evitar usando el --inplace
conmutador. Rsync seguirá detectando errores, pero como los archivos de destino ya se habrán sobrescrito, cuando lo haga, dejará allí los archivos potencialmente corruptos.
Sin embargo, tenga en cuenta que un efecto secundario es que los archivos terminan con relleno de ceros a 4k, ya que este es el tamaño que rsync cree que tienen los archivos. No debería hacer una diferencia en la mayoría de los casos, ya que los bytes nulos generalmente se ignoran.