Usando expressões regulares e final para executar um comando

1

Semelhante a esta questão , no Linux tcsh eu quero cauda um arquivo de log e quando eu corresponder a uma expressão regular eu quero executar um comando arbitrário. Como posso fazer isso?

    
por Ross Rogers 10.10.2009 / 00:52

4 respostas

2

Na observação do pôster, um comentário nessa pergunta leva a uma postagem SO em desabilitação do auto- buffering ao usar pipes . A solução foi usar unbuffer (de expect ), como em:

$ unbuffer tail -f foo | find-and-run "findwhat" "runwhat"

A resposta de wfaulk (mais a limpeza de ayrnieu) nos fornece o script find-and-run:

#!/usr/bin/perl
# run: find-and-run "regex-to-find" "commandtorun"
die "usage: $0 <regex> <exec-this> [exec-this-arg1 ...]\n"
   unless @ARGV >= 2;

my ($re, @run) = @ARGV; 

while (<>) {
        last if /$re/;
}
exec { $run[0] } @run;

Nota 1: no Debian lenny, você precisará instalar o pacote "expect-dev"; unbuffer é instalado como "expect_unbuffer".

Nota 2: isto é completamente não testado e completamente ligeiramente ingênuo. por segurança, não use isso. Se você usar isso, provavelmente desejará uma citação simples do seu regex para evitar a substituição / expansão do shell.

Nota 3: muito obrigado ao ayrnieu pela conclusão e limpeza de scripts.

    
por 10.10.2009 / 04:13
3

Isso parece adequado para um script perl curto:

#!/usr/bin/perl

while (<>) {
        last if /regex/;
}
system("ls");

Se você deseja fornecer um padrão e um comando com argumentos sinalizados, consulte a documentação em perldoc Getopt::Std .

    
por 10.10.2009 / 01:27
1

No meu caso (no RHEL, queria que tail -n 0 -f file | grep -m 1 pattern terminasse imediatamente quando o padrão ocorre no arquivo crescente), o uso simples do utilitário unbuffer do pacote Esperar não resolveu o problema por algum motivo.

Mas com base em uma postagem no blog ( link ) Descobri que redirecionar a entrada da cauda lançada em um subshell resolveu o problema:

grep -m 1 pattern <(tail -n 0 -f file)

Isso não foi tão simples, no entanto. Enquanto trabalhava em um shell interativo, o mesmo comando, quando executado remotamente usando o SSH, ainda congelava como de costume:

ssh login@hostname 'grep -m 1 pattern <(tail -n 0 -f file)'

Descobri que, neste caso, é necessário desativar a saída do tail usando o utilitário unbuffer em Expect:

ssh login@hostname 'grep -m 1 pattern <(unbuffer -p tail -n 0 -f file)'

Este não deve ser usado em um shell interativo - o unbuffer causará um ioctl(raw): I/O error !

Portanto, o conselho para você é que, se as soluções propostas não funcionarem, tente lançar tail -f em um subshell e, se quiser fazê-lo em um script ou em um shell não interativo, use unbuffer ou unbuffer -p pode ser necessário.

BTW, consulte este artigo para obter explicações detalhadas sobre o problema de buffer de saída: link

    
por 25.02.2010 / 14:26
0

Uma abordagem diferente é usar um programa como a amostra . O Swatch é construído para fazer exatamente o que você está falando, além de uma dúzia de outras coisas.

    
por 25.02.2010 / 16:34