2

I'm working on a set of scripts to monitor some external services that log to a TCP port.

function handleMessage {
  while read message
  do
    # Handle $message
  done
}
nc -d $ipadd $port | handleMessage

This code works fine when log messages are delimited by new lines like the following

Service started

ERROR: Something terrible happened

Service stopped

But one of the services delimits messages using LOGXXXX and allows new lines within messages so it's output looks more like this:

LOG0001 Service startedLOG0002 ERROR: Something terrible happened

NullPointerException at SomeMethod (File1.java)

SomeOtherMethod (File2.java)LOG0003 Service stopped

Using my code above handleMessage is called for each of the lines instead of for each set of LOGXXXX segments and if time passes with no messages containing newlines my script gets very far behind in handling messages.

Is there an option on nc or another program I can use to read from this TCP port and break on a custom delimiter, or some option to have a bash function handle each write to stdout instead of only being called for each line?

  • 3
    I think your best bet is to pipe nc's output to sed to do the line-splitting, and give the result of that mangling to your script. – vonbrand Feb 1 '13 at 19:48
  • You could try poking around with bash's variable IFS, i.e. set IFS=LOG in both the command line and the function. But I agree that sed might be worth to study. – user49738 Oct 23 '13 at 12:21
1

The problem here is in your while read message line. read by default terminates on a newline, but you can pass it another character with the -d option.

The question to ask is in your LOGXXXX lines, how does the script know when the entry is finished? If you can put a special character at the end then you can use read -d. Otherwise, you could replace the newlines with something else and then put them back after.

So in your example:

function handleMessage {
  while read message
  realmessage=`echo $message | tr '|' '\n'`
  do
    # Handle $realmessage
  done
}
nc -d $ipadd $port | tr '\n' '|' | handleMessage

So you're replacing all the newlines with a | so that it'll all get in the read call, and then you split it out after.

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.