How to assure a “oneshot” service gets retried if it fails the first time

systemd

I've read the systemd service manpage a few times, but I still cannot figure out a basic systemd pattern:

I want to run a startup process once (like a docker container, or format a drive) at bootup, successfully to completion. But if I use Type=oneshot for that, then I can't use Restart=on-failure, and if it fails, then it won't retry the job. Am I missing something obvious here?

I also tried setting Type=simple with Restart=on-failure, but this in many cases I need the following behavior (from the manpage) that oneshot services give:

Behavior of oneshot is similar to simple; however, it is expected that the process has to exit before systemd starts follow-up units.

Updates:

Best Answer

One possible workaround I'm trying is

  [Unit]
    Description=Tags instance and EBS vols
    After=docker.service
    Requires=docker.service

    [Service]
    ExecStartPre=/usr/bin/docker run --rm -v /opt/tag.sh:/tag.sh -v /opt:/ack --entrypoint=/bin/sh alpine /tag.sh
    ExecStartPre=/usr/bin/sh -c '[[ -e /opt/TAG_SUCCESS ]]'
    ExecStart=/usr/bin/rm /opt/TAG_SUCCESS
    Restart=on-failure
    RestartSec=30

Where the script tag.sh will touch /ack/TAG_SUCCESS at the end of execution. I believe this gets pretty close to the desired behavior because ExecStartPre will sequentially execute, waiting for successful completion before calling ExecStart and the unit is only considered Starting once ExecStart is called by which point we're sure we've completed the startup task.

But this still feels like a giant hack?

Related Question