1

After failing to produce a robust messaging system using named pipes I'm trying to use netcat. My receiving side will be a small script that listens to a port using netcat, spawns a new listener and execute a script based on the received message:

# jh_listen.sh
message=$(netcat -l 5555)
nohup jh_listen.sh >/dev/null 2>&1 &
cmd=${message%% *}
parms=${message#* }
nohup ${cmd} ${parms} >/dev/null 2>&1 &

On the sending side it will be nothing more complex than

echo "<command> <parms>" | netcat host 5555

My problem is that there will be a short gap between the listener closing the connection and a new listener starting. The echo thru netcat ends immediately having done nothing if a listening process does not receive the message, so I have the potential to lose messages. Is it possible to have netcat block when sending data until something receives it? I've tried -q and -w but neither do what I want. Message rate will be high and from multiple hosts so chance for loss if high if the message sender can't block until its message is consumed.

Additional info

To work around the sender not blocking I've tried to implement a robust sender for the above listener using

msgno=1

while [[ true ]]; do
    rc=-1
    retrycount=0

    while [[ ${rc} -ne 0 ]]; do
        echo "<command> <parms> ${msgno} ${retrycount}" | netcat host 5555"
        rc=$?
        echo "<command> <parms> ${msgno} ${retrycount}" >> local.log
        ((retrycount++))
    done
    ((msgno++))
done

Although I can't find a list of netcat exit codes it appears that it should only exit with 0 if the connection can be made. What I'm seeing in the local.log on the writer end is what I would expect; msgno increasing after each send, and retrycount increasing occasionally if it can't send. On the receiving end I occasionally get empty messages and/or gaps in the msgno sequence. I'm at a loss to explain either other than netcat sometimes seems to lose stdin, and sometimes exits with 0 even if it hasn't sent a message. Most of the time it seems to work fine but that's not good enough; I need to guarantee the messages get thru.

Kara
  • 6,115
  • 16
  • 50
  • 57
Jim Hudd
  • 47
  • 10

1 Answers1

1

Not directly an answer to your question, but you if you can use socat instead of netcat, you could do something like this:

jh_listen.sh:

#/bin/bash
socat TCP4-LISTEN:5555,fork EXEC:./jh_exec.sh

jh_exec.sh:

#/bin/bash
cmd=$(cat -)
exec ${cmd}

On the sending side you would do something like this:

echo "touch foo" | socat - TCP4:hostname:5555

With the above setup jh_listen.sh will continuously listen on port 5555 and for each connection made, it will fork a child process jh_exec.sh to handle it. This is basically a forking socket server setup.

  • socat isn't present on any of the Linux distributions I'm using and I really want something that is widely supported. Does the command you specify here continuously listen at the socket? If it's just a one-shot and I would need to spawn a new listener then I'm in the same boat as with netcat. – Jim Hudd Feb 02 '15 at 08:53
  • 1
    @JimHudd This may answer your comment [here](http://stackoverflow.com/questions/9596594/why-is-fork-needed-by-socat-when-connecting-to-a-web-server?answertab=votes). You should also check out _TCP-LISTEN_ in the socat man page. – Mikolaj Feb 02 '15 at 15:30
  • @JimHudd, `socat` is a lot more advanced and is just as widely supported as `netcat`. Just saying – Super-intelligent Shade Feb 02 '15 at 15:33
  • I'm not against using socat but since this is going to be used for a commercial application (if I ever get it working) I wanted to use something that was part of a base install of Linux. I've tried 5 different flavours of Linux and none of them included socat out of the box. If I needed to install something additional it invariably makes the security teams jumpy. If it's in the base install then I've got much more chance of being able to use it. However, I will give socat a go and hopefully it will solve the dropped and blank message problems and give me something I could try to work with. – Jim Hudd Feb 03 '15 at 07:24
  • Having tried socat as you've suggested it works perfectly, so thank you very much for your help. I set it up on three machines (1 reading/writing and 2 others writing) and saturated the listener with messages and not a single message was blank or dropped. I suspect netcat might have worked as well if I have a version that supported command execution. socat also seems to consistently exit with 1 if it cannot send a message, so I can use that to detect that the listener is down. Thanks again, Jim. – Jim Hudd Feb 03 '15 at 11:00