web-dev-qa-db-ja.com

Linuxでrsyncが/ sysからファイルをコピーできないのはなぜですか?

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が失敗するのでしょうか。それを使用してファイルをコピーすることは可能ですか?

12
Eugene Yarmash

Rsyncには code があり、読み取り中にファイルが切り捨てられているかどうかを確認し、このエラーを表示します— ENODATAなぜ/sysのファイルにこのような動作があるのか​​はわかりませんが、実際のファイルではないため、そうではありません。意外。この特定のチェックをスキップするようにrsyncに指示する方法はないようです。

おそらく、/sysをrsyncせずに、特定のスクリプトを使用して、必要な特定の情報(ネットワークカードのアドレスなど)を抽出する方がよいでしょう。

12
mattdm

最初に_/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ファイルの統計

_/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対cp

疑似ファイルの同期のrsync失敗の最も簡単な説明は、おそらく例によるものです。

18バイトのaddressという名前のファイルがあるとします。ファイルのlsまたはstatは4096バイトを報告します。


rsync

  1. ファイル記述子fdを開きます。
  2. サイズなどの情報を取得するには、fstat(fd)を使用します。
  3. サイズのバイト、つまり4096を読み取るように設定します。これは @ mattdm によってリンクされたコードの 253行目 になります。 _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. エクステントコピー((normalスパースファイルをコピーするためのより効率的な方法))によってファイルを読み取ろうとして失敗します。

  5. スパースコピーでコピーします。
    1. MAXINTの最大読み取りサイズで開始します。
      32ビットシステムでは、通常_18446744073709551615_バイト。
    2. 尋ねる; 4096バイトを読み取ります。 (統計情報からメモリに割り当てられたバッファサイズ。)
    3. 短い文字列、つまり18バイトが読み取られます。
    4. いいえ、穴が必要かどうかを確認してください。
    5. ターゲットにバッファを書き込みます。
    6. 最大読み取りサイズから18を引きます。
    7. 尋ねる; 4096バイトを読み取ります。
    8. 最初の読み取りですべてが消費されるため、0バイト。
    9. 成功を返す。
  6. 大丈夫。ファイルのフラグを更新します。
  7. ファイン。
11
Runium

関連している可能性がありますが、拡張属性の呼び出しはsysfsで失敗します。

[root @ hypervisor eth0]#lsattrアドレス

lsattr:アドレスのフラグを読み取っているときにデバイスに不適切なioctl

[root @ hypervisor eth0]#

私のstraceを見ると、rsyncがデフォルトで拡張属性を取得しようとしているように見えます。

22964 <... getxattr resumed>、0x7fff42845110、132)= -1 ENODATA(データなし)

拡張属性をスキップすることで問題が解決するかどうかを確認するためにrsyncにフラグを見つけようとしましたが、何も見つけることができませんでした(--xattrsそれらをオンにしますon宛先で)。

2
Bratchley

Rsyncは通常、ファイルの情報を読み取り、ファイルの内容またはデルタを宛先ディレクトリの一時ファイルに転送し、ファイルのデータを確認した後、ファイル名を宛先ファイル名に変更します。

Sysfsの問題は、すべてのファイルが4k(1つのメモリページ)を示しているにもかかわらず、数バイトしか含まれていない可能性があることです。破損の可能性があるファイルを宛先にコピーしないようにするために、rsyncは、ファイルのメタデータと実際にコピーされたものとの不一致を検出すると、コピーをキャンセルします。

少なくともrsync v3.0.6では、--inplaceスイッチを使用してこの動作を回避できます。 Rsyncはエラーを検出しますが、宛先ファイルはすでに上書きされているため、破損している可能性のあるファイルがそこに残ります。

ただし、rsyncがファイルと見なしているサイズであるため、ファイルの結果として4kまでゼロが埋め込まれることに注意してください。 nullバイトは通常無視されるため、ほとんどの場合、違いはありません。