20

Systemd offers unit files whom control monitoring of a certain path trough inotify: systemd.path(5). If a file or directory is modified in the watched path the corresponding systemd.service(5) is called.

According to the inotify(7) man page:

To determine what events have occurred, an application read(2)s from the inotify file descriptor. If no events have so far occurred, then, assuming a blocking file descriptor, read(2) will block until at least one event occurs (unless interrupted by a signal, in which case the call fails with the error EINTR; see signal(7)).

Each successful read(2) returns a buffer containing one or more of the following structures:

      struct inotify_event {
          int      wd;       /* Watch descriptor */
          uint32_t mask;     /* Mask of events */
          uint32_t cookie;   /* Unique cookie associating related
                                events (for rename(2)) */
          uint32_t len;      /* Size of name field */
          char     name[];   /* Optional null-terminated name */
      };

So if systemd see a change in the watched path, is there a way of getting any data from the read(2) command? Notably I need the name[] to be used as an argument to the command for the ExecStart= in the systemd.service(5) unit statement.

[Service]
ExecStart=/usr/bin/command --file=$inotifyName
Tim
  • 1,083
  • 9
  • 13
  • Sure there is: can you program C? – MariusMatutiae Jan 25 '14 at 12:58
  • Nope. Just pointing out, that if a program is using inotify, it can include `read(2)`, to work with the event. So how does systemd use it and can I use data from `read(2)` in a systemd unit file as a variable or specifier? – Tim Jan 25 '14 at 17:03
  • It does so from within a C program: read(2) is a system all, you can check it from man man. – MariusMatutiae Jan 25 '14 at 17:20
  • 1
    I know read(2) is a system call. I do not want to do anything with read(2). I want to run a command from a `systemd.service` file, triggered by a `systemd.path` file, which in turn uses inotify and I *assume* it uses something like `read(2)`. I need the a string containing the filename that triggered the event appended to the `ExecStart` statement in the unit file. – Tim Jan 25 '14 at 19:09
  • 2
    Did you find out? I'm looking at running a script as well. – CMCDragonkai Jan 17 '16 at 05:45
  • @Tim I know this has been posted a while ago, nevertheless - did you find a solution? – Moritz Friedrich Jun 28 '18 at 09:20
  • 1
    Hi, no never found (I stopped looking to be honest) – Tim Jun 28 '18 at 09:30
  • 1
    systemd doesn't pass its file descriptor that has inotify open to the called process. The python [inotify](https://pypi.org/project/inotify/) should be easy enough to script up. – danblack Aug 24 '18 at 06:27
  • 2
    It's a fair question, and I'd like to hear the same. In particular, because I finally got the skeleton of my monitoring service moved over from inotify (!) with hope hung on using systemd Path units like inotify! :( I feel I (we) must be overlooking something...? – texas-bronius Dec 21 '18 at 19:21

1 Answers1

1

Steward gave a quiet complete proposal for a reasonable workaround on unix.stackexchange.com

After some playing I found the easiest way was to use one *.path file per path and template each path into a single *@.service file.

cheers

domson
  • 131
  • 4
  • 1
    Welcome to Super User! Please quote the essential parts of the answer from the reference link(s), as the answer can become invalid if the linked page(s) change. – DavidPostill Aug 19 '20 at 17:06