I am trying to implement a simple log server in Bash. It should take a file as a parameter and serve it on a port with netcat.
( tail -f $1 & ) | nc -l -
Another option: use a redirect to subshell. This changes the order in which background processes are started, so $! gives PID of the tail
process.
tail -f $1 > >(nc -l -p 9977) &
wait $!
Write tail's PID to file descriptor 3, and then capture it from there.
( tail -f $1 & echo $! >&3 ) 3>pid | nc -l -p 9977
kill $(<pid)
Have you tried:
nc -l -p 9977 -c "tail -f $1"
(untested)
Or -e
with a scriptfile if your nc
doesn't have -c
. You may have to have an nc
that was compiled with the GAPING_SECURITY_HOLE
option. Yes, you should infer appropriate caveats from that option name.
You could use the coproc
command twice.
The given example translates to:
coproc TAIL { tail -f $1; }; exec {TAIL[1]}<&-
coproc NC { nc -v -l -p 9977; } <&"${TAIL[0]}" >&1
wait $NC_PID; echo "nc exit code: $!"
kill $TAIL_PID; echo "done"
(I've thrown a -v
and a couple echo
in there for troubleshooting.)
Using coproc
feels a lot like using Popen() in various other scripting languages.
You may store the pid of the tail
command in a variable using Bash I/O redirections only (see How to get the PID of a process in a pipeline).
# terminal window 1
# using nc on Mac OS X (FreeBSD nc)
: > /tmp/foo
PID=$( { { tail -f /tmp/foo 0<&4 & echo $! >&3 ; } 4<&0 | { nc -l 9977 ;} & } 3>&1 | head -1 )
kill $PID
# terminal window 2
nc localhost 9977
# terminal window 3
echo line > /tmp/foo
ncat
automatically terminates tail -f
on exit (on Mac OS X 10.6.7)!
# simple log server in Bash using ncat
# cf. http://nmap.org/ncat/
touch file.log
ncat -l 9977 -c "tail -f file.log" </dev/null # terminal window 1
ncat localhost 9977 </dev/null # terminal window 2
echo hello > file.log # terminal window 3