1

I've got this command which displays packets received and sent on port 1700.

tcpdump -AUq port 1700

In the packet there is the string rxpk, but most of the packets don't have it. When the output contains this string I want some script (which flashes a led) to run.

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

But it appears that it only matches the first time an rxpk is found, subsequent occurences wont trigger the { ... }-part

Anybody an idea why? Or even an other approach to run a script when rxpk is received?

2
  • Does blink_led do something every time it reads a line of input, or does it do something once regardless of input? Sep 22, 2016 at 21:58
  • The blink_led has to be called everytime the string rxpk is printed by tcpdump.
    – stUrb
    Sep 23, 2016 at 8:26

1 Answer 1

1

The reason that the LED blinks only once is that when you print to a pipe, the pipe remains open, so there is only one invocation of blink_led. If blink_led was to read its stdin for instructions then this wouldn't be a problem. If it fails to read stdin and exits, then awk will exit too.

The conventional way around this is to close() the pipe so the next invocation starts a fresh one:

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

system() is fine too, as suggested by @heemayl (and probably better if blink_led has no interest in reading stdin at all).

You'll notice I'm using -l instead of -U, -l flushes stdout to avoid pauses if the output you want is waiting in a stdio buffer (-U enables whole packet flushing when you use -w to write to a file).

3
  • Thanks! Is it also possible to match multiple packets and give the match to the script as an argument? eg /(rxpk|txpk|stat)/ don't know if the regexp is that versatile?
    – stUrb
    Sep 23, 2016 at 11:11
  • You can use an ERE of /(rxpk|txpk|stat)/ as the awk pattern, but it won't tell you what it matched, you'll need to call match($0,/(rxpk|txpk|stat)/); print substr($0,RSTART,RLENGTH) from the { } block ,or instead of /../ use match(..) (though both will only show the first match, in case that's important). Sep 23, 2016 at 14:37
  • There is also a command called ngrep (netgrep) which might be more suitable for the packet collection Sep 23, 2016 at 18:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .