запрос повторно выполняет циклические скрипты параллельно

запрос повторно выполняет циклические скрипты параллельно

У меня в скрипте оболочки есть следующее:

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 минут я запускаю второй экземпляр скрипта оболочки:

  • а) будет ли второй скрипт по-прежнему видеть файлы, которые не были обработаны?
  • б) вызовет ли это проблемы в первую очередь, если удалит файлы

или я смогу запускать их параллельно без проблем?

решение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 и выполнять его параллельно, позволяя одному скрипту выполнять работу двух или более.

решение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"

Конечно, это лишь краткий обзор того, что необходимо сделать.

Кстати, это также можно сделать в скрипте-оболочке, который ничего не делает, кроме как генерирует пакетный файл, а затем запускает основной скрипт.

Связанный контент