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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.