シェルスクリプトには次のものがあります。
for file in $local_dir/myfile.log.*;
do
file_name=$(basename $file);
server_name=$(echo $file_name | cut -f 3 -d '.');
file_location=$(echo $file);
mv $file_location $local_dir/in_progress1.log
mysql -hxxx -P3306 -uxxx -pxxx -e "set @server_name='${server_name}'; source ${sql_script};"
rm $local_dir/in_progress1.log
done
デフォルトでは、基準に一致するディレクトリ内のすべてのファイルを取得し、ファイル名からサーバー名を抽出し、処理のためにMySQLスクリプトに渡します。
10個のファイルがあるかどうかを知りたいです。各ファイルの完了には60秒かかり、5分後にシェルスクリプトの2番目のインスタンスを起動します。
- a) 2番目のスクリプトがまだ処理されていないファイルを表示できますか?
- b) ファイルを削除すると最初に問題が発生しますか?
それとも問題なく並列に実行できますか?
答え1
「60秒」(または「5分」)は単なる良い見積もりであると考えることができます。バッチを分離する場合(間欠的に重複するログファイルを除いて問題はありません)、バッチ番号を進行中のファイル命名規則の一部にすることをお勧めします。
このような:
[[ -s ]] $local_dir/batch || echo 0 > $local_dir/batch
batch=$(echo $local_dir/batch)
expr $batch + 1 >$local_dir/batch
for ループの前とループの先頭で、パターンが実際のファイルと一致することを確認します。
[[ -f "$file" ]] || continue
そして、ファイル名にバッチ番号を使用します。
mv $file_location $local_dir/in_progress$batch.log
前後。これは衝突の危険を減らします。
答え2
上記のこの問題に対する良い解決策を提供する答えがありますが、いくつかの説明を提供する必要があると思いました。なぜ問題は何ですか?
ほとんどの場合、名前を変更するログファイル(進行中のログファイル)が条件を満たしていない限り、次のことができます。おそらく実行しても安全です最小危険。しかし、それでもエラーが発生する可能性があります。
スクリプトが実行されると、ファイルのリストが生成されます。最終的に起こるものは次のとおりです。
Script A
リストを入手してください10 files
。処理を開始し5 files
(残り5つ)からscript B
リストを取得し、5 remaining files
処理を開始します。Script a
その後、リスト内の次のファイル(処理を開始したのと同じファイルscript B
)を処理すると、ファイル名が変更されたため、エラーが発生します。したがって、エラー処理を使用すると、理論的にはリストの次の項目に移動して問題なく動作することができます。しかし、スクリプトがソートされているが、同時に同じファイルに到達し、予期しないことが起こる可能性は明らかに常にあります。リスクを自由に評価してください。
python
おそらくよりエレガントな解決策は、これをスクリプトに変換し、単一のparallel for loops
forループを作成して並列に実行して、1つのスクリプトが複数のスクリプト操作を実行できるようにする方法を調べることです。
答え3
別のアプローチは、スクリプトに単純なバッチキューを実装することです。
スクリプトの先頭で次のことができます。
mkdir -p $localdir/batch
BATCHTMP=$(mktemp batch.XXXXXXXXXX)
MYBATCH="$localdir/batch/batch.$$"
# get list of current log files
find $local_dir/ -name 'myfile.log.*' > "$BATCHTMP"
# exclude any log files already in other batches
grep -vF -f <(sort -u $localdir/batch/batch.*) < "$BATCHTMP" > "$MYBATCH"
rm -f "$BATCHTMP"
# only process log files that are in my batch
for lf in $(cat "$MYBATCH") ; do
....
# somewhere in here, mv or rm the logfile being processed
# so it doesn't get processed again in a later batch run
done
rm -f "$MYBATCH"
もちろん、これは実行する必要がある作業の簡単な概要です。
ちなみに、これはバッチファイルを作成してから基本スクリプトを実行する以外に何もしないラッパースクリプトでも実行できます。