Почему rsync не может скопировать файлы из / sys в Linux?

12

У меня есть скрипт bash, который используется rsyncдля резервного копирования файлов в Archlinux. Я заметил, что rsyncне удалось скопировать файл /sys, хотя cpработал нормально:

# 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

Интересно, почему не получается rsync, и возможно ли скопировать файл вместе с ним?

Евгений Ярмаш
источник
4
Почему вы хотите скопировать /sys/?
frostschutz
1
@frostschutz Я использую команду в OP, чтобы скопировать MAC-адрес сетевой карты (в виде файла)
Евгений Ярмаш
@eugeney Итак, почему недостаточно сделать резервную копию файла конфигурации, из которого установлен MAC-адрес?
depquid
@eugeney Можно ли даже написать /sys/class/net/*/address(я получаю «разрешение отказано», когда я пытаюсь это сделать)? Если нет, то вы не создаете реальную / полезную резервную копию, поскольку ее невозможно восстановить.
depquid

Ответы:

12

Rsync имеет код, который специально проверяет, урезан ли файл во время чтения, и выдает эту ошибку - ENODATA. Я не знаю, почему файлы /sysимеют такое поведение, но так как они не настоящие файлы, я думаю, это не слишком удивительно. Похоже, нет способа заставить rsync пропустить эту конкретную проверку.

Я думаю, что вам, вероятно, лучше не использовать rsyncing /sysи использовать специальные сценарии, чтобы выбрать нужную информацию (например, адрес сетевой карты).

mattdm
источник
Пффф, где удовольствие в том, чтобы не выяснить, почему Rsync, в частности, терпит неудачу?
Братчли
Извините, мне было непонятно. Rsync специально проверяет файлы, усеченные во время чтения, и выдает эту ошибку.
mattdm
4
Я бы предположил, что у них такое поведение, потому что, пока вы на самом деле не прочитаете их, то, что «там», не совсем точно; чтение действительно запрос динамической информации от ядра. Поэтому ядро ​​не пытается заранее предоставить точную информацию WRT о размере файла и т. Д., И, как вы отметили, rsync воспринимает такое расхождение как плохой признак.
Златовласка
11

Прежде всего /sys, это псевдо файловая система . Если вы посмотрите на них, /proc/filesystemsвы найдете список зарегистрированных файловых систем, где их довольно много nodev . Это указывает на то, что они являются псевдофайловыми системами . Это означает, что они существуют в работающем ядре как файловая система на основе RAM. Далее они не требуют блочного устройства.

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

При загрузке ядро ​​монтирует эту систему и обновляет записи, когда подходит. Например, когда новое оборудование найдено во время загрузки или udev.

У /etc/mtabвас обычно встречается монтировка:

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

Прочитайте статью Патрика Мохеля «Файловая система sysfs», чтобы прочитать хорошую статью на эту тему .


статистика файлов / sys

Если вы войдете в каталог /sysи выполните команду a, ls -lвы заметите, что все файлы имеют один размер. Обычно 4096 байт. Об этом сообщает 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
...

Далее вы можете сделать statфайл и заметить другую особенность; это занимает 0 блоков. Кроме того, индекс root (stat / sys) равен 1. Как /stat/fsправило, индекс 2. и т. Д.

rsync против cp

Возможно, самое простое объяснение сбоя синхронизации псевдо-файлов в rsync - это пример.

Скажем, у нас есть файл с именем address18 байтов. Файл lsили statфайл сообщает 4096 байт.


Rsync

  1. Открывает дескриптор файла, fd.
  2. Использует fstat (fd) для получения такой информации, как размер.
  3. Задайте чтение байтов размера, т.е. 4096. Это будет строка 253 кода, связанного с @mattdm .read_size == 4096
    1. Спросить; читать: 4096 байт.
    2. Короткая строка читается, т.е. 18 байтов. nread == 18
    3. read_size = read_size - nread (4096 - 18 = 4078)
    4. Спросить; прочитано: 4078 байт
    5. 0 байт прочитано (поскольку первое чтение потребляет все байты в файле).
    6. nread == 0, Линия 255
    7. Невозможно прочитать 4096байты. Обнуление буфера.
    8. Установить ошибку ENODATA.
    9. Возвращение.
  4. Сообщить об ошибке.
  5. Retry. (Выше петли).
  6. Провал.
  7. Сообщить об ошибке.
  8. FINE.

Во время этого процесса он фактически читает весь файл. Но при отсутствии доступного размера он не может проверить результат - таким образом, отказ является единственным вариантом.

ср

  1. Открывает дескриптор файла, fd.
  2. Использует fstat (fd) для получения информации, такой как st_size (также использует lstat и stat).
  3. Проверьте, не является ли файл редким. То есть файл имеет дыры и т. Д.

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

    Поскольку statфайл отчетов имеет нулевые блоки, он классифицируется как разреженный.

  4. Пытается прочитать файл с помощью экстент-копии (более эффективный способ копирования обычных разреженных файлов) и завершается неудачно.

  5. Копировать по разреженным копиям.
    1. Начинается с максимального размера чтения MAXINT.
      Обычно 18446744073709551615байты в 32-битной системе.
    2. Спросить; читать 4096 байт. (Размер буфера выделяется в памяти из статистической информации.)
    3. Короткая строка читается, т.е. 18 байтов.
    4. Проверьте, нужна ли дыра, нет.
    5. Записать буфер в цель
    6. Вычтите 18 из максимального размера чтения.
    7. Спросить; читать 4096 байт.
    8. 0 байт, поскольку все они были использованы в первом чтении.
    9. Верните успех.
  6. Все ок. Обновить флаги для файла.
  7. FINE.
Runium
источник
2

Может быть связано, но вызовы расширенных атрибутов не будут работать на sysfs:

[root @ hypervisor eth0] # адрес lsattr

lsattr: неподходящий ioctl для устройства при чтении флагов по адресу

[root @ гипервизор eth0] #

Глядя на мой список, похоже, что rsync пытается добавить расширенные атрибуты по умолчанию:

22964 <... getxattr возобновлено>, 0x7fff42845110, 132) = -1 ENODATA (данные отсутствуют)

Я пытался найти флаг , чтобы дать Rsync , чтобы увидеть , если пропустить расширенные атрибуты решает эту проблему , но не смог найти что - нибудь ( --xattrsпревращает их на месте назначения).

Bratchley
источник
0

Rsync обычно читает информацию файла, передает содержимое файла или дельту во временный файл в каталоге назначения, затем после проверки данных файла переименовывает его в имя файла назначения.

Я считаю, что проблема с sysfs заключается в том, что все файлы отображаются как 4 КБ (одна страница памяти), но они могут содержать только несколько байтов. Чтобы избежать копирования потенциально поврежденного файла в место назначения, rsync отменяет копию, когда обнаруживает несоответствие между метаданными файла и тем, что было фактически скопировано.

По крайней мере на rsync v3.0.6 такого поведения можно избежать с помощью --inplaceкоммутатора. Rsync по-прежнему будет обнаруживать ошибки, но поскольку файлы назначения уже будут перезаписаны, он оставит там потенциально поврежденные файлы.

Обратите внимание, что побочным эффектом этого является то, что файлы заканчиваются заполнением нулями до 4 КБ, так как это тот размер, который rsync считает для файлов. Это не должно иметь значения в большинстве случаев, поскольку нулевые байты обычно игнорируются.

Томас Гайот-Сионнест
источник