41

How do I restart a Systemd service when a file change. I've got a Java service that I want to reload when any jar file changes.

This is my setup:

srv.service

[Unit]
Description=srv 0.1: Service's description
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/srv
ExecStart=/opt/srv/bin/srv
User=root
Group=root

[Install]
WantedBy=multi-user.target

srv.path

[Path]
PathModified=/opt/srv/lib/

I also tried using PathChanged and using a file instead a directory.

When I installed the service I executed: sudo systemctl daemon-reload and sudo systemctl enable srv

Thanks!

jaguililla
  • 513
  • 1
  • 4
  • 7
  • 3
    Not tested so not an answer, but from the documentation it seems that `path` units are only useful for activating (starting) other units. Here you could probably create `srv-restart.path` with `PathChanged=/opt/srv/lib/` and `srv-restart.service` with `ExecStart=systemctl restart srv.service`. – Michał Politowski Jan 26 '17 at 12:46
  • It seems that if you name it the same as the service (with .path) the path file refers to the same service: https://www.freedesktop.org/software/systemd/man/systemd.path.html however... I don't know if it only starts a service or it even restart it if it is already running – jaguililla Jan 26 '17 at 13:12
  • As I understand it from the docs, `srv.path` can only do the equivalent of `systemclt start srv.service`, so for automating restarts you will need another service, which when started restarts your service. – Michał Politowski Jan 26 '17 at 13:16
  • You need to start it `systemctl start srv.path` - and to have it started on boot `systemctl preset srv.path` – Michael D. Jan 26 '17 at 13:25
  • see (second) answer by JdeBP http://unix.stackexchange.com/questions/203637/how-can-i-start-a-file-processing-daemon – Michael D. Jan 26 '17 at 13:26
  • Thanks for your comments, last two replies make my service start if a file change... But once it is started, if a file is modified, the service is not reloaded again. Do you know if this is feasible? – jaguililla Jan 26 '17 at 13:40
  • 1
    Relevant: https://github.com/systemd/systemd/issues/4324 – Michał Politowski Jan 26 '17 at 15:03

2 Answers2

55

Michal Politowski's comment is exactly correct. I use this method to automatically restart services when new artifacts are deployed. It is very helpful.

To be clear, you need:

srv.service

[Unit]
Description=srv 0.1: Service's description
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/srv
ExecStart=/opt/srv/bin/srv
User=root
Group=root

[Install]
WantedBy=multi-user.target

srv-watcher.service

[Unit]
Description=srv restarter
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl restart srv.service

[Install]
WantedBy=multi-user.target

srv-watcher.path

[Path]
PathModified=/opt/srv/lib

[Install]
WantedBy=multi-user.target
John
  • 666
  • 7
  • 4
  • 15
    Are there any guarantees about when this is triggered if lots of files are getting changed in rapid succession? – Rich Remer Feb 22 '18 at 23:29
  • 8
    Is important to remember that the «.path» unit also needs to be enabled. In this case: `systemctl enable srv-watcher.path && systemctl start srv-watcher.path` – Pau Ruŀlan Ferragut Apr 13 '18 at 09:57
  • 1
    If your restart service is not of the same name as the `.path` file then just add `Unit=nameofmyrestart.service` to the `[Path]` section of your `.path` file. https://www.freedesktop.org/software/systemd/man/systemd.path.html#Unit= – DKebler Mar 19 '19 at 02:10
  • Works fine in CentOS for restarting Kestrel (ASP.NET Core) – Suleman Oct 07 '19 at 05:39
  • the .service need to be disabled otherwise it will run on boot... also note that this does not work with sub-folders – intika Jan 28 '20 at 07:01
  • 3
    What if you want to run the service after a succession of file changes? i.e. only run it once the consecutive changes stop so we avoid restarting for each change. – djuarez Mar 03 '21 at 13:36
17

The answer above is almost great, but it's missing a few things that took me a while to figure out. Others came across the same issues, see the comments section.

systemctl enable srv-watcher.{path,service}
systemctl start srv-watcher.{path,service}

srv.service

[Unit]
Description=srv 0.1: Service's description
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/srv
ExecStart=/opt/srv/bin/srv
User=root
Group=root

[Install]
WantedBy=multi-user.target

srv-watcher.service

[Unit]
Description=srv restarter
After=network.target
StartLimitIntervalSec=10
StartLimitBurst=5

[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl restart srv.service

[Install]
WantedBy=multi-user.target

srv-watcher.path

[Path]
Unit=srv-watcher.service
PathChanged=/opt/srv/lib 
# trigger on changes to a file not just create/delete
# don't put comments in the same line as the command

[Install]
WantedBy=multi-user.target

If it is working, you will see these messages in journalctl

$: journalctl -f -o cat -u srv-watcher
Starting srv-watcher...                                                                                          
Started srv-watcher.

Other things to note, patch may fire many times but the srv-watcher.service will respect the default limit of 5 restarts in 10 second intervals. https://www.freedesktop.org/software/systemd/man/systemd.unit.html#StartLimitIntervalSec=interval

Drew
  • 281
  • 2
  • 6
  • Thanks for your answer-- it really makes sense of the accepted answer. Question: have you looked at putting in explicit "Requires=" or "After=" for the watcher service files? Does it matter and would it work like one would expect? – Zchpyvr Mar 26 '20 at 16:46
  • 3
    What if you want to run the service after a succession of file changes? i.e. only run it once the consecutive changes stop so we avoid restarting for each change. – djuarez Mar 03 '21 at 13:37
  • Getting `Failed to restart srv.service: Interactive authentication required.` This is because I have strict access controls on the system & running systemctl might need sudo. `kill` would need process id for the srv.service but would need some minor scripting to obtain the pid – Rajeev Ranjan Jul 05 '23 at 17:10