134

When I restart the nginx service on a command line on an Ubuntu server, the service crashes when a nginx configuration file has errors. On a multi-site server this puts down all the sites, even the ones without configuration errors.

To prevent this, I run the nginx configuration test first:

nginx -t

After the test ran successful, I could restart the service:

/etc/init.d/nginx restart

Or only reload the nignx site configs without a restart:

nginx -s reload

Is there a way to combine those two commands where the restart command is conditional to the configuration test's result?

I couldn't find this online and the official documentation on this is rather basic. I don't know my way around Linux that well, so I don't know if what I'm looking for is right in front of me or not possible at all.

I'm using nginx v1.1.19.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jan
  • 2,879
  • 2
  • 19
  • 28
  • What about a small shell script that checks the return status of nginx -t (with $?) and then does the restart depending on the return state? – TeTeT Sep 03 '13 at 12:41

7 Answers7

104

As of nginx 1.8.0, the correct solution is

sudo nginx -t && sudo service nginx reload

Note that due to a bug, configtest always returns a zero exit code even if the config file has an error.

Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
51

Actually, as far as I know, nginx would show an empty message and it wouldn't actually restart if the configuration is bad.

The only way to screw it up is by doing an nginx stop and then start again. It would succeed to stop, but fail to start.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mohammad AbuShady
  • 40,884
  • 11
  • 78
  • 89
  • 1
    What version of nginx are you talking about? I'm working with v 1.1.19 and it will try to restart regardless of any errors in the config files. It will notify me that there is a problem, but by then it's already too late – jan Sep 03 '13 at 10:05
  • 5
    Ok I just tested it, my laptop has nginx 1.2 and it worked as i described, my VPS has 1.1.19 like yours, and It did the same as you described in your question. So i guess this was handled in 1.2 – Mohammad AbuShady Sep 03 '13 at 10:23
  • Great! Thanks for figuring that out for me. I'll keep the question open a little longer to see if noone has an answer for nginx < v1.2 – jan Sep 03 '13 at 10:29
  • 1
    I guess i'll have to upgrade then :-) Needed an excuse anyway – jan Sep 05 '13 at 07:15
  • 2
    `service nginx reload` shows nothing whether the config was loaded correctly or not, so it's useless if you suspect the config might be incorrect. `service nginx restart` will stop the server if the config has an error! – Dan Dascalescu May 19 '15 at 01:52
  • the new versions show error messages, were talking about an old 1.19 the current version is 1.9 – Mohammad AbuShady May 19 '15 at 05:44
41

I use the following command to reload Nginx (version 1.5.9) only if a configuration test was successful:

/etc/init.d/nginx configtest && sudo /etc/init.d/nginx reload

If you need to do this often, you may want to use an alias. I use the following:

alias n='/etc/init.d/nginx configtest && sudo /etc/init.d/nginx reload'

The trick here is done by the "&&" which only executes the second command if the first was successful. You can see here a more detailed explanation of the use of the "&&" operator.

You can use "restart" instead of "reload" if you really want to restart the server.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mauricio Sánchez
  • 4,602
  • 1
  • 23
  • 15
  • Beware for nginx 1.4.2 I found `pkill -1 nginx` (effectively what my init.d/nginx reload does) does NOT reload if the config fails and misleadingly returns successful. Check your own versions. – KCD Feb 13 '14 at 02:48
  • 2
    This doesn't work for me. Both commands get executed even if the test fails. – Mario Campa Jun 13 '14 at 17:06
  • 2
    [configtest always returns a zero exit code](http://trac.nginx.org/nginx/ticket/763), at least in nginx 1.8.0. Use `nginx -t` instead. – Dan Dascalescu May 19 '15 at 01:52
9
alias nginx.start='sudo nginx -c /etc/nginx/nginx.conf'
alias nginx.stop='sudo nginx -s stop'
alias nginx.reload='sudo nginx -s reload'
alias nginx.config='sudo nginx -t'
alias nginx.restart='nginx.config && nginx.stop && nginx.start'
alias nginx.errors='tail -250f /var/logs/nginx.error.log'
alias nginx.access='tail -250f /var/logs/nginx.access.log'
alias nginx.logs.default.access='tail -250f /var/logs/nginx.default.access.log'
alias nginx.logs.default-ssl.access='tail -250f /var/logs/nginx.default.ssl.log'

and then use commands "nginx.reload" etc..

MechanisM
  • 906
  • 8
  • 14
9

You can reload using /etc/init.d/nginx reload and sudo service nginx reload

If nginx -t throws some error then it won't reload

so use && to run both at a same time

like

nginx -t && /etc/init.d/nginx reload

gokul kandasamy
  • 193
  • 1
  • 2
  • 14
  • 1
    Let me teach you something about bash. && does not `run both at a same time` It runs the command on the right IF the command on the left returns an exit code of 0. If your `nginx -t` throws an error it's exit code wont be 0, so the second command will not run. Its `nginx -s reload` anyway – miknik Jul 07 '18 at 18:17
  • @miknik I think that's what he meant to say, it just didn't come out right. He says `If nginx -t throws some error then it won't reload`. The statement `run both at a same time` could also be interpreted as a single command, or one line. I don't interpret him necessarily saying in this case `in parallel`. – matt Jan 11 '19 at 21:07
3

You can use signals to control nginx.

According to documentation, you need to send HUP signal to nginx master process.

HUP - changing configuration, keeping up with a changed time zone (only for FreeBSD and Linux), starting new worker processes with a new configuration, graceful shutdown of old worker processes

Check the documentation here: http://nginx.org/en/docs/control.html

You can send the HUP signal to nginx master process PID like this:

kill -HUP $( cat /var/run/nginx.pid )

The command above reads the nginx PID from /var/run/nginx.pid. By default nginx pid is written to /usr/local/nginx/logs/nginx.pid but that can be overridden in config. Check your nginx.config to see where it saves the PID.

hcristea
  • 93
  • 8
1

At least on Debian the nginx startup script has a reload function which does:

reload)
  log_daemon_msg "Reloading $DESC configuration" "$NAME"
  test_nginx_config
  start-stop-daemon --stop --signal HUP --quiet --pidfile $PID \
   --oknodo --exec $DAEMON
  log_end_msg $?
  ;;

Seems like all you'd need to do is call service nginx reload instead of restart since it calls test_nginx_config.

Daenney
  • 11
  • 1
  • `service nginx reload` won't give any sort of indication as to whether the configuration tested OK or not, or whether it was reloaded or not. – Dan Dascalescu May 19 '15 at 01:36
  • What does `test_nginx_config` do then in that case? – Daenney Jul 02 '15 at 07:19
  • 1
    I think you both have a point. `service nginx reload` is sufficient on the command line, however sometimes you may want to capture stderr output and return that back to a script for troubleshooting. `nginx -t` would tell you which file had the invalid parameter and on which line. – anastymous Aug 13 '16 at 23:44