Linux

為什麼 rsync 在 Linux 中無法從 /sys 複製文件?

  • February 23, 2018

我有一個用於rsync在 Archlinux 中備份文件的 bash 腳本。我注意到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失敗,是否可以用它複製文件?

Rsync 具有專門檢查文件在讀取期間是否被截斷並給出此錯誤的程式碼ENODATA- . 我不知道為什麼其中的文件/sys有這種行為,但由於它們不是真正的文件,我想這並不奇怪。似乎沒有辦法告訴 rsync 跳過這個特定的檢查。

我認為你最好不要 rsync/sys並使用特定的腳本來挑選你想要的特定資訊(比如網卡地址)。

首先/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 Filesystem


/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塊。根 (stat /sys) 的 inode 也是 1。/stat/fs通常具有 inode 2。等等。

rsync 與 cp

同步偽文件的 rsync 失敗的最簡單解釋可能是通過範例。

假設我們有一個名為address18 字節的文件。一個lsstat的文件報告 4096 字節。


rsync

  1. 打開文件描述符 fd。
  2. 使用 fstat(fd) 獲取大小等資訊。
  3. 開始讀取 size 字節,即 4096。那將是@mattdm連結的程式碼的第 253 行read_size == 4096
  4. 問; 讀取:4096 字節。
  5. 讀取一個短字元串,即 18 個字節。nread == 18
  6. read_size = read_size - nread (4096 - 18 = 4078)
  7. 問; 讀取:4078 字節
  8. 讀取 0 個字節(因為第一次讀取消耗了文件中的所有字節)。
  9. nread == 0第 255 行
  10. 無法讀取4096字節。清零緩衝區。
  11. 設置錯誤ENODATA
  12. 返回。
  13. 報告錯誤。
  14. 重試。(以上循環)。
  15. 失敗。
  16. 報告錯誤。
  17. 美好的。

在此過程中,它實際上會讀取整個文件。但是由於沒有可用的大小,它無法驗證結果——因此失敗是唯一的選擇。

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. 嘗試通過 extent-copy 讀取文件(一種複制普通 稀疏文件的更有效方法),但失敗。 5. 通過稀疏複製進行複制。

  1. 從 MAXINT 的最大讀取大小開始。
    通常 18446744073709551615是 32 位系統上的字節。
  2. 問; 讀取 4096 字節。(根據統計資訊在記憶體中分配的緩衝區大小。)
  3. 讀取一個短字元串,即 18 個字節。
  4. 檢查是否需要一個孔,不。
  5. 將緩衝區寫入目標。
  6. 從最大讀取大小中減去 18。
  7. 問; 讀取 4096 字節。
  8. 第一次讀取時消耗了 0 個字節。
  9. 返回成功。
  10. 一切都好。更新文件的標誌。
  11. 美好的。

引用自:https://unix.stackexchange.com/questions/73569