Observe periodicamente um pipe e extraia a nova saída que foi produzida desde a última vez que a examinei

0

Estou lendo uma saída continuamente crescente de um pipe (por exemplo, saída de inotifywait ).

Eu preciso examinar periodicamente a saída do pipe e extrair todas as novas saídas que foram produzidas desde a última vez que a analisei.

Como faço isso em um script de shell? Eu estou fora ideias de palavras-chave para usar para googling.

    
por Costin Gușă 06.03.2018 / 16:56

1 resposta

2

Os dados em um pipe só podem ser lidos uma vez; a parte "o que é novo" é fácil. Basta criar um pipe nomeado com mkfifo , redirecionar sua saída inotifywait para ele com > e ler o pipe periodicamente.

A parte mais complicada é a leitura de um pipe, que está aberto para gravação em algum lugar, sem bloqueio. dd pode fazer isso.

Aqui está a configuração que usei para criar e escrever continuamente em um pipe:

mkfifo foo
( while true ; do date; sleep 1 ; done ) > foo

E para ler todos os dados não lidos:

dd iflag=nonblock if=foo bs=1M count=1 of=buffer.txt

Você pode alterar of=... para um arquivo de saída de sua escolha.

Mais cedo ou mais tarde, você obterá uma linha parcial do canal, portanto, certifique-se de que seu script possa lidar com isso. Para o tipo de atividade que você descreve, uma boa abordagem é repetir o dd no modo append até que o buffer seja terminado por nova linha:

buf=buffer.txt
pipe=foo
> $buf # empty the buffer
until [[ $( tail -c1 $buf | od -a ) == *nl* ]] # nl means newline
do
  dd iflag=nonblock oflag=append conv=notrunc if=$pipe bs=1M count=1 of=$buf
  ls -l $buf # see how it grows
  sleep 1 # if the writer dies, this loop will be infinite and we don't want to kill the CPU
done
do_stuff.sh < $buf
# rm $buf

EDIT: parece que você quer dizer inotifywait quando você está no terminal e despejar tudo o que é novo. Isso é mais fácil. Faça um arquivo como whatsnew.sh:

#!/bin/bash
echo "waiting for first output ... "
while true
do
    n=0
    while read -t0.1 line
    do
        echo "[$line]"
        (( n++ ))
    done
    read -p "$n new lines.  Press any key to try again... " -n1 -s </dev/tty
    echo
done

Em seguida, inicie:

inotifywait | whatsnew.sh
    
por 11.03.2018 / 05:55