Questão Em relação ao comando Unix Move


Eu preciso escrever um script Unix Shell Script tran.sh que move os arquivos de entrada csv da pasta / exp / files para o diretório / exp / ready.

Os arquivos de entrada csv são gravados em /exp/files pasta por um servidor FTP cujo comportamento não posso mudar trivialmente. Dentro tran.sh Eu preciso garantir antes de fazer um movimento do arquivo de entrada CSV do diretório / exp / files e nenhum outro processo está gravando no arquivo.

Como eu posso fazer isso.


4


origem


BTW - sabendo que é um servidor FTP (em oposição a um processo arbitrário) realmente altera o conjunto de respostas apropriadas; Eu certamente tive motivos para atualizar o meu. Por favor, forneça mais informações na sua próxima pergunta.


Respostas:


Não há uma maneira portátil de fazer isso. Podes tentar fuser, lsof, inotify, FAMe outros embora.


3



boa resposta, corta direto ao ponto. Eu acho que você poderia adicionar glib e gamin também - Matt Joiner


Tente usar fuser [FILE]. Ele retornará diferente de zero se o arquivo não estiver em uso.

Veja alguns exemplos de código que aguardarão um arquivo pronto para ser movido:

#!/bin/sh

FROMDIR='/exp/files'
DESTDIR='/exp/ready'

function move_file_if_ready () {
    if [ -f "$1" ]; then
        while fuser "$1" 2>/dev/null 1>&2 ; do
            sleep 1
        done

        mv "$1" "$DESTDIR"
    fi
}

for "$fn" in "$FROMDIR"/*.csv; do
    move_file_if_ready "$fn"
done

3



Nada mal, mas ainda tem uma condição de corrida. - dmckee
Muito obrigado. Três processos de aplicativos remotos estão enviando o arquivo de entrada para este diretório. Então eu serei capaz de saber com este comando do fusor se eles estão gravando no arquivo.
@dmckee - É verdade sobre a condição de corrida, mas eu assumi que o processo de gravação apenas mantém o identificador de arquivo aberto por tempo suficiente para escrever nele, depois o fecha, nunca mais para abri-lo novamente. - amphetamachine
Muito obrigado. Estou planejando para verificar se a última linha dentro do arquivo csv é recebida e validar o arquivo


você pode usar o lsof

r=$(lsof /exp/files )
if [ ! -z "$r" ] ;then
  mv /exp/files/*csv /exp/ready
fi

3



Muito obrigado. Três processos de aplicativos remotos estão enviando o arquivo de entrada para este diretório. Então eu serei capaz de saber com este comando lsof se eles estão escrevendo no arquivo.
Mas, com três processos (assumindo-se independentes) gravados nos arquivos do diretório, eles não serão movidos a menos que os três tenham terminado. É mais modular usar o fusor e testar em uma base por arquivo. - amphetamachine
Muito obrigado. Estou planejando para verificar se a última linha dentro do arquivo csv é recebida e validar o arquivo.


A maneira certa de fazer isso é fazer com que o processo de gravação dos arquivos seja renomeado ou movido de sua própria vontade quando feito com a gravação. Qualquer outra coisa é propensa a condições de corrida e / ou problemas de permissão.

Alguns exemplos específicos de casos de problemas:

  • Se o processo que move os arquivos for executado como um usuário diferente de lsof / fuser / etc, as informações não são garantidas como completas
  • Se o processo que faz a gravação for um shell script, ele pode gerar um subprocesso que abre o arquivo, permite que ele seja fechado, crie outro subprocesso, etc. Neste cenário, lsof, fuser e ferramentas semelhantes podem legitimamente mostrar o arquivo como não sendo acessado mesmo que mais subprocessos sejam iniciados para escrever posteriormente.

Outras condições de corrida mais sutis também podem existir - e independentemente disso, lsof, fuser e tal não são ferramentas POSIX e não estão disponíveis em todos os lugares.

Exija, como uma questão do protocolo, que os processos que os gravam os movam para o local final ao completarem-se; é a única abordagem segura e portátil.

EDIT: foi esclarecido que os arquivos estão sendo escritos não por um processo arbitrário (que pode fechar e reabri-los), mas por um servidor FTP. Nesse caso, incron pode ser usado para executar um script arbitrário sempre que um arquivo for fechado nesse diretório.


2



Muito obrigado pela informação O problema é que três processos de aplicativos remotos estão enviando o arquivo para este diretório. Então eu não deveria mover o arquivo quando eles estão escrevendo neste diretório / exp / files
@arav - você pode contornar isso (o que significa dizer, Eu contornar isso) com um servidor sftp personalizado. (O meu é escrito em Python usando a biblioteca Paramiko; também há um ftpdlib para escrever servidores FTP padrão no Python, embora muitos motivos para evitar o FTP sejam muitos).
@arav - ... Dito isso, parece-me que outra solução livre de condições de corrida que funcionaria para você seria usar inotifywatch ou incron para executar um script de sua escolha sempre que uma atualização for concluída.


Eu não acho que você pode fazer isso sem modificar processos que criam esses arquivos. Sempre que temos uma tarefa como essa em nossos sistemas, garantimos que o processo que cria o arquivo torne-o executável no final. Assim, o processo que move ou processa de alguma outra maneira esses arquivos podem verificar o bit executável para garantir que o processo de origem tenha terminado de trabalhar com um arquivo.


0



O Problema é que três processos de aplicativos remotos estão enviando o arquivo para este diretório. Então eu posso verificar os três processos de aplicativos remotos estão concluídos.