3

I'm writing a simple web server using nc and bash. It looks like this:

#!/bin/bash rm -f /var/run/streamman/out mkfifo /var/run/streamman/out trap "rm -f /var/run/streamman/out" EXIT while true do cat /var/run/streamman/out | nc -l 8080 > >( # parse the netcat output, to build the answer redirected to the pipe "out". while read line do line=$(echo "$line" | tr -d '[\r\n]') if echo "$line" | grep -qE '^GET /\?action' # if line starts with "GET /" then action=$(echo "$line" | cut -d '=' -f2 | cut -d ' ' -f1 | cut -d '&' -f1) # extract the request query_str=$(echo "$line" | cut -d '&' -f 2-) args=$(query_string_to_args $query_str) fn_exists $action && eval ${action} ${args} || echo "No route for $action" elif [ "x$line" = x ] # empty line / end of request then header=$(cat /var/www/header.html) footer=$(cat /var/www/footer.html) echo "$header somecontent $footer" > /var/run/streamman/out fi done ) done 

There are some extra functions in there but I left them out for brevity.

I start it as a daemon using the following init script:

#!/bin/bash user=streamman name=streamman-httpd prog=/usr/sbin/streamman-httpd case $1 in start) start-stop-daemon --start --user $user --chuid $user --background --umask 0000 --exec $prog > /var/log/streamman/streamman.log 2>&1 ;; stop) /sbin/start-stop-daemon --stop --user "$user" --name "$name" --retry=TERM/5/KILL/1 ;; restart) ;; *) ;; esac 

Here is the output of ps afx after starting the service:

3023 ? S 0:00 /bin/bash /usr/sbin/streamman-httpd 3065 ? S 0:00 \_ nc -l 8080 3066 ? S 0:00 \_ /bin/bash /usr/sbin/streamman-httpd 

As you can see, a child process has started up for some reason. I think it's to do with the way I use nc and the named pipe.

Now when I try to stop the service I get this:

Program streamman-httpd, 1 process(es), refused to die. 

And the output of ps afx:

3065 ? S 0:00 nc -l 8080 3066 ? Z 0:00 \_ [streamman-httpd] <defunct> 

For some reason the child process won't die.

I've tried using pid files, but I can't get my server script to output the child's pid to a file.

How can I make it kill both processes?

2
  • have you looked into kill options? Such as kill -9? Commented Aug 18, 2014 at 6:42
  • In my experience, shell scripts don't deal well with direct kills because shells don't automatically kill their child processes. If you want robust cleanups with shell scripts, you need to run them in separate process groups and you need to aim the kill at the whole group, not just the topmost process. I'm using a C program that ensures the script runs in a separate proces group and that all signals aimed at the topmost process are forwarded to the whole child group (I don't know how to handle signal forwarding corner cases in shell). Commented Jul 17, 2017 at 22:45

1 Answer 1

1

I think the primary cause is "exec" call in your "start" section. Could you add to trap "rm -f /var/run/streamman/out" EXIT string something like:

; ps ax | kill `awk '$5 ~ /nc -l 8080/ {print $1}` 

I understand this is a dirty workaround...

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.