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.
Best Answer
You're almost there. Wrap your first script in a
while
loop and you are set: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.