7

I'm working on a system whose primary startup system is runit.

Unfortunately, runit requires that whatever application it is running be running in the foreground like so:

#!/bin/bash

exec sshd -D

Seeing as nginx doesn't offer a way to run it in the foreground, how can I have runit still manage nginx and be able to stop, start, and restart it using runit's sv commands?

Naftuli Kay
  • 39,676

2 Answers2

9

You can use option daemon off:

exec /usr/sbin/nginx -c /etc/nginx/nginx.conf  -g "daemon off;"

From nginx wiki:

You can use daemon off safely in production mode with runit / daemontools however you can't do a graceful upgrade. master_process off should never be used in production.

When you use runit to control nginx, it becomes the parent process of the nginx master process. But if you try to do an online upgrade, the nginx master process will fork and execute the new binary.

A new master process is created, but because old master process still exists (because it's controlled by runit), the parent of the new master process will be the init process, because runit can not control new master master process as it didn't start it.

Naftuli Kay
  • 39,676
cuonglm
  • 153,898
0

Don’t turn off the master process for anything used in the real world, it doesn’t do zero-downtime upgrades and it’s unsupported.

Do it the/a right way using page sentinel monitoring of port 80, etc. to not contain some magic content, otherwise nginx can’t do zero-downtime upgrades and you’ll look like a rank amateur.

# . . .
set -e
## config - start - should move to another file
CONF='/etc/nginx/nginx.conf'
# TODO: grab below by parsing CONF
PROTO=http
IP=0.0.0.0
PORT=80
## config - end - should move to another file
case "$(uname | tr '[A-Z]' '[a-z]')" in
darwin|freebsd|netbsd|openbsd) NC_ARGS="-n -w 5 -z '${IP}' '${PORT}'" ;;
linux) NC_ARGS="-n -w 5 --send-only '${IP}' '${PORT}'" ;;
*) echo "unsupported os $(uname)" >&2; exit 1 ;;
esac
/usr/bin/nginx -t -c "${CONF}"
/usr/bin/nginx -c "${CONF}"
sleep 5
while /usr/bin/nc $NC_ARGS </dev/null >/dev/null 2>&1; do
  set -e # loop runs in a subshell
  /usr/bin/curl -m5 -fsS -A 'runit script/0.0.0' \
    "${PROTO}"://"${IP}":"${PORT}" | \
    /usr/bin/grep -q 'This comment is required'
  sleep 2
done
dhchdhd
  • 348