Como garantir que um processo tenha iniciado a leitura de um arquivo antes de continuar?

1

Estou tentando escrever um comando para testar se os dados estão gravados em um arquivo. Minha primeira abordagem foi:

  1. Comece a ler em segundo plano.
  2. Escreva alguns dados para o arquivo.
  3. Espere o leitor encontrar um resultado.
  4. Repita indefinidamente para ver se há algum problema de tempo.

Em forma de script:

while true
do
    grep -q foo <(tail -n0 -f /var/log/syslog) &
    logger foo && logger line && wait
done

(o comando logger line evita last message repeated N times linhas no arquivo)

Essa versão normalmente faz um loop uma ou duas vezes antes de ficar presa no comando wait , então parece que tail não teve tempo para começar a ler antes de logger foo ter escrito no arquivo.

Qual é a melhor maneira de garantir que tail está lendo antes de continuar ? Essas soluções alternativas não são ideais:

  • Pause antes de logger (não funciona no caso de sistemas de arquivos lentos)

        sleep 1 && logger foo && logger line && wait
    
  • Inicie um segundo leitor e presuma que o primeiro começou a ler no momento em que o segundo foi exibido. Isso circulou alguns milhares de vezes antes de ficar preso:

        grep -q foo <(tail -n0 -f /var/log/syslog) &
        grep -q bar <(tail -n0 -f /var/log/syslog) &
        while kill -0 $!
        do
            logger bar
            logger line
        done
        logger foo && logger line && wait
    
por l0b0 17.01.2013 / 13:45

1 resposta

1

Aqui está uma maneira, reutilizando o leitor depois de estabelecer que realmente está lendo:

while true
do
    exec 3<> myfifo
    tail -n0 -f /var/log/syslog >&3 &
    tailproc=$!
    while ! grep -q start <&3
    do
        logger start
        logger line
    done
    grep -q end <&3 &
    logger end
    logger line
    wait $!
    exec 3<&-
    exec 3>&-
    kill $tailproc
done

Desde o escritor é bloqueado enquanto ninguém está lendo (entre o primeiro e o segundo grep ) ele não deveria ser possível para o segundo grep perder a próxima linha.

Isso está funcionando há algumas dezenas de milhares de iterações (com base nos IDs do processo na saída) sem ficar preso.

    
por 17.01.2013 / 14:21