This command is based on an extrapolation and adaptation to the case in question of an answer of mine on Ask Ubuntu, which I converted to a systemd-run command. The extrapolated and adapted answer, useful to understand the reasoning behind the command and useful to set this up as permanent service rather than as a transient unit, is reported down below.
Note that this will run on poweroff and won't run on reboot. This is intentional. If this is undesired and you want to run this both on poweroff and on reboot, simply replace the ExecStop property with just dnf5 update -y package1.
systemd-run \
--property="ExecStop=sh -c 'systemctl list-jobs | grep -q \"poweroff.target.*start\" && dnf5 update -y package1'" \
--property=RemainAfterExit=true \
--property=TimeoutStopSec=infinity \
--property=After=network-online.target \
true
Replace package1 according to needs.
What my research has taught me is that:
- It's hard to latch the service to the right point in the poweroff / reboot chain if you're approaching the problem in terms of "order in which services go down in the poweroff / reboot chain"; there's just too much to keep track of. The trick here, is to approach the problem in terms of "order in which services go up in the startup chain", and to latch a
oneshotservice right afternetwork-online.targethas gone up, at the same time marking it as active usingRemainAfterExit=trueand providing it with anExecStopaction which will be "naturally" triggered when the system is going down, just right before the network goes down. - DeterminingThere's no super-clean way to determine if the system is going down for poweroff or for rebootreboot; however, this can be done reliably by checking which systemd special targets are active during the poweroff / reboot sequence; in this case,
poweroff.targetwill be active only in case the system is going down for poweroff.
So, putting everything together, this could be done by creating a service /etc/systemd/system/update.service (the name of the file and the Description and ExecStop fields, of course, may be adjusted; make sure the file is owned by root:root and has 644 / -rw-r--r-- permissions):
[Install]
WantedBy=multi-user.target
[Service]
ExecStop=sh -c 'systemctl list-units --ty=target --al --o=jsonjobs | jqgrep -e 'any(.[];q "poweroff.unit==\"powerofftarget.target\")'*start" && dnf5 update -y package1'
RemainAfterExit=true
TimeoutStopSec=infinity
[Unit]
After=network-online.target
Description=update
Once done, run sudo systemctl enable --now update.service to enable the service.
TimeoutStopSec=infinity is obviously needed in case of an update, but it can be changed in case you want to use this for something else.