I use netcat to run a tiny development webserver through the bash, which is able to handle one connection at once.
Netcat is started as follows (-k
to make it survive multiple connections):
nc -kl 3000
A bash script processes the browser's request which is received by netcat, and builds the response, which is sent back to the browser through the same netcat instance.
Everything works as expected, but sometimes, the browser does not get the file it requested. My suspicion: If a connection is closed before the response is sent completely, the response's remainder is sent as response to the following request (it, of course, not belongs to).
Proof
nc -kl 3000
nc localhost 3000
hello\n
in terminal 1.hello\n
.world\n
in terminal 1.nc localhost 3000
in terminal 2 again (new connection).world\n
even though world\n
was actually sent when no connection existed, meant as second response line in the first connection.Required behavior: Ignore all bytes that are passed to netcat if no connection exists.
Is it possible using netcat? (I prefer a tool like netcat as it comes pre-installed on all machines.)
well, as a workaround and if you can do that, instead of running ncat using the keep-open option, just respawn it between each connection in a while loop:
while true; do
#what you want to do with: ncat -l 3000
done
Then each time the process will respawn, it will discard all stdin, and then you start over with the next i/o for the following process.
Of course, if respawning your bash script isn't convenient, then it might mean you're not using the right tool for the job. (you might be able to workaround that playing with fifos or using temporary fds, but that'd be overengineering to avoid writing a script in a language that'd be a better fit for the job).
If you're not already doing it, did you try running your script from netcat and not the other way around?
ncat -kl 3000 -c ./script.sh
it will spawn the script for each connection, on which it will redirect stdin/stdout. Then when the client will disconnect, the script will get killed and should release your input fd.
Actually, if you're serving files as an http server, you might to look up:
ncat -lk 3000 --lua-exec httpd.lua
with the httpd.lua
offered with the ncat distribution
If you want a simple run anywhere script to do something on your system, you can write a small python script.
It is installed per default on ubuntu (and many other systems), and you have a minimalist web server implementation provided, for example to serve files you just do:
python -m SimpleHTTPServer <port>
http.server
in py3it is rather easy to customize, to fit your unique needs, and will offer you a full control over your sockets and file descriptors.
Sticking with the need for "run everywhere" script, you could try processing the input line by line and detecting if an ESTABLISHED connection exists with netstat:
while read line; do
netstat -an | grep 3000 | grep -q ESTABLISHED;
ret=$?;
if [ "$ret" == "0" ]; then
echo $line;
else
# this output is just for fun, and can be removed
echo "not sending $line" >&2;
fi;
done | nc -kl 3000
This will have the limitation of being line-based and may still send data to netcat wrongly if the connection is closed just after the netstat call. The two grep calls should make sure that you dont wrongly detect your own grep.
Ive tried looking for signals returned by netcat when the connection is closed but cant see any exposed to the shell.
The use of a fifo can be used to demonstrate that netcat keeps its stdin open, even when no connection exists:
mkfifo test
nc -kl < test
# then in a different shell
for a in {0..5}; do echo hi > test; done
The for
does not block, so netcat is actively reading the stdin but buffering it (and I cant see an option to turn off buffering). This means you cant really tell the difference between netcat with or without an active connection, except by looking at the network state. netstat is one of many ways of getting this state.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With