Eu tenho um script bash que usa rsync
para fazer backup de arquivos no Archlinux. Percebi que rsync
não consegui copiar um arquivo de /sys
, mas cp
funcionou perfeitamente:
# 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
Eu me pergunto por que rsync
falha e é possível copiar o arquivo com ele?
Responder1
Primeiro /sys
é umpseudo sistema de arquivos. Se você olhar, /proc/filesystems
encontrará uma lista de sistemas de arquivos registrados, onde alguns têm nodev
na frente. Isso indica que eles estãopseudo sistemas de arquivos. Isso significa que eles existem em um kernel em execução como um sistema de arquivos baseado em RAM. Além disso, eles não necessitam de um dispositivo de bloqueio.
$ cat /proc/filesystems
nodev sysfs
nodev rootfs
nodev bdev
...
Na inicialização, o kernel monta este sistema e atualiza as entradas quando adequado. Por exemplo, quando um novo hardware é encontrado durante a inicialização ou pelo udev
.
Em /etc/mtab
você normalmente encontra a montagem por:
sysfs /sys sysfs rw,noexec,nosuid,nodev 0 0
Para um bom artigo sobre o assunto, leia Patric Mochel's – O sistema de arquivos sysfs.
estatísticas de arquivos /sys
Se você entrar em um diretório abaixo /sys
e fizer um, ls -l
notará que todos os arquivos têm o mesmo tamanho. Normalmente 4096 bytes. Isto é relatado por 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
...
Além disso, você pode fazer uma pesquisa stat
em um arquivo e notar outro recurso distinto; ocupa 0 blocos. Além disso, o inode da raiz (stat/sys) é 1. /stat/fs
normalmente possui o inode 2. etc.
rsync vs.
A explicação mais fácil para a falha do rsync na sincronização de pseudoarquivos é talvez um exemplo.
Digamos que temos um arquivo chamado address
de 18 bytes. Um ls
ou stat
do arquivo relata 4.096 bytes.
sincronizar novamente
- Abre o descritor de arquivo, fd.
- Usa fstat(fd) para obter informações como tamanho.
- Prepare-se para ler bytes de tamanho, ou seja, 4096. Isso serialinha 253do código vinculado por@mattdm.
read_size == 4096
- Perguntar; leia: 4096 bytes.
- Uma string curta é lida, ou seja, 18 bytes.
nread == 18
read_size = read_size - nread (4096 - 18 = 4078)
- Perguntar; leia: 4078 bytes
- 0 bytes lidos (como a primeira leitura consumiu todos os bytes do arquivo).
nread == 0
,linha 255- Não é possível ler
4096
bytes. Zerar buffer. - Definir erro
ENODATA
. - Retornar.
- Reportar erro.
- Tente novamente. (Loop acima).
- Falhar.
- Reportar erro.
- MULTAR.
Durante esse processo, ele lê o arquivo inteiro. Mas sem tamanho disponível não pode validar o resultado – portanto o fracasso é apenas uma opção.
CP
- Abre o descritor de arquivo, fd.
- Usa fstat(fd) para obter informações como st_size (também usa lstat e stat).
Verifique se o arquivo provavelmente será esparso. Esse é o arquivo que tem furos 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
o arquivo de relatórios tem zero blocos, ele é categorizado como esparso.Tenta ler o arquivo por cópia de extensão (uma maneira mais eficiente de copiarnormal arquivos esparsos) e falha.
- Copiar por cópia esparsa.
- Começa com tamanho máximo de leitura de MAXINT.
Normalmente18446744073709551615
bytes em um sistema de 32 bits. - Perguntar; leia 4096 bytes. (Tamanho do buffer alocado na memória a partir de informações estatísticas.)
- Uma string curta é lida, ou seja, 18 bytes.
- Verifique se é necessário um furo, não.
- Grave o buffer no destino.
- Subtraia 18 do tamanho máximo de leitura.
- Perguntar; leia 4096 bytes.
- 0 bytes, pois todos foram consumidos na primeira leitura.
- Retorno com sucesso.
- Começa com tamanho máximo de leitura de MAXINT.
- Tudo bem. Atualize sinalizadores para arquivo.
- MULTAR.
Responder2
Rsync temcódigoque verifica especificamente se um arquivo está truncado durante a leitura e fornece este erro - ENODATA
. Não seipor queos arquivos /sys
têm esse comportamento, mas como não são arquivos reais, acho que não é muito surpreendente. Não parece haver uma maneira de dizer ao rsync para pular esta verificação específica.
Acho que é melhor não sincronizar novamente /sys
e usar scripts específicos para selecionar as informações específicas desejadas (como o endereço da placa de rede).
Responder3
Pode estar relacionado, mas as chamadas de atributos estendidos falharão no sysfs:
[root@hypervisor eth0]# endereço lsattr
lsattr: ioctl inapropriado para dispositivo ao ler sinalizadores no endereço
[root@hipervisor eth0]#
Olhando para o meu strace, parece que o rsync tenta extrair atributos estendidos por padrão:
22964 <... getxattr retomado> , 0x7fff42845110, 132) = -1 ENODATA (Nenhum dado disponível)
Tentei encontrar um sinalizador para fornecer o rsync para ver se pular atributos estendidos resolve o problema, mas não consegui encontrar nada ( --xattrs
os transformasobreno destino).
Responder4
O Rsync normalmente lê as informações do arquivo, transfere o conteúdo do arquivo ou delta para um arquivo temporário no diretório de destino e, após verificar os dados do arquivo, ele o renomeia para o nome do arquivo de destino.
Acredito que o problema com o sysfs é que todos os arquivos são exibidos como 4k (uma página de memória), mas podem conter apenas alguns bytes. Para evitar a cópia de um arquivo potencialmente corrompido para o destino, o rsync cancela a cópia quando detecta uma incompatibilidade entre os metadados do arquivo e o que foi realmente copiado.
Pelo menos no rsync v3.0.6 esse comportamento pode ser evitado usando a --inplace
opção. O Rsync ainda detectará erros, mas como os arquivos de destino já terão sido sobrescritos, os arquivos potencialmente corrompidos permanecerão lá.
Observe, porém, que um efeito colateral disso é que os arquivos acabam sendo preenchidos com zeros para 4k, pois esse é o tamanho que o rsync pensa que os arquivos têm. Na maioria dos casos, isso não deve fazer diferença, pois os bytes nulos geralmente são ignorados.