consulta está sendo executada para scripts de loop em paralelo

consulta está sendo executada para scripts de loop em paralelo

Eu tenho o seguinte em um script de shell:

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

Basicamente, ele obtém todos os arquivos em um diretório que corresponde aos critérios, extrai um nome de servidor do nome do arquivo, antes de passá-lo para um script MySQL para processamento.

O que estou pensando é se tenho 10 arquivos que levam 60 segundos cada para serem concluídos e, após 5 minutos, inicio uma segunda instância do script de shell:

  • a) o segundo script ainda verá os arquivos que não foram processados
  • b) causará problemas em primeira instância se excluir arquivos

ou poderei executá-los em paralelo sem problemas?

Responder1

Seria de supor que “60 segundos” (e até “5 minutos”) é apenas uma boa estimativa e que existe o risco de o primeiro lote ainda estar em andamento quando o segundo lote for iniciado. Se você quiser separar os lotes (e se não houver nenhum problema além dos arquivos de log em uma sobreposição ocasional), uma abordagem melhor seria criar um número de lote como parte da convenção de nomenclatura de arquivos em andamento.

Algo assim:

[[ -s ]] $local_dir/batch || echo 0 > $local_dir/batch
batch=$(echo $local_dir/batch)
expr $batch + 1 >$local_dir/batch

antes do loop for e, em seguida, no início do loop, verifique se o seu padrão corresponde a um arquivo real

[[ -f "$file" ]] || continue

e use o número do lote no nome do arquivo:

mv $file_location $local_dir/in_progress$batch.log

e para frente. Isso reduz o risco de colisão.

Responder2

Há uma resposta acima que fornece algumas boas soluções para o problema, mas pensei em fornecer uma pequena explicação sobre opor quede qual é o problema.

Na maioria das vezes: contanto que seus arquivos de log renomeados (os em andamento) não atendam aos critérios, você estaráprovavelmenteseguro para executar isso commínimorisco. Você ainda receberá alguns erros ...

Sua lista de arquivos é gerada na execução do script. Então o que acabaria acontecendo é que:

Script Aobtém uma lista de 10 files. Inicia o processamento, 5 filesem (5 restantes) script Bobtém uma lista de 5 remaining files, inicia o processamento. Script aem seguida, processa o próximo arquivo de sua lista (que é o mesmo que o arquivo script Bcomeçou a ser processado), ocorrerá um erro porque o arquivo foi renomeado. Portanto, com o tratamento de erros, ele poderia, teoricamente, passar para o próximo em sua lista e funcionar sem problemas. Mas, obviamente, SEMPRE existe a chance de as estrelas se alinharem, mas os scripts atingirem o mesmo arquivo ao mesmo tempo e algo inesperado acontecer. Pese esse risco como quiser.

Uma solução potencialmente mais elegante seria converter isso em um pythonscript e verificar parallel for loopsqual permitiria criar um único loop for e executá-lo em paralelo, permitindo que um script fizesse o trabalho de dois ou mais.

Responder3

Outra maneira de fazer isso é implementar uma fila em lote simples em seu script.

No início do script, você poderia fazer algo assim:

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"

É claro que isto é apenas um simples esboço do que precisa ser feito.

Aliás, isso também pode ser feito em um script wrapper que não faz nada além de gerar o arquivo em lote e, em seguida, executar o script principal.

informação relacionada