Preciso implantar um processo automatizado (via script cron de 1 min) que procure por arquivos tar em um diretório específico. Se um arquivo tar for encontrado, ele não será desviado para o local apropriado e o arquivo tar será excluído.
Os arquivos tar são copiados automaticamente para este servidor pelo SSH de outro servidor. Em alguns casos, os arquivos tar são extremamente grandes, com muitos arquivos.
O problema que eu espero encontrar: Se demorar> 1 minuto para o arquivo tar ser copiado no servidor, e o script cron for executado uma vez a cada minuto, ele verá o arquivo .tar.gz e tentará descompacte-o, mesmo que o arquivo tar ainda esteja no processo de gravação.
Existe alguma maneira (via comandos bash) de testar se um arquivo está sendo gravado atualmente ou se é apenas um arquivo parcial, etc?
Uma alternativa em que eu pensava era fazer com que o arquivo fosse copiado como uma extensão de arquivo diferente (como .tar.gz.part
) e renomeado para .tar.gz
após a conclusão da transferência. Mas achei que tentaria descobrir se existe simplesmente uma maneira de determinar se o arquivo está inteiro na linha de comando primeiro ... Alguma pista?
rsync
usa um nome de arquivo temporário durante a transferência (por padrão) e somente após a transferência completa do arquivo, renomeia-o para o nome do arquivo real.Respostas:
Você está no caminho certo; renomear o arquivo é uma operação atômica; portanto, executar a renomeação após o upload é simples, elegante e não propenso a erros. Outra abordagem que posso pensar é usar
lsof | grep filename.tar.gz
para verificar se o arquivo está sendo acessado por outro processo.fonte
lsof filename.tar.gz
É mais eficiente e mais preciso do quelsof | grep filename.tar.gz
)Sua melhor aposta é usar
lsof
para determinar se um arquivo foi aberto por qualquer processo:Você não pode dizer com facilidade se está sendo gravado, mas se está sendo gravado, DEVE estar aberto.
Edit: vamos resolver o problema real aqui, em vez de tentar implementar a solução proposta!
Use rsync para transferir o arquivo:
Dessa forma, o arquivo não será copiado por cima do existente, mas copiado para um arquivo temporário (
.big.tar.gz.XXXXXX
) até a transferência ser concluída e, em seguida, movido para o local.fonte
Um pouco velho, mas a maioria das respostas esquece completamente o objetivo da pergunta:
Em geral, não há. Você simplesmente não tem informações suficientes para determinar isso.
Como determinar se o arquivo está fechado não é o mesmo que determinar se o arquivo está inteiro . Por exemplo, um arquivo será "fechado" se a conexão for perdida parcialmente durante a transferência.
Somente a resposta de @ Alex acertou. E até ele se apaixonou por usar
lsof
um pouco.Para determinar se o arquivo foi totalmente transferido com sucesso, são necessários mais dados. Tal como:
Essa é uma maneira perfeitamente correta de comunicar que o arquivo foi transferido total e com êxito. Você também pode mover arquivos de um diretório para outro, desde que permaneça no mesmo sistema de arquivos. Ou peça ao remetente que envie um
filename.done
arquivo vazio para sinalizar a conclusão.Mas todos os métodos precisam contar com o remetente de alguma forma sinalizando que a transferência foi concluída com êxito. Porque apenas o remetente tem essa informação.
Alguns formatos de arquivo (como PDFs) possuem dados que permitem determinar se o arquivo está completo. Mas você precisa abrir e ler praticamente todo o arquivo para descobrir.
lsof
apenas informará que o arquivo não está mais aberto - não informará por que não está mais aberto. Nem lhe dirá qual o tamanho do arquivo.fonte
A melhor maneira de fazer isso é usar o incron ("inotify cron system"). Ele permite que você defina uma inspeção inotify em um diretório que o notificará sobre as operações do arquivo. Nesse caso, você deve assistir o dir por um close_write. Isso permitirá que você execute seu comando assim que o arquivo for fechado após uma gravação.
fonte
Parece que o lsof pode detectar em que modo um arquivo está aberto em:
Veja onde diz 1w? Isso significa que o número do descritor de arquivo é 1 e o modo é w ou write.
fonte
FD
campo mostra3r
para mim quando o arquivo está aberto para leitura.O uso
inotifywait
pode alcançar o que você procura - ele tem a capacidade de aguardar até que a gravação de um arquivo seja concluída antes de executar um comando.A seguir, você assiste continuamente uma pasta a novos arquivos e executa o comando no loop ao concluir a gravação no arquivo.
Para mais opções de configuração, consulte https://linux.die.net/man/1/inotifywatch
fonte