42

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!

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. Jan 26, 2017 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: 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, 2017 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. Jan 26, 2017 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, 2017 at 13:25
  • 1
    Relevant: github.com/systemd/systemd/issues/4324 Jan 26, 2017 at 15:03

2 Answers 2

57

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
6
  • 16
    Are there any guarantees about when this is triggered if lots of files are getting changed in rapid succession?
    – Rich Remer
    Feb 22, 2018 at 23:29
  • 9
    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 Apr 13, 2018 at 9: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. freedesktop.org/software/systemd/man/systemd.path.html#Unit=
    – DKebler
    Mar 19, 2019 at 2:10
  • Works fine in CentOS for restarting Kestrel (ASP.NET Core)
    – Suleman
    Oct 7, 2019 at 5:39
  • 4
    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 3, 2021 at 13:36
18

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

3
  • 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, 2020 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 3, 2021 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 Jul 5, 2023 at 17:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .