I am using socat to intercept UDP messages and send them to a named pipe:

socat UDP-LISTEN:9999,fork PIPE:/tmp/mypipe,append

I am able to tail this pipe and see all the messages it receives.

I would like to pipe the output of tail -f /tmp/mypipe to sed to do some post-processing of the messages, but unfortunately some of them are not newline-terminated. This is a problem because it means multiple distinct UDP messages could be on the same line, and also because tail -f /tmp/mypipe | sed ... does not pass the last line if it is unterminated.

Ideally I would like to be able to add a custom message delimiter as they are sent to my pipe, so that I can easily find the message boundaries. If that's not possible then is there some way I can follow this file and pipe the final (potentially unterminated) line to another program for post-processing?

  • I was able to get closer to my goal, though it's not perfect. Neither UDP-LISTEN nor UDP-RECV seemed to work -- when I tried to execute a system command to echo a trailing newline it appears they would hang on cat;. Using UDP-RECVFROM like so seems to work: socat -u UDP-RECVFROM:9999,fork SYSTEM:"cat; echo \"\n\"" – abc Jul 27 '18 at 22:21
  • The solution in my comment above appears to suffer from a race condition -- since the receives are forked (as they have to be, else socat exits after the first UDP message) the SYSTEM commands are not executed atomically. I noticed the cat and echo getting interleaved when multiple messages came in at the same time. I serialized it by wrapping it in a lock like this: socat -u UDP-RECVFROM:9999,fork SYSTEM:"(flock -x 200; cat; echo \"\n\";) 200>./udplockfile" – abc Jul 27 '18 at 22:43

One possibility that does not involve forking is to use the socat verbose output rather than the data. My version of socat -v includes the length of the data in the verbose output, so you know where it ends. For example,

mkfifo mypipe
while sleep 3
do    printf "%sNONEWLINE" $RANDOM
done |
socat -u - UDP4:localhost:9999  &
socat -u -v UDP-RECV:9999 - >/dev/null 2>mypipe  &
cat -uv mypipe

will output before each data item (eg 9430NONEWLINE) a header starting > with the date and a length.

> 2018/07/28 10:29:33.965222  length=13 from=0 to=12
9430NONEWLINE> 2018/07/28 10:29:36.968335  length=14 from=13 to=26
26947NONEWLINE> 2018/07/28 10:29:39.971025  length=14 from=27 to=40

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.