Archlinuxのファイルをバックアップするためにrsync
を使用する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には code があり、読み取り中にファイルが切り捨てられているかどうかを確認し、このエラーを表示します— ENODATA
。 なぜ/sys
のファイルにこのような動作があるのかはわかりませんが、実際のファイルではないため、そうではありません。意外。この特定のチェックをスキップするようにrsyncに指示する方法はないようです。
おそらく、/sys
をrsyncせずに、特定のスクリプトを使用して、必要な特定の情報(ネットワークカードのアドレスなど)を抽出する方がよいでしょう。
最初に_/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's – The sysfs Filesystem を参照してください。
_/sys
_の下のディレクトリに移動して_ls -l
_を実行すると、すべてのファイルのサイズが1つであることがわかります。通常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ブロックを占めます。また、ルートのiノード(stat/sys)は1です。_/stat/fs
_には通常iノード2があります。
疑似ファイルの同期のrsync失敗の最も簡単な説明は、おそらく例によるものです。
18バイトのaddress
という名前のファイルがあるとします。ファイルのls
またはstat
は4096バイトを報告します。
read_size == 4096
_ nread == 18
_read_size = read_size - nread (4096 - 18 = 4078)
nread == 0
_、 255行目4096
_バイトを読み取れません。ゼロアウトバッファ。ENODATA
を設定します。このプロセス中に、ファイル全体を実際に読み取ります。しかし、使用可能なサイズがないと、結果を検証できません。したがって、失敗は唯一の選択肢です。
ファイルがスパースである可能性が高いかどうかを確認してください。つまり、ファイルには穴などがあります。
_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
レポートファイルはブロックがゼロであるため、スパースとして分類されます。
エクステントコピー((normalスパースファイルをコピーするためのより効率的な方法))によってファイルを読み取ろうとして失敗します。
18446744073709551615
_バイト。関連している可能性がありますが、拡張属性の呼び出しはsysfsで失敗します。
[root @ hypervisor eth0]#lsattrアドレス
lsattr:アドレスのフラグを読み取っているときにデバイスに不適切なioctl
[root @ hypervisor eth0]#
私のstraceを見ると、rsyncがデフォルトで拡張属性を取得しようとしているように見えます。
22964 <... getxattr resumed>、0x7fff42845110、132)= -1 ENODATA(データなし)
拡張属性をスキップすることで問題が解決するかどうかを確認するためにrsyncにフラグを見つけようとしましたが、何も見つけることができませんでした(--xattrs
それらをオンにしますon宛先で)。
Rsyncは通常、ファイルの情報を読み取り、ファイルの内容またはデルタを宛先ディレクトリの一時ファイルに転送し、ファイルのデータを確認した後、ファイル名を宛先ファイル名に変更します。
Sysfsの問題は、すべてのファイルが4k(1つのメモリページ)を示しているにもかかわらず、数バイトしか含まれていない可能性があることです。破損の可能性があるファイルを宛先にコピーしないようにするために、rsyncは、ファイルのメタデータと実際にコピーされたものとの不一致を検出すると、コピーをキャンセルします。
少なくともrsync v3.0.6では、--inplace
スイッチを使用してこの動作を回避できます。 Rsyncはエラーを検出しますが、宛先ファイルはすでに上書きされているため、破損している可能性のあるファイルがそこに残ります。
ただし、rsyncがファイルと見なしているサイズであるため、ファイルの結果として4kまでゼロが埋め込まれることに注意してください。 nullバイトは通常無視されるため、ほとんどの場合、違いはありません。