Фильтрация вывода tcpdump и запуск скрипта при обнаружении строки в реальном времени

Фильтрация вывода tcpdump и запуск скрипта при обнаружении строки в реальном времени

У меня есть команда, которая отображает пакеты, полученные и отправленные через порт 1700.

tcpdump -AUq порт 1700

В пакете есть строка rxpk, но в большинстве пакетов ее нет. Когда вывод содержит эту строку, я хочу запустить какой-то скрипт (который мигает светодиодом).

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

Но, похоже, это соответствует только первому случаю, когда rxpkвстречается an, последующие случаи не будут вызывать { ... }-часть

Есть ли у кого-нибудь идея, почему? Или даже другой подход к запуску скрипта при rxpkполучении?

решение1

Причина, по которой светодиод мигает только один раз, заключается в том, что при печати в канал канал остается открытым, поэтому происходит только один вызов blink_led. Если blink_ledбы он считывал его stdin для получения инструкций, то это не было бы проблемой. Если он не может прочитать stdin и завершается, то он awkтакже завершается.

Обычный способ обойти это — использовать close()канал, чтобы следующий вызов начинался заново:

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

system()тоже неплохо, как предложил @heemayl (и, вероятно, лучше, если blink_ledвообще не заинтересован в чтении stdin).

Вы заметите, что я использую -lвместо -U, -lочищает stdout, чтобы избежать пауз, если нужный вам вывод ожидает в буфере stdio ( -Uвключает очистку всего пакета при -wзаписи в файл).

Связанный контент