Search code examples
linuxservicesystemd

systemd service run before and after other service starts


I want to run a script before and after autofs starts. I have two systemd service:

backup1.service runs before autofs

[Unit]
Description=Backup mount

[Service]
ExecStart=/backup/sw/bmount before


[Install]
WantedBy=autofs.service

backup2.service runs after autofs

[Unit]
Description=Backup mount
PartOf=autofs.service
After=autofs.service

[Service]
ExecStart=/backup/sw/bmount after

[Install]
WantedBy=autofs.service

I can determine the after/before status in the bmount script, so I can call it without parameter and I could use only one service, but don't know how.

Is it possible?


Solution

  • There are a few ways to do this:

    Edit autofs.service

    By design, service files should be site-maintainable. On Debian-based platforms, vendor-supplied service files are in /lib/systemd/system/, I think redhat has them in /usr/lib/systemd/system/ but you can override these with site-managed service files in /etc/systemd/system/.

    In that case, I'd

    cp /lib/systemd/system/autofs.service /etc/systemd/system/autofs.service
    

    Then in the [Service] section, I'd add:

    ExecStartPre=/backup/sw/bmount before
    ExecStartPost=/backup/sw/bmount after
    

    The systemd.service manpage says:

    ExecStart= commands are only run after all ExecStartPre= commands exit successfully.

    ExecStartPost= commands are only run after the commands specified in ExecStart= have been invoked successfully, as determined by Type= (i.e. the process has been started for Type=simple or Type=idle, the last ExecStart= process exited successfully for Type=oneshot, ...).

    Drop-in service parameters

    A more elegant way to do the same thing as what's above is to use a drop-in. Simply create /etc/systemd/system/autofs.service.d/backup.conf with this content:

    [Service]
    ExecStartPre=/backup/sw/bmount before
    ExecStartPost=/backup/sw/bmount after
    

    Relationships

    Maybe autofs.service already has ExecStartPre and ExecStartPost commands and you are worried about interferring with that service. In that case, you can use relationships to start/stop your services.

    [Unit]
    Description=Backup mount
    PartOf=autofs.service
    Before=autofs.service
    
    [Service]
    Type=oneshot
    ExecStart=/backup/sw/bmount before
    
    [Install]
    WantedBy=autofs.service
    

    and

    
    [Unit]
    Description=Backup mount
    PartOf=autofs.service
    After=autofs.service
    
    [Service]
    Type=oneshot
    ExecStart=/backup/sw/bmount after
    
    [Install]
    WantedBy=autofs.service
    

    In this case:

    • PartOf=autofs.service means "When systemd stops or restarts autofs.service, the action is propagated to backup.service"
    • Before=autofs.service means "If both units are being started, autofs.service's startup is delayed until backup.service has finished starting up."
    • After=autofs.service means "If both units are being started, backup.service's startup is delayed until autofs.service has finished starting up."
    • WantedBy=autofs.service means "backup.service will be started if autofs.service is".
    • Type=oneshot means that the service will still be considered as running, even after the ExecStart= process completes.

    Be sure to run systemctl daemon-reload so systemd reads the new service. Also run systemctl enable backup.service to ensure that the WantedBy= becomes a Wants= for autofs.service.

    I think you were pretty close with your solution.