0

I am trying to run a network server that is supposed to receive very short newline-terminated udp messages. The service plist looks like this

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>local.listener</string>
        <key>Program</key>
        <string>/bin/cat</string>
        <key>Sockets</key>
        <dict>
            <key>Listeners</key>
            <dict>
                 <key>SockType</key>
                 <string>dgram</string>
                 <key>SockNodeName</key>
                 <string>0.0.0.0</string>
                 <key>SockServiceName</key>
                 <integer>9999</integer>
            </dict>
        </dict>
        <key>inetdCompatibility</key>
        <dict>
            <key>Wait</key>
            <true/>
        </dict>
        <key>StandardOutPath</key>
        <string>/tmp/test.stdout</string>
</dict>

and it loads and does what it is supposed to do (write message strings to /tmp/test.stdout). However, I fail at replacing /bin/cat with a shell script that reads the message into a variable and lets me do something with it. I thought that something like this should work:

#!/bin/sh
read MSG
echo $MSG

but this appears to block, and so does

#!/bin/sh
/bin/cat

while

#!/bin/sh
exec /bin/cat

still works. On the command line all three variants do about the same thing, e.g.,

$ echo 123 | ./mycat.sh
123

and nothing blocks. Any insight into these subtle differences would be appreciated.

1

You're almost there. Wrap your first script in a while loop and you are set:

#!/bin/sh

while true; do
    read MSG
    echo $MSG
done

This is necessary to keep the process alive. Without the loop the script exits after the first line of input.

The exec approach works because you replace the current shell with /bin/cat. It is the same as calling /bin/cat directly.

  • Unfortunately that does not work either. In any case, the script is supposed to be started on demand, handle the message, and exit. But unlike, /bin/cat (and the exec ...) version, it does not. Instead it hangs around and never writes output. It looks like read never returns, although the message is newline-terminated (and /bin/cat writes lines to the output file, which I think confirms that this is indeed the case.) – robmaz Oct 24 '17 at 16:27
  • I also would like to understand the difference between piping something into the scripts on the command line, where all read an input line and write it to an output line, and them being called by launchd, where two of them apparently don't, although I thought that was doing pretty much the same thing. – robmaz Oct 24 '17 at 16:32
  • I'm sorry. I don't know what makes the job hang on your system. Your plist and script work just fine for me on macOS 10.13. Your version gets started every time I send a string to port 9999, my version keeps running after the first connection. – guest Oct 25 '17 at 12:10

You must log in to answer this question.

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