web-dev-qa-db-ja.com

数千のファイルに対するchmod再帰的許可

これは、再帰的に「chmoding」することに関するより一般的な質問です。

ある時点で、数十万のファイルがあるフォルダのアクセス許可を再帰的に変更する必要があるこのスクリプトがあります。そのフォルダーには毎日新しいファイルが追加されますが、すでにそこにあるファイルは、アクセス許可がすでに設定されており、変更されません。

私の質問は...私が電話したとき

chmod 775。 -R 

既に適切なアクセス許可が設定されているファイルにアクセス許可を設定しようとしますか、それとも適切なアクセス許可を持たない新しいファイルにのみアクセス許可を設定しますか?

「新しい」ファイルはほんの数千であり、それらの権限をかなり迅速に実行する必要があるにもかかわらず、スクリプト内でこのコマンドを通過するには常に時間がかかるようです。

私はchmodのmanページを見てきましたが、このケースについては何も触れられていないようです。

Chmodが権限を事前にチェックしない場合、「find」と「chmod」の組み合わせを検討する必要がありますか?

16
Titi Dumi

chmodは、必要なものに既に設定されているファイルのアクセス許可を変更する場合と変更しない場合がありますが、変更しない場合でも、現在のアクセス許可が何であるかを確認する必要があります[0]。数十万のファイルがあるので、どちらにしても問題ないと思います。ほとんどの場合、時間はすべてのファイルをstatingツールで費やしています。

findを使用して、前回の実行より新しいファイル、またはchmodの実行が必要なファイルを確認することはできますが、速度が大幅に向上するとは思いません。

スクリプトで可能であれば、新しいファイルを最初に別のディレクトリに「保持」領域として配置できる場合があります。次に、chmod THATディレクトリ(新しいファイルのみが含まれる)を作成し、残りのファイルと一緒にmvできます。これはかなり高速になるはずですが、残念ながらすべてのアプリケーションで機能するわけではありません。

[0]変更を必要としないファイルのパーミッションを設定しようとしたとしても、基礎となるファイルシステムはおそらく不要なので、リクエストに対して何もしません。

9
mrb

検索/ chmod最適化

findchmodはどちらも読み取る必要があります

  1. すべてのディレクトリエントリ
  2. これらすべてのエントリのiノード

ディスクヘッドがディレクトリとiノードの間を移動しないため、最初にすべてのエントリを読み取ってから、(回転ディスク上の)すべてのiノードを読み取ることでパフォーマンスが向上する可能性があります。 chmodとしてisばかげている(他の回答の1つが説明しているように)findからのみ呼び出す必要があります。しかし、それでも最初の書き込みが行われる前にすべてのiノードを読み取ると役立つ場合があります(ディスクキャッシュに十分な空き容量があると想定した場合RAM)。これをお勧めします:

find . -printf "" # reading the file names only
find . ! -perm 775 -printf "" # reading all the inodes (file names are cached)
find . ! -perm 775 -exec chmod 775 + # writing to the cache without reading from disk

良い解決策:ACL

適切な解決策はまったく異なる可能性があります。ファイルがこのディレクトリに作成されている場合(他の場所から移動されていない場合)、ACLはその場で処理を実行できます。親ディレクトリにデフォルトのACLを設定するだけです。

ファイルシステムの最適化により、さらに改善される可能性があります。 ext3/ext4の場合は、e2fsck -D時々。このディレクトリを別のボリュームに配置すると役立つ場合があります。異なるファイルシステムまたはファイルシステム設定を試すことができます(たとえば、異なるiノードサイズ)。

10
Hauke Laging

Ubuntu 12.10で GNU coreutilsパッケージ からのchmodの使用を想定しています。

chmod 775 . -Rは、アクセス許可を変更する必要があるかどうかに関係なく、見つかった各ファイルに対してfchmodatシステムコールを実行します。これを確認するには、コードを調べ、strace chmod 775 . -R(下のスニペット)を使用して実際の動作をリストします。

newfstatat(4, "d", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "d", 0775)                  = 0
newfstatat(4, "c", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "c", 0775)                  = 0
newfstatat(4, "a", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "a", 0775)                  = 0
newfstatat(4, "b", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "b", 0775)                  = 0

各ファイルでfchmodatを実行することにはいくつかの欠点があります

  • 多数のファイルが変更された場合、余分なシステムコールが重要になる可能性があります。他の人が言及しているfind/xargs/chmodメソッドは、変更が必要なファイルのみを変更することで、おそらくより速くなります。
  • fchmodatを呼び出すと、各ファイルのファイルステータスの変更(ctime)が変更されます。これにより、すべてのファイル/ inodeが毎回変更され、ディスクへの書き込みが過剰になる可能性があります。マウントオプションを使用して、これらの過剰な書き込みを停止できる場合があります。

簡単な実験は、ストレートchmodで発生するctimeの変更を示しています

auser@duncow:/tmp/blah.test$ ls -lc
total 0
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 a
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 b
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 c
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 d
auser@duncow:/tmp/blah.test$ chmod 775 . -R
auser@duncow:/tmp/blah.test$ ls -lc
total 0
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 a
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 b
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 c
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 d

しかし、数分後のfind/xargs/chmodについては、これは変わりません

auser@duncow:/tmp/blah.test$ date
Tue Jun 18 18:27:27 BST 2013
auser@duncow:/tmp/blah.test$ find . ! -perm 775 -print0 | xargs -0 -I {} chmod 775 {}
auser@duncow:/tmp/blah.test$ ls -lc
total 0
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 a
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 b
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 c
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 d

Findは選択をより詳細に制御できるため、常にfind/xargs/chmodバージョンを使用する傾向があります。

8
Richm

coreutils/src/chmod.c#process_file は、 chmod(1) が常にモードの設定を試み、次に fstatat(2)

ファイルは fts(3) によって処理されます。データツリーを構築するには、すべてのトラバースファイルシステムオブジェクトを事前に stat(2) する必要があります。

バルクファイル操作の高速化 測定におけるUnixlore機能。ここで、chmod(1)は、find/xargsアプローチに対してタイミングがとられています。

ここで、元の質問に適応したコマンドライン:

find . -print0 | xargs -0 chmod 775

2つの理由:

  1. ファイルシステムトラバーサルは、2つのプロセス間のパイプを介したファイルの操作から切り離されます。これは、異なるコアで実行される場合さえあります。

    1. fts(3)はディレクトリツリーを「平坦化」するため、xargs(1)操作は最小化されます。

ですから、簡単な解決策としてfind/xargsを必ず使用してください。

別のオプション:

  • mask と、新しいファイルを書き込むプロセスのソースコードを試してください。

  • Linuxを使用している場合は、システムがinotifyカーネルサブシステムを有効にしている可能性があります。この場合、 inotifywait(1) を使用して、効率的なソリューションでスクリプトを作成できます。


補足:ファイルのアクセス許可を実行したくない場合は、呼び出しを次のように変更することをお勧めします。

find . -type f -print0 | xargs -0 chmod 664
find . -type d -print0 | xargs -0 chmod 775

編集者への注意:投稿に3つ以上のリンクを追加したり、他の投稿にコメントしたりすることは許可されていません。私はここにURLを残し、十分な評判のある寛容なユーザーがそれらをテキストに戻し、この段落を削除することを願っています。


find . -printf ""を使用した ディスクキャッシュの準備 に関するコメント:

これにより、次のchmod操作の実行速度が上がる場合がありますが、使用可能なメモリとI/O負荷によって異なります。だから、うまくいくかもしれません。トラバーサルのデカップリング(find)およびchmod操作はすでにキャッシングを提供しているため、キャッシュの準備は不要な場合があります。

1
Georg Lehner

ファイルを作成するプロセスを0775モードで作成するように変更することを検討しましたか?環境のumask値を見てください-0002が役立つかもしれません。

0
D McKeon