Como saber se um arquivo foi escrito completamente?

1

Eu tenho o shell script que aguarda alguns arquivos chegarem da máquina remota, quando eles chegam, eles os colocam em um novo arquivo. Para isso estou usando um loop while, como segue:

while true
do

    if [ $(find ../Test_Data/local_enc* | wc -l) -eq 2 ]
    then
            break
    else
            sleep 0.001

    fi
done
cat ../Test_Data/local_enc* > ../Test_Data/All_Enc_Coords.txt

O problema é que o arquivo All_Enc_Coords é escrito às vezes e, às vezes, não escrito. Eu acho que isso é porque, encontrar função retorna algum valor, mesmo quando o arquivo não tem dados nele.

Como garantir que os arquivos foram gravados com sucesso? e como especificá-lo no loop while. Quer dizer, eu quero que todos os arquivos sejam escritos completamente e depois os cat? ... Eu usei o sleep 1 antes do cat e descobri que o arquivo está escrito completamente, mas existe alguma maneira de verificar isso ??

    
por MiNdFrEaK 29.09.2012 / 09:38

6 respostas

0

Você pode usar um caso de teste.

while [[ ! -e ../Test_Data/All_Enc_Coords.txt ]]; do
  if [ $(find ../Test_Data/local_enc* | wc -l) -eq 2 ]; then
    cat ../Test_Data/local_enc* > ../Test_Data/All_Enc_Coords.txt
  else
    sleep 0.001
  fi
done

De acordo com os comentários, se você estivesse verificando o arquivo contendo dados antes de escrever, você poderia usar:

while [[ ! -s ../Test_Data/All_Enc_Coords.txt ]]; do
  if [ $(find ../Test_Data/local_enc* | wc -l) -eq 2 ]; then
    cat ../Test_Data/local_enc* > ../Test_Data/All_Enc_Coords.txt
  else
    sleep 0.001
  fi
done
    
por 29.09.2012 / 09:44
4

Você consegue que o computador remoto crie um arquivo antes de iniciar o upload dos arquivos e depois os exclua depois?

por exemplo. usando ssh (semelhante pode ser feito com ftp ou HTTP PUT):

ssh yourhost touch ../Test_Data/upload-in-progress
scp local_enc* yourhost:../Test_Data/
ssh yourhost rm ../Test_Data/upload-in-progress

Depois, tudo o que o seu script precisa fazer é aguardar o desaparecimento do arquivo de upload em andamento. Isso pode ser feito com um loop de sono ou talvez usando inotifywait do pacote inotify-tools .

NOTA: Se o host remoto morrer ou seu script for eliminado antes de concluir o upload, ele deixará um arquivo obsoleto de upload em andamento. IMO este é um problema muito menor do que o risco de condições de corrida de tentar adivinhar quando o upload foi concluído (como todas as soluções em execução na máquina de destino por si só serão propensas)

Inicialmente, pensei em usar lsof | grep local_enc | wc -l , mas isso é tão propenso a raças quanto seu find .. | wc -l .

Como está usando inotify ou similar para ser notificado das mudanças no diretório Test_Data - você pode dizer quando os arquivos são criados / alterados naquele diretório, mas isso não indica quando uma sessão de upload foi concluída ... inotify em combinação com um arquivo de semáforo iria funcionar. inotify para aguardar o diretório Test_Data ser alterado e, em seguida, inotify to sleep até que o upload em andamento tenha sido excluído.

Além disso, se o script de upload no host remoto for executado a partir do cron, o arquivo de upload em andamento corrigirá a si mesmo na próxima execução. Como alternativa, seu script poderia ser escrito para assumir que qualquer arquivo de upload em andamento com mais de X minutos é antigo e deve ser excluído / ignorado ( inotifywait tem uma opção -t ou --timeout que seria útil aqui), mas atrasos na rede ou interrupções temporárias podem causar problemas aqui.

    
por 29.09.2012 / 11:07
1

Existem duas formas de o conseguir.

  1. Verifique se o arquivo não foi tocado por 2 ou 3 minutos após a gravação. Dessa forma, você pode dizer que o arquivo está totalmente escrito ou não. Para verificar se o arquivo foi escrito no mínimo 3 minutos antes:

    find /testfolder/filename.* -type f -mmin +3
    

    Você pode usar um loop for se tiver mais de um arquivo:

    for f in $(find /testfolder/filename.* -type f -mmin +3)
    do
      mv filename.* to destination
    cat ../Test_Data/local_enc* > ../Test_Data/All_Enc_Coords.txt
    done
    
  2. Se você tiver um trailer no arquivo, poderá ler o registro do trailer e decidir quando catalogar o arquivo.

por 04.04.2018 / 00:50
0

Se cat não imprimir erros, foi bem-sucedido. Se você não vir nenhum dado em All_Enc_Coords.txt, verifique se local_enc * também está vazio.

Você não precisa monitorar as gravações de arquivos, se o cat quits, a escrita estiver concluída; Se isso estiver sendo executado em outro script, use inotify para escutar o sinal WRITE_CLOSE.

    
por 29.09.2012 / 09:51
0

Estou usando o código abaixo para verificar se os dados ainda estão chegando ao arquivo. Se não, então está escrito completamente. Loop sai e o próximo processamento é iniciado.

for (( ; ; ))
do
    bfr=$(stat -c%s "$f")
    sleep 0.5
    aftr=$(stat -c%s "$f")
    if [ $bfr -eq $aftr ];
    then
        break;
    fi
done
    
por 18.07.2017 / 09:24
0
while true
do
    echo "Checking for file : $file_with_full_path"
    if [ -f "$file_with_full_path" ]; then
            echo "**File arrived**"
        for (( ; ; )); do
                echo "getting the file size"
            bfr=$(stat -c%s "$file_with_full_path")
                echo "File size at present: $bfr"
            sleep 30 # the sleep limit can be adjusted
            aftr=$(stat -c%s "$file_with_full_path")
            if [ $? -ne 0 ];then echo "File not present, looping again";break;fi #error handling, incase if file got removed or renamed after the transfer
                echo "File size at present: $aftr"
            if [ $bfr -eq $aftr ];then
                    echo "**File arrived and file size matched exiting the loop, before vs after size : $bfr vs $aftr**"
                break 
            fi
                echo "File arrived but file size doesn't match looping again: Before vs after : $bfr vs $aftr"
        done
        if [ -f "$file_with_full_path" ]; then  break; fi #double break to exit the loop
    else
            echo "File not available Sleeping and looping again"
        sleep 30 # wait limit can be adjusted
        continue
    fi
done
    
por 12.10.2018 / 17:27

Tags