We help IT Professionals succeed at work.

How to auto reload nginx when there is a change in its config file?

Balbir Singh
Balbir Singh asked
on
I am constantly changing my nginx configuration. I am wondering if there is way to auto reload/restart nginx whenever there is change in its config file.
Comment
Watch Question

Dr. KlahnPrincipal Software Engineer

Commented:
Under linux, or under Windows?

Under linux:  Run a cron job once a minute, hash the config file (any hash will do), and see if the current hash matches the previous hash.  If not, shut nginx down and restart it.
nociSoftware Engineer
Distinguished Expert 2019

Commented:
The commands you are lookingfor are:
nginx -s reload   or nginx -s reopen

AFAICT they should work on all platforms (it searches the main process and sends it the right signal).
Also the signals stop & quit do exist.
David FavorFractional CTO
Distinguished Expert 2019

Commented:
Simple way is to camp on the file using inotifywait, then anytime inotifywait raises a CLOSE_WRITE event (new data in file), then run your reload.

I do this running a farm of in-house DNS servers.

1) Camp on all source zone files.

2) If one changes, recompile zone file source into zone file.

3) Push any changes to all DNS servers, across many machines.

4) Do a reload on all DNS servers, across many machines.

Same approach. Camp on a file or directory looking for CLOSE_WRITE, then take some action.
I usually compare the config files mtimes with /proc/nginxpid and reload when there is an output. A single find command can do thr comparison.
Balbir SinghSystem Administrator

Author

Commented:
It seems like I do not have inotifywait in my freeBSD 12.1

root@freebsd:~ # inotifywait
inotifywait: Command not found.
root@freebsd:~ # pkg install inotifywait
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
pkg: No packages available to install matching 'inotifywait' have been found in the repositories
root@freebsd:~ # find / -name inotifywait
root@freebsd:~ # 

Open in new window


How to get it? Also I would appreciate if I could get "find" command which compares mtimes or related example. If I run it via crontab then atleast I will have 1 min delay before I reload the nginx. Is there a solution to immediate reload when there is a config change?
the port is named inotify-tools. not inotifywait.
you can search for freebsd ports using the builtin search feature or online on the freshports site.

the find command is something like this. i am not using /proc which is not mounted by default on bsd systems and using the pidfile instead. you may need to adjust paths.

find /usr/local/etc/nginx -newer /var/run/nginx.pid | grep . >/dev/null && service nginx reload

Open in new window


inotify is merely a complement to a cron if you really need changes to be pickedup instantly. it will only work when the watcher is running.

i leave the exercise to provide an inotify script to others. you can also simply run something like this

* * * * * flock -w 60 /var/run/nginx_watcher.lock sh -c 'while sleep 5 ; do find .... ; done'

Open in new window


this will pick changes within 5 seconds which seems more than enough

___

as a side note, which mauy or may not be helpful to you, i deploy configs remotely using scripts. each of those scripts would do roughly the same thing :
- grab the config
- lint the config, check for errors
- update the config file if it changed
- check for a running daemon older than the configs. stop it if there is one
- start the daemon
- perform a few basic checks. complain on error

the same scripts run periodically and can also be run manually while working on them. this is very convenient and allows to handle lots of machines without hassle and without hardly ever actually login on most machines.
Fractional CTO
Distinguished Expert 2019
Commented:
Another option is to use http://manpages.ubuntu.com/manpages/bionic/man5/incrontab.5.html which is a inotify() based CRON facility.

Thinking about your situation, likely using incron will be easier to setup + get working.
Balbir SinghSystem Administrator

Author

Commented:
Thanks David, I am giving a try to incrontab, it looks good, though whenever I put below in incrontab for root user:

/usr/local/etc/nginx/vhosts IN_MODIFY /usr/sbin/service nginx reload

Open in new window

and then I verify using incrontab -e then I get below:

/usr/local/etc/nginx/vhosts     IN_MODIFY       /usr/sbin/service nginx reload

Open in new window


It seems delimiter between these components changes from a single "space" to multiple space or "tab" which in turn give these error:

Jan 22 22:07:03 freebsd incrond[32793]: cannot exec process: No such file or directory

Open in new window


Appreciate any suggestion on how to fix it.
nociSoftware Engineer
Distinguished Expert 2019

Commented:
If your system is systemd based you may need to use the [bsystemctl restart nginx[/b]  in stead of service nginx restart
@noci : that's freebsd... hopefully still systemd-safe ;)
nociSoftware Engineer
Distinguished Expert 2019

Commented:
@skull .. you are right.. it was clearly past bedtime ... when i answered..  :-( and i agree.   ( or it starts to look like Mac...)
David FavorFractional CTO
Distinguished Expert 2019

Commented:
You're welcome!

Glad this simple fix worked for you!

About your whitespace issue. First I've heard of this + looking at my incron entries, looks like I only use single spaces across all entries.

If this problem persists, I'd open a support ticket with the incron dev project to get this fixed.
Balbir SinghSystem Administrator

Author

Commented:
Thanks David.

Whitespace issue is fixed after some wrong entry on my side. Though I am having a peculiar issue. Whenever there is a file event a child process is executed and continue to be in process until even though associated event is executed.

I have following incrontab entry

cat /usr/local/etc/incron.d/nginx
/usr/local/etc/nginx/nginx.conf IN_ATTRIB /usr/local/sbin/nginx -s reload

and when I look at process tree then I see below:

pstree -p $(cat /var/run/incrond.pid )
-+= 00001 root /sbin/init --
 \-+= 61144 root /usr/local/sbin/incrond
   |--- 03029 root /usr/local/sbin/incrond
   |-+- 61212 root /usr/local/sbin/incrond
   | \--- 68983 root /usr/local/sbin/incrond
   \--- 68674 root /usr/local/sbin/incrond

and it continue to increase when there is more event in /usr/local/etc/nginx/nginx.conf