こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

find . -user hoge の代わりに。。

/home 以下で ユーザー hoge の全ファイルを抽出するのに、

find /home -user hoge

としていますが、とても遅く、そして何よりも、負荷が高くなりすぎます。
毎日実行する必要があり、他に同様のことを実現するベターな方法はないでしょうか。

locate はファイル名を検索するだけで、「ユーザー hoge を探す」方法が
ないように思います。

投稿日時 - 2012-07-06 03:57:17

QNo.7574653

すぐに回答ほしいです

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

「userがroot になっているファイルを毎日検索したいです」というセキュリティ用途っぽい感じなら、auditが使えるのではないかと思います。

auditはfindのように網羅的に今の状態を調べることはできませんが、ルールに合致したシステムコールを記録することができます。つまり、おそらくはrootが所有者となっているファイルが作られた場合 (uid=0のユーザーによるcreatシステムコールなど)、rootにchownされた場合(所有者をuid 0にするchownシステムコールなど)を記録に残すようにできます。

あるいは、SELinuxの機能を利用して、rootユーザーのファイルの作成を禁止することもできると思います。

auditはfindと違って、今の状態はわかりませんが、一度findしてからauditで監視しておけば、findした時からの差分とあわあせて、現在rootが所有しているファイルがわかるようになると思います。
所定のシステムコールの発行のたびにチェックされるのでその分遅くなりますが、あまり頻繁にファイルの作成はchownはしないと思うので、こちらのほうが総合的な負荷は低いかもしれません。

投稿日時 - 2012-07-07 11:20:20

お礼

そういう方法もあるんですね。auditの記述の仕方から勉強してみます。

投稿日時 - 2012-07-10 02:59:59

ANo.3

No1です。
>とたくさんユーザーとファイルがある中で、userがroot になっているファイルを毎日検索したいです。

となると、find以上に速い物はなさそうです。
速くなるかどうかわかりませんが、更新のファイルディレクトリが少ないのであれば、最近更新の掛かったディレクトリだけに限定するというのも考えられます。

find `find /home -type d -mtime -2 ` -maxdepth 1 -user root

ただし、これではroot所有の全部は検出できません。最近作られた物を含む一部だけです。昨日分と比較することで増えた物がわかるはず。

投稿日時 - 2012-07-06 20:56:42

お礼

最近の更新ディレクトリーだけに絞る最初のfindの時点で同じように負荷が大きくなり、
結局、過去のデータから当たりをつけて検索対象ディレクトリーを最初から絞り込むことにしました。
全部をすくい取ることはできそうもありませんが当面はこの運用でいくしかないと思いました。
ありがとございました。

投稿日時 - 2012-07-07 02:49:55

ANo.2

#1さんの回答に補足ですが、
特定のディレクトリーにしかユーザーのファイルがないとわかっているなら、locateでディレクトリーを絞り込んで、探す範囲を限定してから、statでユーザーを絞り込むのがいいと思います。

例えば、ホームディレクトリーなどそのユーザーの名前がついたディレクトリーからそのユーザーのファイルを探してくるならこういう方法もあるかと。
locate $USER | xargs stat -f "%Su %SN" | egrep "^$USER" | awk '{print $2}'

fork+execのオーバヘッドを考えると、パイプでつないでプログラムを書くよりもPerlなどで全部書いたほうが多分速いんですけどね。

この手のシステムスクリプトを高速化する場合の基本方針は次の4つだと思います。
a. 早めに枝刈りをする。参照するデータを絞り込む。 (加工する必要があるデータに絞り込んでから加工)
b. なるべく一箇所にまとまったデータを使う (新鮮な情報が必要でないなら、findよりはlocate)
c. システムコールを呼ぶ回数を減らす (シェルクリプトではなく、Perlスクリプト)
d. キャッシュを有効活用する


このスクリプトの実際の運用を知れば、find /home -user hogeだけを見せられるよりもまだ改善の余地はありそうです。
1. /home全体にuserのデータが存在し得るのか?特定のところにあるという事はないのか?
あるいは、/home/userにないuserのデータを探したいなら、/home/userを除いて探せないか? (方針a)
2. 毎日実行するほど頻繁にuserのデータは書き換わるのか?
例えば、持ち主の変更を考慮しないで良いなら、ファイル名と持ち主の情報が入ったBerkeley DBを作り、そこにデータをキャッシュできないか? (方針d)
3. このスクリプトでは一人のユーザーの情報しか探さないのか?
もし、findを複数のユーザーに対して行うなら、初回でDBを作り、あとはそのDBを参照するだけにできないか? (方針b、d)
4. find ...は単体で呼び出すのか、スクリプトから呼び出すのか
スクリプトから呼び出すなら、そのスクリプトをPerlなどで書きなおして外部のコマンドを呼ぶ回数をを減らせないか。(かつてはpythonやrubyなどよりもperlが高速でしたが、今は違うかもしれません) (方針c)


というわけで、findが呼ばれる背景がわかると枝刈りももっと効率的に出来るように思います。あとは上記方針を参考に書き換えてみてください。

投稿日時 - 2012-07-06 08:25:11

補足

#1さんのおっしゃるようにコマンド一発の方法は無いのですね。find /home/hoge ではだめで、
ちょっと質問が間違っていまして正確には

/home/aaa
/home/bbb
/home/ccc
/home/ .....

とたくさんユーザーとファイルがある中で、userがroot になっているファイルを毎日検索したいです。

そういったファイルはランダムな場所にランダムに発生しますので
以下をcron で単純に実行して書き出していますが、

find /home -user root > hoge.txt

負荷的に厳しく代替手段に苦慮しています。

投稿日時 - 2012-07-06 10:26:00

ANo.1

ファイルの所有ユーザを調べるためには実際にそれぞれのファイルのinodeをアクセスする必要があるために、findより抜本的に速い方法というのは無いです。

find /home/hoge じゃ駄目なんですか?

投稿日時 - 2012-07-06 06:06:47

あなたにオススメの質問