103

I'm working on a systemd .service script that is supposed to start after a CIFS network location is mounted via /etc/fstab to /mnt/ on boot-up.

The script waits for an OpenVPN dependency script to launch first, but I also want it to wait for mount to complete.

/etc/systemd/system/my-daemon.service:

[Unit]
Description=Launch My Daemon
After=network.target vpn-launch.service
Requires=vpn-launch.service

I tried to add systemd.mount to the line: After=network.target vpn-launch.service systemd.mount, but it didn't give the results I was hoping for.

1
  • Does it work if you add systemd-remount-fs to your After list? Commented Dec 4, 2015 at 19:13

5 Answers 5

153
+50

a CIFS network location is mounted via /etc/fstab to /mnt/ on boot-up.

No, it is not. Get this right, and the rest falls into place naturally.

The mount is handled by a (generated) systemd mount unit that will be named something like mnt-wibble.mount. You can see its actual name in the output of the follwoing command:

systemctl list-units --type=mount

You can look at it in detail just like any other unit with:

systemctl status

Very simply, then: you have to order your unit to be started after that mount unit is started.

After=network.target vpn-launch.service mnt-wibble.mount

Further reading

7
  • 16
    For followers, "wibble" is just a dummy name, like "foobar"
    – rogerdpack
    Commented Jul 5, 2019 at 17:03
  • 7
    Isn't it better to use something like mnt-[disk name].mount instead of mnt-wibble.mount in the answer so that users would not type that exact name? Commented Oct 30, 2020 at 14:58
  • 1
    This answer is incomplete. You also need to add the mount unit to the Requires= definition. See answer below.
    – nmgeek
    Commented Apr 5, 2021 at 16:46
  • For some reason it doesn't work for me. I'm trying: After=systemd-udevd mnt-usb23.mount and also RequiresMountsFor=/mnt/usb23. But it doesn't work.
    – hudac
    Commented Aug 8, 2021 at 18:50
  • 1
    Regardless of the wibblers in the comments, I found this to be a great answer. I came in looking for a quick "systemd wait until.." hack and I left with slightly more knowledge than I bargained for. Bravo.
    – bitofagoob
    Commented Sep 15, 2022 at 21:58
39

Although both answers are correct, I want to add my two cents to the discussion, because when I have looked for it I was missing some instructions and examples of how to proceed.

  1. Add the filesystem to /etc/fstab
  2. Type mount -a which mounts all filesystems mentioned in fstab
  3. Look for the systemd unit that has been generated with:

    systemctl list-units | grep '/path/to/mount' | awk '{ print $1 }'

    (should return something that ends with .mount)
  4. Add the found mount-unit to the After= statement in the *.service file

Here is an example of starting the my-daemon service on boot but after the network is ready, a CIFS share is mounted at /mnt/cifs, and the vpn-launch service has started:

/etc/fstab

//servername/sharename /mnt/cifs cifs defaults,some,other,options 0 0

Note: You may want to add nofail to your fstab options (e.g. when using an external drive). Otherwise, your machine won't boot if the device is not connected. See ArchWiki's fstab article


/etc/systemd/system/my-daemon.service

[Unit]
Description=Launch My Daemon
Requires=vpn-launch.service mnt-cifs.mount
After=network.target vpn-launch.service mnt-cifs.mount

[Service]
ExecStart=/path/to/my-daemon

[Install]
WantedBy=multi-user.target

Do not forget to enable the service such that it is started on boot: systemctl enable my-daemon

Note that this works for other filesystems (NFS, HDDs, etc.) as well.

As already mentioned, both answers are correct and I encourage everybody to read them but for me a couple of examples would have saved me some time.

Update (2019-06-25):

  • added a note regarding fstab options to prevent boot lock when using external drives
  • added mnt-cifs.mount to the Requires= list which causes the my-daemon.service fail to start-up when the cifs mount was not successfully mounted
2
  • 1
    Just to be clear, "mnt-cifs.mount" is the name of the mount unit for your specific mount-point from systemctl list-units --type=mount?
    – smdvlpr
    Commented Nov 8, 2019 at 23:55
  • This answer is more complete. You also need the Requires= definition. Unfortunately even that may not work during boot because systemd has a bug described here. Does anyone know a workaround to the bug?
    – nmgeek
    Commented Apr 5, 2021 at 16:49
29

Sorry but I can't comment yet.

Like JdeBP said, you should be ordering on the filesystem mount. You can predict the name of the mount unit or, alternatively, you can use (in unit section):

RequiresMountsFor=/absolute/path/of/mount

This option creates the dependencies to the appropriate *.mount units to make the path accessible before starting the service. It may not be on all systemd versions, but I've been using it in a CentOS 7 machine for the last 6 months or so.

5
  • 1
    (And your differences from vanilla systemd are here.) RequiresMountsFor= does come with its own set of caveats. With RedHat bug #1088057 and Chris Siebenmann in hand, you should be able to answer superuser.com/questions/988734 . It's a CIFS mount in this question, too. But the implication is that it is auto, fortunately.
    – JdeBP
    Commented Dec 13, 2015 at 6:19
  • @JdeBP Thank you for the comment. I wasn't aware of the caveats and issues on that feature. Commented Dec 13, 2015 at 15:56
  • 2
    The issue with RequiresMountsFor= was that it didn't pull in the units to do the mount if they were not required by something else. E.g., noauto mounts in fstab. But this was changed ~2017 so there shouldn't be a problem using RequiresMountsFor anymore.
    – TrentP
    Commented Feb 27, 2020 at 20:18
  • 1
    Simple question, but I can't find the answer anywhere: how would I go about requiring multiple mounts? Is it space-delimited like other parameters? Commented Jun 14, 2021 at 13:51
  • 1
    Seems to be space seoarated as you suspected: man7.org/linux/man-pages/man5/systemd.unit.5.html Commented Jun 15, 2021 at 18:06
5

First determine the mount unit name with:

systemctl list-units --type=mount

It will likely be named after the mountpoint in /mnt such as

mnt-syncthing\x2ddeb.mount

for a mount point of /mnt/syncthing .

Then add this mount unit to the After= directive in your service, such as:

After=network.target mnt-syncthing\x2ddeb.mount

Edit your service with

systemctl edit --full [servicename.service]

to preserve the config after an update. Now your service will wait for the mount before starting!

2
3

@bm-bergmotte: thanks for your instruction which helped me a lot. For me it´s just working, if I put

After=network.target vpn-launch.service mnt-cifs.mount
Requires=vpn-launch.service mnt-cifs.mount

If I don´t put "mnt-cifs.mount" inside the "Requires" (and in this order) it works for reboot/ startup, but the service starts anyway, if the device is not mounted. After putting it additionally inside ""Requires" the service mounts the device before starting it, if the device was not mounted.

2
  • 2
    You are right. If the mount fails then the my-daemon.service is started anyway. After= just dictates the order. Requires= makes it mandatory that the cifs mount must be present (see Sufiyan Ghori answer on that one). I'll update my answer.
    – voidptr127
    Commented Jun 25, 2019 at 16:05
  • 3
    Doesn't Requires= imply After=, or is After= still, um.. required?
    – cueedee
    Commented Mar 14, 2023 at 15:18

You must log in to answer this question.

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