S3をs3fsでマウントしている環境で、アップロードされたファイルのパーミッションを、ディレクトリは0755、ファイルは0644にchmodするスクリプトがあり、だいぶ処理時間が掛かっているので改善できないか調べていました。
s3fs使ってS3にアクセスするのは非常に遅いため、通常のファイルシステムに対しての常識とはまた違った気遣いが必要になります。
最初のスクリプトは
find ./example -type d -exec chmod 0755 {} + find ./example -type f -exec chmod 0644 {} +
という感じだったので、これを1コマンドにまとめたら少なくとも倍速になるんでは、と思ったわけです。
こういうのってうまく書いたらchmodだけで出来ないのかなあ、とも思っていたのでtweetしたところ、@mnb0327さん、@tatsushi_dさん、@satoh_fumiyasuさんからリプいただきました。
というわけで簡単に書く方法はなくて、やはりfind使うかperlとかでごりごりやるしかない、という感じでした。
(2016/11/2 追記)
chmodだけでディレクトリに対してのみ+x出来る記述方法を教えていただきました。
chmod -R a=,u=rwX,go=rX ./example
「0755」系のビットフィールド使った指定ではなく、「x」系の指定で「X」を使うと、ディレクトリに対してのみ実行権限「x」を付けられるのですね。
知らんかった…
そこで教えていただいた方法や、対照実験用のchmod単体でやった場合など、いくつか試してtime取ってみました。
2回データ取ってよかったほうを採用しましたが、だいたい近い時間で処理されていました。
s3fs-1.74で約950ファイルに対して行っています。
time ./chmod.pl real 2m39.680s time chmod -R 0755 ./example real 2m44.186s time find ./example -exec chmod 0644 {} + real 2m47.660s time find ./example -type d -exec chmod 0755 {} + -o -type f -exec chmod 0644 {} + real 2m53.486s time find ./example -exec chmod 0755 {} + real 2m58.552s time find ./example -depth -type d -exec chmod 0755 {} + -o -type f -exec chmod 0644 {} + real 3m8.701s time (find ./example -type d -exec chmod 0755 {} +; find ./example -type f -exec chmod 0644 {} +) real 3m38.750s
chmod.pl
sub recursive { my ($dir) = @_; my @files = glob("$dir/*"); foreach my $file (@files) { if (-d $file) { system("chmod 0755 $file"); recursive($file); } else { system("chmod 0644 $file"); } } } recursive("./example");
(参考)ディレクトリの中をを再帰的にたどってすべてのファイルに対してなにかの処理をするには | 入出力・ファイル操作 | プログラミング言語の比較 | hydroculのメモ
結局、perlで書いたのが一番早く、その場合は単純にchmodで全部0755にしてしまうよりも早く処理が終わりました。
単純なchmodよりもperlのが早いというのはちょっと不思議ですが、他の処理も動いていたため揺れの範疇かもしれません。
そして、find で -o オプション使って処理を変えるものも、ほとんど遜色ない時間で処理が終わりました。
さらに意外だったのが、元々のfindを2回書くパターンが実はそれほど遅くないということで、だいたい2割増程度の時間で済んでいました。
(2016/11/2 追記)
エントリ書いた後、さらにこのようなアドバイスいただいたので
を追加テストしました。
今日は全体的にS3へのアクセス速度が早くなっていて昨日やったテストの時間と直接比較できないため、代表的なものを比較用に再度テストしています。
time chmod -R a=,u=rwX,go=rX ./example real 2m19.232s time chmod -R 0755 ./example real 2m22.987s time ./chmod2.pl real 2m26.634s time ./chmod.pl real 2m41.052s time find ./11434 -type d -exec chmod 0750 {} + -o -type f -exec chmod 0640 {} + real 3m18.127s time (find ./example -type f -print | xargs chmod 0644; find ./example -type d -print | xargs chmod 0755) real 3m19.146s
chmod2.pl
sub recursive { my ($dir) = @_; my @files = glob("$dir/*"); foreach my $file (@files) { if (-d $file) { chmod 0755, $file; recursive($file); } else { chmod 0644, $file; } } } recursive("./example");
というわけでchmodでラージ「X」使うのが一番良くて、記述ももっともスッキリしました。
アドバイスいただいた皆様、多謝です!!