Чому 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 Я використовую команду в ОП, щоб скопіювати MAC-адресу мережевої карти (як файл)
Євген Ярмаш,

@eugeney Отже, чому не достатньо резервного копіювання файлу конфігурації, з якого встановлено MAC-адресу?
декап

@eugeney Чи це навіть можна написати /sys/class/net/*/address(коли я намагаюся отримати "дозвіл відмовлено")? Якщо ні, то ви не створюєте справжню / корисну резервну копію, оскільки її неможливо відновити.
декап

Відповіді:


12

У Rsync є код, який спеціально перевіряє, чи файл усічений під час читання, і видає цю помилку - ENODATA. Я не знаю, чому файли /sysмають таку поведінку, але оскільки вони не справжні файли, я думаю, це не надто дивно. Здається, не існує способу сказати rsync пропустити цю перевірку.

Я думаю, вам, мабуть, краще не рисинсувати /sysта використовувати конкретні сценарії, щоб вибрати потрібну інформацію (наприклад, адресу мережевої картки).


Pfft, де цікаво, якщо не з'ясувати, чому саме rsync не вдається?
Братчлі

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

4
Я б припустив, що вони мають таку поведінку, тому що, поки ви їх фактично не прочитаєте, те, що "є", не є абсолютно впевненим; read - це справді запит на динамічну інформацію від ядра. Тому ядро ​​не намагається заздалегідь дати точні деталі WRT до розміру файлу тощо, і, як ви зазначаєте, rsync сприймає таку розбіжність як поганий знак.
goldilocks

11

По-перше, /sysце файлова система псевдо . Якщо ви подивитесь, /proc/filesystemsви знайдете список зареєстрованих файлових систем, де їх досить багато nodev попереду. Це означає, що вони є псевдофайловими системами . Це означає, що вони існують на запущеному ядрі як файлова система на основі ОЗУ. Далі вони не потребують блокового пристрою.

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

Під час завантаження ядра монтують цю систему та оновлює записи, коли вони підходять. Наприклад, коли під час завантаження або користування знайдено нове обладнання udev.

У /etc/mtabви зазвичай знайти кріплення з допомогою:

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

Для приємного документу на цю тему прочитайте статті Патріка Мочеля - Файлова система sysfs .


stat з / sys файлів

Якщо ви ввійдете в каталог під /sysі 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 блоків. Також inode кореня (stat / sys) дорівнює 1. /stat/fsЗазвичай має inode 2. і т.д.

rsync vs. cp

Найпростіше пояснення несправності rsync синхронізації псевдофайлів, можливо, на прикладі.

Скажімо, у нас є ім'я файлу, addressякий становить 18 байт. 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. Повторіть спробу. (Вище петлі).
  6. Збій.
  7. Повідомити про помилку.
  8. ТОЧО.

Під час цього процесу він фактично зчитує весь файл. Але не маючи доступного розміру, він не може підтвердити результат - тому невдача є єдиним варіантом.

cp

  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. ТОЧО.

2

Можливо, пов'язано, але розширені дзвінки атрибутів не спрацюють у sysfs:

[root @ гіпервізор eth0] # lsattr адреса

lsattr: Невідповідний ioctl для пристрою Під час читання прапорів за адресою

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

Якщо дивитися на мій страйс, схоже, rsync намагається залучити розширені атрибути за замовчуванням:

22964 <... getxattr відновлено>, 0x7fff42845110, 132) = -1 ENODATA (даних немає)

Я намагався знайти прапор , щоб дати Rsync , щоб побачити , якщо пропустити розширені атрибути вирішує цю проблему , але не зміг знайти що - небудь ( --xattrsперетворює їх на місці призначення).


0

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

Я вважаю, що проблема із системою sysfs полягає в тому, що всі файли відображаються як 4k (одна сторінка пам'яті), але вони можуть містити лише кілька байтів. Щоб уникнути копіювання потенційно пошкодженого файлу до пункту призначення rsync скасовує копію, коли виявляється невідповідність метаданих файлу та того, що було фактично скопійовано.

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

Зауважте, що побічним ефектом цього є те, що файли закінчуються нульовим значенням до 4k, оскільки це розмір rsync вважає файли. У більшості випадків це не має значення, оскільки нульові байти зазвичай ігноруються.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.