web-dev-qa-db-ja.com

cp / rsyncで拡張属性を保持する

cpを使用してコピーする場合、明示的な属性であっても、拡張属性は保持されません。

cp -a --preserve=all /source /dest

または

cp -a --preserve=xattr /source /dest

同じことはrsyncでも同じです。

rsync -aq -A -X --delete /source /dest

ただし、宛先ファイルシステムでは、手動で(chattrを使用して)拡張属性を作成できます。これは、ターゲットファイルシステムがxattrをサポートすることを意味します。

xattrcpまたはrsyncで保存できないのはなぜですか?

追加情報:

  • ソースとターゲットの両方のファイルシステムはext4です
  • ソースとターゲットの両方のファイルシステムがローカル(nfsではない)である
  • 私はDebian Wheezyを使用しています
12
Martin Vegter

更新

これをいじって、chattrと他のe2fsprogsのコードを見てみると、chattrで設定された属性とlibattrで設定された属性(たとえば、setfattrコマンドを使用)は非常に異なっていることがわかります。 chattrは、extファイルシステムフラグを設定します。これらのフラグは、名前付き属性または名前空間にマップされません。 なしlibattrlistxattrへの呼び出しで表示されます。これらはおそらくすべき以下で想定されるようにsystem名前空間の名前付き属性にマップされますが、現時点ではこれは完全に実装されていません。また、以下の属性の1つへのマッピングと間違えたsystem.posix_acl_access属性は、extファイルシステムフラグとは関係なく、アクセス制御リストと関係しています。関連するstraceメッセージはすべてのファイルに対して表示され、cp --preserve=xattrのみが使用されると表示されなくなります。

chattrによって設定された属性はextファイルシステムに固有であり、それらに影響を与える唯一の方法はe2fsprogsツールを使用することです。実際、manページでは、実際には「拡張属性」という用語ではなく、「ファイル属性」という用語を使用しています。 「実際の」拡張属性は、libattrで変更できる名前と値のペアであり、複数のファイルシステムに実装されています。これらは、cpおよびrsyncが検索し、正しいオプションが指定されたときにコピーされたファイルに転送するものです。ただし、system名前空間は、chattr属性を名前に、最終的には他のファイルシステムの同等の属性にマップするために存在するようですが、現時点では機能しません。

いくつかの良い情報がありますので、元の回答はそのままにしておきますが、ポイントではかなり間違っています。

アップデート2

私は今までにこれに戻ってきたはずですが、- この答え に従って、chattrは単なるextファイルシステムでは機能しません。 Wikipedia によると、これはBSDベースのシステムのchflagsコマンドと同等です。

いくつかのファイルシステムでこれらの属性の設定と読み取りをテストするスクリプトを書いて、次の結果を得ました。

ext4:
suS-iadAcj-t-e-- mnt/test_file
suSDiadAcj-tTe-- mnt/test_dir

reiserfs:
lsattr: Inappropriate ioctl for device While reading flags on mnt/test_file
lsattr: Inappropriate ioctl for device While reading flags on mnt/test_dir

xfs:
--S-iadA-------- mnt/test_file
--S-iadA-------- mnt/test_dir

btrfs:
--S-iadAc------C mnt/test_file
--SDiadAc------C mnt/test_dir

Wikipediaにいくつかの機能があると記載されているにもかかわらず、reiserfsファイルフラグを読み取ったり設定したりしようとすると、上記のエラーが発生します。 reiser4はテストしていません。また、cフラグをext4に設定することもできますが、これは優先されません。これらのフラグに影響するチューニング/マウントオプションもあるかもしれませんが、見つかりませんでした。

ただし、現在、chattrはLinuxでこれらの属性を変更できる唯一のユーティリティであるため、これらの属性を保持できるコピーユーティリティはありません。

元の回答

rsyncの理由は、試してさえいないためだと思われます。 rsyncドキュメントの-Xセクションから:

For systems that support extended-attribute namespaces, a copy being done by a
super-user copies all namespaces except system.*.  A normal user only  copies
the user.* namespace.

chattrおよびlsattrで使用される属性文字を、ファイルシステムで使用される基本的な名前付き属性にマップすることは困難です(インターネット上にリストがない場合)。しかし、私のテストでは、A属性はsystem.posix_acl_access属性にマップされ、これはsystem名前空間であるため、rsyncはそれをコピーしようとしません。manスニペットで言及されていない他の2つの名前空間は、trustedsecurityです。これらを設定するにはroot権限が必要です(そしてrsyncはこれなしでは試せません)。

おそらく、設定しようとした属性は、systemが無視するrsync名前空間に含まれます(おそらく賢明です)。それか、そうでないものを取得するにはrootになる必要があります。

cpについては、バグが発生しているようです。cp -astraceを実行すると、次の2つの興味深い行が得られます。

fgetxattr(3, "system.posix_acl_access", 0x7fff5181c0e0, 132) = -1 ENODATA (No data available)

そして

fsetxattr(4, "system.posix_acl_access", "\x02\x00\x00\x00\x01\x00\x06\x00\xff\xff\xff\xff\x04\x00\x04\x00\xff\xff\xff\xff \x00\x04\x00\xff\xff\xff\xff", 28, 0) = 0

最初に、fgetxattr呼び出しはデータを返しません(おそらくデータがないため-属性の存在で十分です)、それでも何らかの理由でcpは28バイトの(ジャンク?)データを見つけて宛先ファイルの属性値として設定します。これはcpのバグのようですが、実際には属性を設定せずにlibattr呼び出しが成功した場合に0を返すため、問題の原因はfsetattrのバグのようです。

ext4でマウントするかどうかに関係なく、user_xattrでこの動作が発生します。 「一部のシステム」では拡張属性が機能するためにこのマウントオプションが必要であると言う以外に、これに関するドキュメントは見つかりません。一見私のもの(Debian Jessie)はそうではない。私が見逃したマウントの問題があっても、fsetattr、つまりcpがサイレントに失敗するのは誤りです。

実際には、user_xattrext2reiserfsなどのext3が必要です。 ext4の場合は必要ありません

また、attrツールsetfattrgetfattrattr(後者はXFS専用であると記載されていますが、ext4の他のツールと同様に機能するようです)は、user名前空間以外では機能しません。 setfattrを使用してsystem名前空間に属性を配置しようとすると、Operation not supportedが表示されます(または、このように名前空間がない bug )。 setfattrは、trustedおよびsecurity名前空間で成功しているように見えますが、getfattrは何も読み込めず、systemによって設定されたchattr名前空間から何も読み込めません。 chattrが成功する理由は、ioctlではなくlibattr呼び出しを使用するためです。

ただし、完全に機能するのは、userを使用してsetfattr名前空間に拡張属性を設定し、rsyncまたはcpを使用してそれらをそのままコピーします(属性の作成時に値を指定しない場合は、cpでも問題はありません)。結論としては、system名前空間の値を使用することは現在 バギーおよび/または サポートされていません、少なくともDebianとおそらく他のディストリビューションでも。おそらくrsync開発者はこれを知っているため、無視されます。

14
Graeme