Filtrando a saída do tcpdump e executando o script quando a string é encontrada em tempo real

Filtrando a saída do tcpdump e executando o script quando a string é encontrada em tempo real

Eu tenho este comando que exibe os pacotes recebidos e enviados na porta 1700.

tcpdump -AUq porta 1700

No pacote existe a string rxpk, mas a maioria dos pacotes não a possui. Quando a saída contém essa string, quero que algum script (que pisca um led) seja executado.

tcpdump -AUq port 1700 | awk '/rxpk/ { print | "/path/to/blink_led 18" }'

Mas parece que ele corresponde apenas à primeira vez que an rxpké encontrado, as ocorrências subsequentes não acionarão o { ... }-part

Alguém tem ideia do porquê? Ou mesmo uma outra abordagem para executar um script quando rxpkfor recebido?

Responder1

A razão pela qual o LED pisca apenas uma vez é que quando você imprime em um canal, o canal permanece aberto, portanto há apenas uma invocação de blink_led. Se blink_ledfosse ler seu stdin para obter instruções, isso não seria um problema. Se não conseguir ler stdin e sair, então awksairá também.

A maneira convencional de contornar isso é usar close()o pipe para que a próxima invocação inicie uma nova:

tcpdump -Alq port 1700 | awk '
  BEGIN { mypipe="/path/to/blink_led 18"; }
  /rxpk/ { print | mypipe; close(mypipe); }'

system()também está bom, como sugerido por @heemayl (e provavelmente melhor se blink_lednão tiver nenhum interesse em ler stdin).

Você notará que estou usando -lem vez de -U, -llibera stdout para evitar pausas se a saída desejada estiver aguardando em um buffer stdio ( -Upermite a liberação de todo o pacote quando você usa -wpara gravar em um arquivo).

informação relacionada