como emitir um sinal sonoro no evento tail -f

14

Quero que o meu PC faça um bipe no sistema em todos os eventos de cauda

Eu tenho o seguinte comando

tail -f development.log | grep "something rare"

existe uma maneira fácil como canalizá-lo para algo que emite um sinal sonoro? gostar

tail -f development.log | grep "something rare" | beep

se sim, a saída grep ainda será mostrada?

Jakob Cosoroaba
fonte
há um programa de beep com está no repo padrão para debian e variantes apenas apt-get install bipe, mas ele não funciona com a maneira tubulação isso
Jakob Cosoroaba

Respostas:

16

Basta definir da beepseguinte maneira:

beep() { read a || exit; printf "$a\007\n"; beep; }

Então, você pode usar seu comando:

tail -f development.log | grep "something rare" | beep
mouviciel
fonte
1
desculpe, mas isso não está funcionando, não emitir um sinal sonoro ou imprime nada
Jakob Cosoroaba
4
Embora a saída direta de tail -f seja imediata, ela é armazenada em buffer assim que passa por um cano. Você tem que esperar o suficiente "algo raro" antes de observar qualquer coisa.
Mouviciel 7/09/09
Você poderia passar a saída através sedou similar (entre tail e grep) para com um regexp, substituindo-o something raremuitas vezes. Quantas vezes isso precisa ser feito depende de quanto o tubo é armazenado no buffer.
David Spillett
6
@ David - Essa é uma abordagem de sucesso e falha. Se você quiser unbuffer os dados passados através de um tubo, utilize qualquer um dos métodos descritos nestas respostas: stackoverflow.com/questions/1000674/turn-off-buffering-in-pipe
2
Saindo da sugestão de @ nagul, aqui é a invocação que funcionou para mim:tail -f development.log | stdbuf -oL -eL grep "something rare" | beep
GuitarPicker
10

A tela GNU possui um recurso embutido para emitir um bipe quando uma janela é alterada: consulte a seção relevante da página de manual .

Resumo do título:

$ screen
$ tail -f yourfile.log    # inside the screen session
<C-a> M    # "Window 0 (bash) is now being monitored for all activity."

Como apontado nos comentários, este será emitido um bipe em cada nova entrada de log, não apenas nas que correspondem a "algo raro"; portanto, isso não faz exatamente o que o OP solicitou. Ainda é um truque útil para conhecer o IMHO.

Você pode obter o melhor dos dois mundos abrindo duas screenjanelas ( <C-a> cpara abrir uma janela, <C-a> <C-a>para alternar entre duas janelas):

  1. monitorado, com tail -f yourfile.log | grep 'something rare'
  2. não monitorado, com uma planície tail -f yourfile.log

Em seguida, você pode ficar assistindo o log rolar na janela 2 e será acionado da janela 1 quando "algo raro" ocorrer.

screen é incrivelmente versátil - eu recomendo a leitura.

Sam Stokes
fonte
1
Isso não soaria apenas "algo raro", seria?
1
Seria se tudo o que estava acontecendo nessa janela em particular é tail -f yourfile.log | grep something\ raremais do que apenas otail -f logfile
David Spillett
Opa, eu não percebi que ele só queria ouvir um sinal sonoro something rare. Editado para refletir isso. O grep funcionaria, mas ele não veria o resto do log, apenas as linhas raras - pelo que entendi, ele quer poder observar o log inteiro rolando, mas ser alertado sobre eventos específicos.
Sam Stokes
1

Você pode impedir que a saída seja armazenada em buffer no comando grep. Veja man grep para detalhes.

Você pode canalizar a saída grep em um bipe.

O exemplo a seguir é do man beep ...

   As part of a log-watching pipeline

          tail -f /var/log/xferlog | grep --line-buffered passwd | \
          beep -f 1000 -r 5 -s

Há muitas coisas boas nesses manuais. Se não tivéssemos que lê-los para encontrá-lo. ;-)

Um leitor
fonte
1

O comando watch possui uma opção --beep, e você também pode definir o intervalo de pesquisa, mas o padrão com 2 s deve estar ok

watch --beep 'tail development.log | grep "something rare"'
oanoss
fonte
1
Observe que watchfunciona executando seu parâmetro / comando em todas as seções (intervalos) e depois obtendo os resultados para a execução anterior. Assim, você vai querer usar a versão normal do comando tail, em vez de usartail -f
RyanWilcox
Isso não funcionou para mim (apesar de adicionar watch --beepe embrulhar minha cauda / grep, eu ainda não ouvi um sinal sonoro).
Machineghost #
1

Você pode usar sed para adicionar o controle-G da seguinte maneira:

tail -f myFile | sed "s/.*/&\x07/"

ou apenas em linhas raras, sem usar grep, da seguinte maneira:

tail -f myFile | sed -n "/something rare/s/.*/&\x07/p"

que diz: nas linhas onde algo raro ocorre, é tudo ubstitute para a mesma coisa com o controle-G pregado na extremidade, e impressão (mas não imprimir as linhas não correspondentes). Funciona bem!

Mi5ke
fonte
0

Hum, complicado. Talvez pudéssemos fazer algo assim?

for i in `find | grep 7171`; do beep; echo $i; done

Ou no seu caso

for i in `tail -f development.log | grep "something rare"`; do beep; echo $i; done

Parece estar fazendo algum buffer embora. Vou procurar se há uma maneira de desativar esse buffer pelo forloop.

Aparentemente, você deve poder ajustar o buffer do pipe usando, ulimit -pmas isso continua reclamando de argumento inválido para mim. Eu também encontrei um post que afirma que você precisa recompilar o kernel para alterar esse limite.

Ivan Vučica
fonte
0

Em um trabalho anterior, eu não conseguia encontrar um observador confiável apenas com command-fu, então eu tinha um script de wrapper como o abaixo, que inspecionava o arquivo a cada segundo de poll_duration e preenchia as novas linhas da frase interessada.

#!/bin/bash

file=$1
phrase=$2
poll_duration=$3

typeset -i checked_linecount
typeset -i new_linecount
typeset -i new_lines
let checked_linecount=new_linecount=new_lines=0
echo "Watching file $file for phrase \"$phrase\" every $poll_duration seconds"

while [ 1 ]
do
        let new_linecount=`wc -l $file| awk '{print $1}'`
        if [[ $new_linecount > $checked_linecount ]]; then
                let "new_lines = $new_linecount-$checked_linecount"
                head --lines=$new_linecount "$file" | tail --lines=$new_lines | grep "$phrase" && beep
                let checked_linecount=$new_linecount
        fi
        sleep $poll_duration
done

Isso foi em uma máquina Unix. No Linux, você pode melhorar ainda mais usando sua interface inotify filewatcher. Se este pacote ( inotify-tools no Ubuntu) estiver presente, substitua

sleep $poll_duration 

com

inotifywait -e modify "$file"  1>/dev/null 2>&1

Essa chamada é bloqueada até que o arquivo seja modificado. A versão de bloqueio é quase tão eficiente quanto a que você obteria com a tail -fversão se o pipe pudesse ser configurado para funcionar sem buffer.

Nota: O script primeiro faz um head --lines=$new_linecountpara garantir que as linhas adicionadas ao arquivo após a verificação não distorcem a parte do arquivo que é verificado nesse loop.


fonte