เหตุใด rsync จึงไม่สามารถคัดลอกไฟล์จาก / sys ใน Linux


12

ฉันมีสคริปต์ทุบตีซึ่งใช้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 ของการ์ดเครือข่าย (เป็นไฟล์)
Eugene Yarmash

@eugeney เหตุใดจึงไม่เพียงพอที่จะสำรองไฟล์กำหนดค่าที่ตั้งที่อยู่ MAC ไว้
depquid

@eugeney เป็นไปได้ไหมที่จะเขียนถึง/sys/class/net/*/address(ฉันได้รับ "ปฏิเสธสิทธิ์" เมื่อฉันลอง)? หากไม่แสดงว่าคุณไม่ได้ทำการสำรองข้อมูลจริง / มีประโยชน์เนื่องจากไม่สามารถกู้คืนได้
ลดลง

คำตอบ:


12

rsync มีรหัสซึ่งการตรวจสอบโดยเฉพาะถ้าแฟ้มถูกตัดทอนในระหว่างการอ่านและให้ข้อผิดพลาดนี้ ENODATA- ฉันไม่รู้ว่าทำไมไฟล์ต่าง ๆ/sysมีพฤติกรรมนี้ แต่เนื่องจากมันไม่ใช่ไฟล์จริงฉันจึงเดาว่ามันไม่น่าแปลกใจเลย ดูเหมือนจะไม่มีวิธีบอก rsync ให้ข้ามการตรวจสอบนี้โดยเฉพาะ

ฉันคิดว่าคุณน่าจะดีกว่าที่จะไม่ทำการซิงโครไนซ์/sysและใช้สคริปต์เฉพาะเพื่อเลือกข้อมูลเฉพาะที่คุณต้องการ (เช่นที่อยู่การ์ดเครือข่าย)


Pfft ความสนุกในการหาสาเหตุที่ rsync โดยเฉพาะล้มเหลวที่ไหน
Bratchley

ขออภัยฉันไม่ชัดเจน Rsync จะตรวจสอบไฟล์ที่ถูกตัดในระหว่างการอ่านและการโยนข้อผิดพลาดนี้โดยเฉพาะ
mattdm

4
ฉันคิดว่าพวกเขามีพฤติกรรมนี้เพราะจนกว่าคุณจะอ่านจริงสิ่งที่ "มี" ไม่แน่นอนอย่างแน่นอน การอ่านเป็นการร้องขอข้อมูลแบบไดนามิกจากเคอร์เนล ดังนั้นเคอร์เนลจึงไม่พยายามที่จะให้รายละเอียดที่ถูกต้องกับขนาดไฟล์ ฯลฯ ล่วงหน้าและเมื่อคุณชี้ให้เห็นว่า rsync ใช้ความแตกต่างเช่นนี้เป็นสัญญาณที่ไม่ดี
goldilocks

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

สำหรับกระดาษที่ดีในเรื่องที่อ่าน Patric Mochel ของ - The sysfs ระบบแฟ้ม


สถิติของ / 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 ของ root (stat / sys) คือ 1 /stat/fsโดยปกติจะมี inode 2 เป็นต้น

rsync กับ cp

คำอธิบายที่ง่ายที่สุดสำหรับความล้มเหลว rsync ของการซิงโครไนไฟล์หลอกอาจเป็นตัวอย่าง

สมมติว่าเรามีไฟล์ชื่อaddress18 ไบต์ lsหรือstatของแฟ้มรายงาน 4096 ไบต์


rsync

  1. เปิดไฟล์ descriptor, fd
  2. ใช้ fstat (fd) เพื่อรับข้อมูลเช่นขนาด
  3. ออกไปอ่านไบต์ขนาดคือ 4096 ที่จะเป็นสาย 253ของรหัสที่เชื่อมโยงโดย@mattdmread_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. ละเอียด.

ในระหว่างกระบวนการนี้มันจะอ่านไฟล์ทั้งหมด แต่หากไม่มีขนาดจึงไม่สามารถตรวจสอบความถูกต้องของผลการทดสอบได้

ซีพี

  1. เปิดไฟล์ descriptor, 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 @ hypervisor eth0] # lsattr ที่อยู่

lsattr: ioctl ที่ไม่เหมาะสมสำหรับอุปกรณ์ในขณะที่อ่านธงที่อยู่

[root @ hypervisor eth0] #

ดู strace ของฉันดูเหมือนว่า rsync จะพยายามดึงคุณสมบัติเพิ่มเติมตามค่าเริ่มต้น:

22964 <... getxattr ทำงานต่อ>, 0x7fff42845110, 132) = -1 ENODATA (ไม่มีข้อมูล)

ฉันพยายามค้นหาแฟล็กเพื่อให้ rsync เพื่อดูว่าการข้ามแอททริบิวต์แบบขยายแก้ไขปัญหาได้หรือไม่ แต่ไม่สามารถหาสิ่งใดได้ ( --xattrsเปิดใช้งานที่ปลายทาง)


0

ปกติแล้ว Rsync จะอ่านข้อมูลของไฟล์ถ่ายโอนเนื้อหาของไฟล์หรือของเดลต้าไปยังไฟล์ชั่วคราวในไดเรกทอรีปลายทางจากนั้นหลังจากตรวจสอบข้อมูลของไฟล์แล้วจะเปลี่ยนชื่อเป็นชื่อไฟล์ปลายทาง

ฉันเชื่อว่าปัญหากับ sysfs คือไฟล์ทั้งหมดแสดงเป็น 4k (หน้าหน่วยความจำหนึ่งหน้า) แต่พวกเขาอาจมีเพียงไม่กี่ไบต์ เพื่อหลีกเลี่ยงการคัดลอกไฟล์ที่อาจเกิดความเสียหายไปยังปลายทาง rsync ยกเลิกการคัดลอกเมื่อมันเห็นไม่ตรงกันระหว่างข้อมูลเมตาของไฟล์และสิ่งที่ถูกคัดลอกจริง

อย่างน้อยใน rsync v3.0.6 พฤติกรรมนี้สามารถหลีกเลี่ยงได้โดยใช้--inplaceสวิตช์ Rsync จะยังคงตรวจจับข้อผิดพลาด แต่เนื่องจากไฟล์ปลายทางจะถูกเขียนทับเมื่อมันจะทิ้งไฟล์ที่เสียหาย

โปรดทราบว่าผลข้างเคียงของมันคือไฟล์ท้ายเป็นศูนย์เบาะถึง 4k เช่นนี้เป็นขนาด rsync คิดว่าไฟล์ที่เป็น ไม่ควรสร้างความแตกต่างในกรณีส่วนใหญ่เนื่องจากโดยปกติแล้วไบต์ที่ไม่มีค่าจะถูกละเว้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.