重複の可能性:
ディレクトリの内容が更新されたときにコマンドを実行する方法は?
私は1分ごとにディレクトリ内のファイルを見つける簡単なetlプロセスを書こうとしています。ファイルがある場合は(スクリプトを介して)リモートシステムにロードしてから削除します。
状況を複雑にすると、ロードに1分以上かかることがあります。この問題を解決するために、すべてのファイルを一時処理ディレクトリに移動し、そこで作業してからそこから削除できると思いました。また、コマンドラインスクリプトの作成をよりよく試みながら、よりエレガントなソリューションを試しています。まず、作業を実行するために、次の簡単なスクリプトを作成しました。
#!/bin/bash
for i in ${find /home/me/input_files/ -name "*.xml"}; do
FILE=$i;
done;
BASENAME=`basename $FILE`
mv $FILE /tmp/processing/$BASENAME
myscript.sh /tmp/processing/$BASENAME other_inputs
rm /tmp/processing/$BASENAME
スクリプトは、処理ディレクトリからほぼ直ちにファイルを削除し(重複処理の問題を回避)、最終的にそれ自体をクリーンアップしてそれらの間でファイルを処理できるようにします。
しかしこれは結局U/Linuxである。巨大なスクリプトを維持するのではなく、パイプを接続して移動して、これらすべての作業を1行で実行できる必要があると思います。
さらに、同時プロセスに並列性を使用することも利点となり得る。
付録:ある種のFIFOキューがこの質問に対する答えになる可能性があります。あるいは、cronの代わりに他の種類のディレクトリウォッチャーがあるかもしれません。私は私の小さな台本よりもエレガントな提案で開いています。唯一の問題は、「入力ディレクトリ」のファイルが実際に記録される前にタッチされることです。 -size -0 は実際のファイルを処理するためだけに必要です。
答え1
小さな処理スクリプトを作成し、並列処理にGNU Parallelを使用できるように聞こえます。
http://www.gnu.org/software/parallel/man.html#example__gnu_parallel_as_dir_processor
だからこんな感じ:
inotifywait -q -m -r -e CLOSE_WRITE --format %w%f my_dir |
parallel 'mv {} /tmp/processing/{/};myscript.sh /tmp/processing/{/} other_inputs; rm /tmp/processing/{/}'
詳しくは、紹介ビデオをご覧ください。http://pi.dk/1
編集する:
長さゼロのファイルを処理するには(つまり無視)、myscript.shが必要です。
これを回避できる場合は、touch
次のようにすることもできます。
inotifywait -q -m -r -e CLOSE_WRITE --format %w%f my_dir |
parallel myscript.sh {} other_inputs
GNU Parallelのインストールは非常に簡単です。
wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
答え2
まず、スクリプトは1つのファイル(リストの最後のファイル)で動作します。また、一行の表現が必ずしも適切でもエレガントではないと思います。 Cronは後ろから多くの作業を実行するため、失敗した作業を確認できるはずです。 cronを「頻繁に」実行することは問題になる可能性があります。これらの数十のプロセスが実行され、すべてキュー内のファイルを処理しようとするため、システムが遅くなる可能性があります。
これが私がすることです。
Dir="$HOME/input_files" # never hardcode when you have variables
for filename in "$Dir"/*.xml; do
# is the file non-empty AND is it still there, or may caught by another
# process
if [ -s "$filename" ]; then
# move files locally will be faster than crossing filesystems to /tmp
mkdir -p "$Dir/.processing"
# temp name should use pid, just in case another input with the same name comes in
tempname="$Dir/.processing/`basename $filename .xml`.$$"
mv "$filename" "$tempname"
# send stdout and stderr to a .output file
myscript.sh "$tempname" other_inputs > "$tempname.output" 2>&1
rc=$?
if [ $rc -eq 0 ]; then
rm "$tempname" "$tempname.output"
else
echo "Error processing $filename; rc=$rc" >&2
echo "File in $tempname" >&2
fi
done
これにより、処理後にファイルが削除されたり.processing
エラーが発生した場合に、コマンド出力を含むディレクトリにファイルが残ります。上記のコマンドは何も制限しませんが、複数のコマンドを互いに干渉せずに実行することができます。改善のためにかなり効率的な作業キューを作成する方法に関する他の質問があります。
答え3
使用イノティファイ(7)cron を介してポーリングするのではなく、着信ディレクトリを監視するインターフェイスです。 inotify-toolsは、システムコールインターフェイスのコードを記述したくない場合にディレクトリを監視するために使用できるinotifywaitプログラムを提供します。