How to write a systemd user service that requires an active session

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
1
down vote

favorite












I've created a systemd user service to run a duplicity backup job once a day at 17:00 broadly based on an article in Fedora Magazine. I'm running Fedora 28 with the Gnome desktop. My systemd timer config is:



[Unit]
Description=daily-backup timer

[Timer]
OnCalendar=*-*-* 17:00:00
Unit=daily-backup.service
Persistent=true

[Install]
WantedBy=default.target


This works well except in the case where the machine was switched off when the backup was due to run. The next time I login, the persistent option ensures the backup runs immediately. Unfortunately the backup script fails at this point because the script tries to run before the user session is active. The backup script starts by trying to mount the backup disk if its not already mounted:



#!/usr/bin/env bash

USER=$(whoami)
MOUNTPOINT="/run/media/$USER/$2"
DEVICE=$(blkid -l -o device -t LABEL="$2")

if [ ! -d "$MOUNTPOINT" ]; then
gio mount --device $DEVICE
fi

# Call duplicity...


It appears, however, that until the user session is active, the script cannot mount the disk. I can work around this by polling for an active session, but this is a crude solution to the problem:



#!/usr/bin/env bash

USER=$(whoami)
MOUNTPOINT="/run/media/$USER/$2"
DEVICE=$(blkid -l -o device -t LABEL="$2")

# Poll for an active session
for i in 1..30
do
SESSION_STATE=$(loginctl show-user "$USER" -p State --value)
[ "$SESSION_STATE" != "active" ] && sleep 1s || break
done

if [ ! -d "$MOUNTPOINT" ]; then
gio mount --device $DEVICE
fi


It seems like there should be a way to configure my systemd user service to require an active user session but I've been unable to work out how to do that. Does anyone know if this is possible?







share|improve this question



















  • I don't know. Have you considered adding the disk to /etc/fstab with options noauto,user? That should allow mount as any unprivileged user. This is assuming the disk isn't encrypted or something, and that the technically more lax security wouldn't bother you. I haven't tested whether you have to use mount, or whether gio mount / the udisks backend are then smart enough to let you do it from an inactive session.
    – sourcejedi
    May 8 at 16:23











  • You're mixing things that shouldn't be mixed. If your cron job depends on a mount, the script shouldn't try to do the mount, systemd should do it. And then if you want the mount to auto start on a user session, that shouldn't be part of the cron job at all. That should be configuration of the mount unit (or auto-start the cron and have the systemd dependency auto-start the mount). Then you can configure your cron unit to depend on the mount unit. Once all this is cleaned up it should work. Don't have time to write a full answer right now, but this might get you in the right direction.
    – Patrick
    May 8 at 17:03







  • 1




    There's no cron job at all in the question, Patrick, just a per-user timer unit and a script run by the associated per-user service unit that that timer activates. And the questioner's problem is that by the time that per-user service management, started up by a login session, has fired off the pending timer, that login session itself has not yet got around to (allowing) mounting the things that the per-user service is needing to be mounted. It would be a bad answer to go on about cron jobs. It might be a good answer to make use of the per-user GNOME VFS service unit.
    – JdeBP
    May 9 at 7:56







  • 1




    @sourcejedi I will investigate the /etc/fstab option again but iirc from the last time I tried that, the backup script still failed because the gnome-keyring had not yet initialized/unlocked and that was required so that duplicity could access the GPG keys.
    – suilven
    May 9 at 23:27














up vote
1
down vote

favorite












I've created a systemd user service to run a duplicity backup job once a day at 17:00 broadly based on an article in Fedora Magazine. I'm running Fedora 28 with the Gnome desktop. My systemd timer config is:



[Unit]
Description=daily-backup timer

[Timer]
OnCalendar=*-*-* 17:00:00
Unit=daily-backup.service
Persistent=true

[Install]
WantedBy=default.target


This works well except in the case where the machine was switched off when the backup was due to run. The next time I login, the persistent option ensures the backup runs immediately. Unfortunately the backup script fails at this point because the script tries to run before the user session is active. The backup script starts by trying to mount the backup disk if its not already mounted:



#!/usr/bin/env bash

USER=$(whoami)
MOUNTPOINT="/run/media/$USER/$2"
DEVICE=$(blkid -l -o device -t LABEL="$2")

if [ ! -d "$MOUNTPOINT" ]; then
gio mount --device $DEVICE
fi

# Call duplicity...


It appears, however, that until the user session is active, the script cannot mount the disk. I can work around this by polling for an active session, but this is a crude solution to the problem:



#!/usr/bin/env bash

USER=$(whoami)
MOUNTPOINT="/run/media/$USER/$2"
DEVICE=$(blkid -l -o device -t LABEL="$2")

# Poll for an active session
for i in 1..30
do
SESSION_STATE=$(loginctl show-user "$USER" -p State --value)
[ "$SESSION_STATE" != "active" ] && sleep 1s || break
done

if [ ! -d "$MOUNTPOINT" ]; then
gio mount --device $DEVICE
fi


It seems like there should be a way to configure my systemd user service to require an active user session but I've been unable to work out how to do that. Does anyone know if this is possible?







share|improve this question



















  • I don't know. Have you considered adding the disk to /etc/fstab with options noauto,user? That should allow mount as any unprivileged user. This is assuming the disk isn't encrypted or something, and that the technically more lax security wouldn't bother you. I haven't tested whether you have to use mount, or whether gio mount / the udisks backend are then smart enough to let you do it from an inactive session.
    – sourcejedi
    May 8 at 16:23











  • You're mixing things that shouldn't be mixed. If your cron job depends on a mount, the script shouldn't try to do the mount, systemd should do it. And then if you want the mount to auto start on a user session, that shouldn't be part of the cron job at all. That should be configuration of the mount unit (or auto-start the cron and have the systemd dependency auto-start the mount). Then you can configure your cron unit to depend on the mount unit. Once all this is cleaned up it should work. Don't have time to write a full answer right now, but this might get you in the right direction.
    – Patrick
    May 8 at 17:03







  • 1




    There's no cron job at all in the question, Patrick, just a per-user timer unit and a script run by the associated per-user service unit that that timer activates. And the questioner's problem is that by the time that per-user service management, started up by a login session, has fired off the pending timer, that login session itself has not yet got around to (allowing) mounting the things that the per-user service is needing to be mounted. It would be a bad answer to go on about cron jobs. It might be a good answer to make use of the per-user GNOME VFS service unit.
    – JdeBP
    May 9 at 7:56







  • 1




    @sourcejedi I will investigate the /etc/fstab option again but iirc from the last time I tried that, the backup script still failed because the gnome-keyring had not yet initialized/unlocked and that was required so that duplicity could access the GPG keys.
    – suilven
    May 9 at 23:27












up vote
1
down vote

favorite









up vote
1
down vote

favorite











I've created a systemd user service to run a duplicity backup job once a day at 17:00 broadly based on an article in Fedora Magazine. I'm running Fedora 28 with the Gnome desktop. My systemd timer config is:



[Unit]
Description=daily-backup timer

[Timer]
OnCalendar=*-*-* 17:00:00
Unit=daily-backup.service
Persistent=true

[Install]
WantedBy=default.target


This works well except in the case where the machine was switched off when the backup was due to run. The next time I login, the persistent option ensures the backup runs immediately. Unfortunately the backup script fails at this point because the script tries to run before the user session is active. The backup script starts by trying to mount the backup disk if its not already mounted:



#!/usr/bin/env bash

USER=$(whoami)
MOUNTPOINT="/run/media/$USER/$2"
DEVICE=$(blkid -l -o device -t LABEL="$2")

if [ ! -d "$MOUNTPOINT" ]; then
gio mount --device $DEVICE
fi

# Call duplicity...


It appears, however, that until the user session is active, the script cannot mount the disk. I can work around this by polling for an active session, but this is a crude solution to the problem:



#!/usr/bin/env bash

USER=$(whoami)
MOUNTPOINT="/run/media/$USER/$2"
DEVICE=$(blkid -l -o device -t LABEL="$2")

# Poll for an active session
for i in 1..30
do
SESSION_STATE=$(loginctl show-user "$USER" -p State --value)
[ "$SESSION_STATE" != "active" ] && sleep 1s || break
done

if [ ! -d "$MOUNTPOINT" ]; then
gio mount --device $DEVICE
fi


It seems like there should be a way to configure my systemd user service to require an active user session but I've been unable to work out how to do that. Does anyone know if this is possible?







share|improve this question











I've created a systemd user service to run a duplicity backup job once a day at 17:00 broadly based on an article in Fedora Magazine. I'm running Fedora 28 with the Gnome desktop. My systemd timer config is:



[Unit]
Description=daily-backup timer

[Timer]
OnCalendar=*-*-* 17:00:00
Unit=daily-backup.service
Persistent=true

[Install]
WantedBy=default.target


This works well except in the case where the machine was switched off when the backup was due to run. The next time I login, the persistent option ensures the backup runs immediately. Unfortunately the backup script fails at this point because the script tries to run before the user session is active. The backup script starts by trying to mount the backup disk if its not already mounted:



#!/usr/bin/env bash

USER=$(whoami)
MOUNTPOINT="/run/media/$USER/$2"
DEVICE=$(blkid -l -o device -t LABEL="$2")

if [ ! -d "$MOUNTPOINT" ]; then
gio mount --device $DEVICE
fi

# Call duplicity...


It appears, however, that until the user session is active, the script cannot mount the disk. I can work around this by polling for an active session, but this is a crude solution to the problem:



#!/usr/bin/env bash

USER=$(whoami)
MOUNTPOINT="/run/media/$USER/$2"
DEVICE=$(blkid -l -o device -t LABEL="$2")

# Poll for an active session
for i in 1..30
do
SESSION_STATE=$(loginctl show-user "$USER" -p State --value)
[ "$SESSION_STATE" != "active" ] && sleep 1s || break
done

if [ ! -d "$MOUNTPOINT" ]; then
gio mount --device $DEVICE
fi


It seems like there should be a way to configure my systemd user service to require an active user session but I've been unable to work out how to do that. Does anyone know if this is possible?









share|improve this question










share|improve this question




share|improve this question









asked May 8 at 16:04









suilven

83




83











  • I don't know. Have you considered adding the disk to /etc/fstab with options noauto,user? That should allow mount as any unprivileged user. This is assuming the disk isn't encrypted or something, and that the technically more lax security wouldn't bother you. I haven't tested whether you have to use mount, or whether gio mount / the udisks backend are then smart enough to let you do it from an inactive session.
    – sourcejedi
    May 8 at 16:23











  • You're mixing things that shouldn't be mixed. If your cron job depends on a mount, the script shouldn't try to do the mount, systemd should do it. And then if you want the mount to auto start on a user session, that shouldn't be part of the cron job at all. That should be configuration of the mount unit (or auto-start the cron and have the systemd dependency auto-start the mount). Then you can configure your cron unit to depend on the mount unit. Once all this is cleaned up it should work. Don't have time to write a full answer right now, but this might get you in the right direction.
    – Patrick
    May 8 at 17:03







  • 1




    There's no cron job at all in the question, Patrick, just a per-user timer unit and a script run by the associated per-user service unit that that timer activates. And the questioner's problem is that by the time that per-user service management, started up by a login session, has fired off the pending timer, that login session itself has not yet got around to (allowing) mounting the things that the per-user service is needing to be mounted. It would be a bad answer to go on about cron jobs. It might be a good answer to make use of the per-user GNOME VFS service unit.
    – JdeBP
    May 9 at 7:56







  • 1




    @sourcejedi I will investigate the /etc/fstab option again but iirc from the last time I tried that, the backup script still failed because the gnome-keyring had not yet initialized/unlocked and that was required so that duplicity could access the GPG keys.
    – suilven
    May 9 at 23:27
















  • I don't know. Have you considered adding the disk to /etc/fstab with options noauto,user? That should allow mount as any unprivileged user. This is assuming the disk isn't encrypted or something, and that the technically more lax security wouldn't bother you. I haven't tested whether you have to use mount, or whether gio mount / the udisks backend are then smart enough to let you do it from an inactive session.
    – sourcejedi
    May 8 at 16:23











  • You're mixing things that shouldn't be mixed. If your cron job depends on a mount, the script shouldn't try to do the mount, systemd should do it. And then if you want the mount to auto start on a user session, that shouldn't be part of the cron job at all. That should be configuration of the mount unit (or auto-start the cron and have the systemd dependency auto-start the mount). Then you can configure your cron unit to depend on the mount unit. Once all this is cleaned up it should work. Don't have time to write a full answer right now, but this might get you in the right direction.
    – Patrick
    May 8 at 17:03







  • 1




    There's no cron job at all in the question, Patrick, just a per-user timer unit and a script run by the associated per-user service unit that that timer activates. And the questioner's problem is that by the time that per-user service management, started up by a login session, has fired off the pending timer, that login session itself has not yet got around to (allowing) mounting the things that the per-user service is needing to be mounted. It would be a bad answer to go on about cron jobs. It might be a good answer to make use of the per-user GNOME VFS service unit.
    – JdeBP
    May 9 at 7:56







  • 1




    @sourcejedi I will investigate the /etc/fstab option again but iirc from the last time I tried that, the backup script still failed because the gnome-keyring had not yet initialized/unlocked and that was required so that duplicity could access the GPG keys.
    – suilven
    May 9 at 23:27















I don't know. Have you considered adding the disk to /etc/fstab with options noauto,user? That should allow mount as any unprivileged user. This is assuming the disk isn't encrypted or something, and that the technically more lax security wouldn't bother you. I haven't tested whether you have to use mount, or whether gio mount / the udisks backend are then smart enough to let you do it from an inactive session.
– sourcejedi
May 8 at 16:23





I don't know. Have you considered adding the disk to /etc/fstab with options noauto,user? That should allow mount as any unprivileged user. This is assuming the disk isn't encrypted or something, and that the technically more lax security wouldn't bother you. I haven't tested whether you have to use mount, or whether gio mount / the udisks backend are then smart enough to let you do it from an inactive session.
– sourcejedi
May 8 at 16:23













You're mixing things that shouldn't be mixed. If your cron job depends on a mount, the script shouldn't try to do the mount, systemd should do it. And then if you want the mount to auto start on a user session, that shouldn't be part of the cron job at all. That should be configuration of the mount unit (or auto-start the cron and have the systemd dependency auto-start the mount). Then you can configure your cron unit to depend on the mount unit. Once all this is cleaned up it should work. Don't have time to write a full answer right now, but this might get you in the right direction.
– Patrick
May 8 at 17:03





You're mixing things that shouldn't be mixed. If your cron job depends on a mount, the script shouldn't try to do the mount, systemd should do it. And then if you want the mount to auto start on a user session, that shouldn't be part of the cron job at all. That should be configuration of the mount unit (or auto-start the cron and have the systemd dependency auto-start the mount). Then you can configure your cron unit to depend on the mount unit. Once all this is cleaned up it should work. Don't have time to write a full answer right now, but this might get you in the right direction.
– Patrick
May 8 at 17:03





1




1




There's no cron job at all in the question, Patrick, just a per-user timer unit and a script run by the associated per-user service unit that that timer activates. And the questioner's problem is that by the time that per-user service management, started up by a login session, has fired off the pending timer, that login session itself has not yet got around to (allowing) mounting the things that the per-user service is needing to be mounted. It would be a bad answer to go on about cron jobs. It might be a good answer to make use of the per-user GNOME VFS service unit.
– JdeBP
May 9 at 7:56





There's no cron job at all in the question, Patrick, just a per-user timer unit and a script run by the associated per-user service unit that that timer activates. And the questioner's problem is that by the time that per-user service management, started up by a login session, has fired off the pending timer, that login session itself has not yet got around to (allowing) mounting the things that the per-user service is needing to be mounted. It would be a bad answer to go on about cron jobs. It might be a good answer to make use of the per-user GNOME VFS service unit.
– JdeBP
May 9 at 7:56





1




1




@sourcejedi I will investigate the /etc/fstab option again but iirc from the last time I tried that, the backup script still failed because the gnome-keyring had not yet initialized/unlocked and that was required so that duplicity could access the GPG keys.
– suilven
May 9 at 23:27




@sourcejedi I will investigate the /etc/fstab option again but iirc from the last time I tried that, the backup script still failed because the gnome-keyring had not yet initialized/unlocked and that was required so that duplicity could access the GPG keys.
– suilven
May 9 at 23:27










2 Answers
2






active

oldest

votes

















up vote
0
down vote



accepted










tl;dr (short answer)



I believe there is no such way, at least out-of-the-box (in form of a systemd unit directive or something). However, this is certainly doable from outside of systemd.



long answer



It would be nice if systemd supported event-based triggering (in a way similar to udev's) or allowed customization of auto-generated unit files. Either idea, if implemented, would solve this problem, but both actually are long-standing shortcomings of systemd.



You may try to implement this logic yourself. If I properly understand what are you trying to actually achieve, you desire the semantics of "delaying" start-up until the session becomes active rather than "skipping" start-up if the session is inactive when the timer triggers.



Then, the basic idea would be to have a daemon that starts as a systemd user service, listens for logind's state change events on the system bus and starts/stops the timer accordingly. This should be easily doable in Python (unfortunately, bash is out of the question because there are no shell-friendly tools that allow listening for signals on D-Bus).






share|improve this answer





















  • Yes I'm trying to delay startup until the session is active and all services required by my backup script are available. It does appear to me that some interaction with the D-Bus is required here. I'm not a Python developer so I'm not going to try and implement your solution but I appreciate the feedback. My crude workaround does the job and I was mostly interested to know if there was a simple win involving systemd dependencies.
    – suilven
    May 14 at 11:06

















up vote
0
down vote













It looks (from the USER=$(whoami) line in your script) that you're running this service as a non-root user (probably by setting User= in your daily-backup.service file.)



You might want to consider setting up the service and timer units as user services, run by the systemd --user manager instead.



To do that, just create daily-backup.service and daily-backup.timer under the ~$USER/.config/systemd/user/ directory. You can essentially use the files you created in the system directory, for the most part unmodified. (You can remove the reference to User= since that will be the user you're setting it up for.)



Use systemctl --user ... commands to enable and start them and to check the status. For the install section, use:



[Install]
WantedBy=default.target


Since the user manager only knows about a default.target (and not e.g. multi-user.target.)



In order to have the user session start at boot, you can enable linger, in which case it will start early and stick around:



loginctl enable-linger $USER


(See documentation for loginctl enable-linger.)



In fact, looking at the Fedora Magazine article you referred to, it seems that's what they had in mind. The "Automate with a timer" part has references to $HOME/.config/systemd/user/.



If you want to read more on systemd user units, the Arch Linux Wiki has a nice article on it.






share|improve this answer





















  • Hmmm, re-reading your question and it seems you already have a user service... So when you're talking about "session" I guess you mean GNOME? Have you considered using systemd-mount instead of gio?
    – Filipe Brandenburger
    May 9 at 5:43






  • 2




    The question did say "systemd user service" in both title and first sentence. And the questioner does talk about the timer triggering, and hence the service being activated, by per-user service management starting up at first login.
    – JdeBP
    May 9 at 7:46











  • @JdeBP yes I realized that on re-reading the question, but I left it around as I was unsure whether the enable-linger would help... Indeed, it seems gnome-vfs-daemon is what is required here for gio to work, but it's unclear to me what starts it...
    – Filipe Brandenburger
    May 9 at 13:10










  • @FilipeBrandenburger I was not aware of systemd-mount so I'll investigate that option. One thing to note is that if I allow Gnome to automount the disk and remove the lines concerned with mounting the disk from the script, the script still fails because the disk is not yet mounted at /run/media/user/disk-label when the backup tries to run. Adding the disk to /etc/fstab is another option but iirc I tried that and the script still failed because the gnome-keyring had not yet initialized and that was required to access the GPG keys to run duplicity.
    – suilven
    May 9 at 23:24











  • @suilven One option you might want to consider is to trigger the backup when the disk is mounted (perhaps in addition to a timer.) This came up recently, see my answer at unix.stackexchange.com/a/441913/281844 for more details (though not completely sure whether doing so in a user unit will work, hmmm...)
    – Filipe Brandenburger
    May 10 at 0:18











Your Answer







StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f442587%2fhow-to-write-a-systemd-user-service-that-requires-an-active-session%23new-answer', 'question_page');

);

Post as a guest






























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
0
down vote



accepted










tl;dr (short answer)



I believe there is no such way, at least out-of-the-box (in form of a systemd unit directive or something). However, this is certainly doable from outside of systemd.



long answer



It would be nice if systemd supported event-based triggering (in a way similar to udev's) or allowed customization of auto-generated unit files. Either idea, if implemented, would solve this problem, but both actually are long-standing shortcomings of systemd.



You may try to implement this logic yourself. If I properly understand what are you trying to actually achieve, you desire the semantics of "delaying" start-up until the session becomes active rather than "skipping" start-up if the session is inactive when the timer triggers.



Then, the basic idea would be to have a daemon that starts as a systemd user service, listens for logind's state change events on the system bus and starts/stops the timer accordingly. This should be easily doable in Python (unfortunately, bash is out of the question because there are no shell-friendly tools that allow listening for signals on D-Bus).






share|improve this answer





















  • Yes I'm trying to delay startup until the session is active and all services required by my backup script are available. It does appear to me that some interaction with the D-Bus is required here. I'm not a Python developer so I'm not going to try and implement your solution but I appreciate the feedback. My crude workaround does the job and I was mostly interested to know if there was a simple win involving systemd dependencies.
    – suilven
    May 14 at 11:06














up vote
0
down vote



accepted










tl;dr (short answer)



I believe there is no such way, at least out-of-the-box (in form of a systemd unit directive or something). However, this is certainly doable from outside of systemd.



long answer



It would be nice if systemd supported event-based triggering (in a way similar to udev's) or allowed customization of auto-generated unit files. Either idea, if implemented, would solve this problem, but both actually are long-standing shortcomings of systemd.



You may try to implement this logic yourself. If I properly understand what are you trying to actually achieve, you desire the semantics of "delaying" start-up until the session becomes active rather than "skipping" start-up if the session is inactive when the timer triggers.



Then, the basic idea would be to have a daemon that starts as a systemd user service, listens for logind's state change events on the system bus and starts/stops the timer accordingly. This should be easily doable in Python (unfortunately, bash is out of the question because there are no shell-friendly tools that allow listening for signals on D-Bus).






share|improve this answer





















  • Yes I'm trying to delay startup until the session is active and all services required by my backup script are available. It does appear to me that some interaction with the D-Bus is required here. I'm not a Python developer so I'm not going to try and implement your solution but I appreciate the feedback. My crude workaround does the job and I was mostly interested to know if there was a simple win involving systemd dependencies.
    – suilven
    May 14 at 11:06












up vote
0
down vote



accepted







up vote
0
down vote



accepted






tl;dr (short answer)



I believe there is no such way, at least out-of-the-box (in form of a systemd unit directive or something). However, this is certainly doable from outside of systemd.



long answer



It would be nice if systemd supported event-based triggering (in a way similar to udev's) or allowed customization of auto-generated unit files. Either idea, if implemented, would solve this problem, but both actually are long-standing shortcomings of systemd.



You may try to implement this logic yourself. If I properly understand what are you trying to actually achieve, you desire the semantics of "delaying" start-up until the session becomes active rather than "skipping" start-up if the session is inactive when the timer triggers.



Then, the basic idea would be to have a daemon that starts as a systemd user service, listens for logind's state change events on the system bus and starts/stops the timer accordingly. This should be easily doable in Python (unfortunately, bash is out of the question because there are no shell-friendly tools that allow listening for signals on D-Bus).






share|improve this answer













tl;dr (short answer)



I believe there is no such way, at least out-of-the-box (in form of a systemd unit directive or something). However, this is certainly doable from outside of systemd.



long answer



It would be nice if systemd supported event-based triggering (in a way similar to udev's) or allowed customization of auto-generated unit files. Either idea, if implemented, would solve this problem, but both actually are long-standing shortcomings of systemd.



You may try to implement this logic yourself. If I properly understand what are you trying to actually achieve, you desire the semantics of "delaying" start-up until the session becomes active rather than "skipping" start-up if the session is inactive when the timer triggers.



Then, the basic idea would be to have a daemon that starts as a systemd user service, listens for logind's state change events on the system bus and starts/stops the timer accordingly. This should be easily doable in Python (unfortunately, bash is out of the question because there are no shell-friendly tools that allow listening for signals on D-Bus).







share|improve this answer













share|improve this answer



share|improve this answer











answered May 10 at 12:45









intelfx

2,8161122




2,8161122











  • Yes I'm trying to delay startup until the session is active and all services required by my backup script are available. It does appear to me that some interaction with the D-Bus is required here. I'm not a Python developer so I'm not going to try and implement your solution but I appreciate the feedback. My crude workaround does the job and I was mostly interested to know if there was a simple win involving systemd dependencies.
    – suilven
    May 14 at 11:06
















  • Yes I'm trying to delay startup until the session is active and all services required by my backup script are available. It does appear to me that some interaction with the D-Bus is required here. I'm not a Python developer so I'm not going to try and implement your solution but I appreciate the feedback. My crude workaround does the job and I was mostly interested to know if there was a simple win involving systemd dependencies.
    – suilven
    May 14 at 11:06















Yes I'm trying to delay startup until the session is active and all services required by my backup script are available. It does appear to me that some interaction with the D-Bus is required here. I'm not a Python developer so I'm not going to try and implement your solution but I appreciate the feedback. My crude workaround does the job and I was mostly interested to know if there was a simple win involving systemd dependencies.
– suilven
May 14 at 11:06




Yes I'm trying to delay startup until the session is active and all services required by my backup script are available. It does appear to me that some interaction with the D-Bus is required here. I'm not a Python developer so I'm not going to try and implement your solution but I appreciate the feedback. My crude workaround does the job and I was mostly interested to know if there was a simple win involving systemd dependencies.
– suilven
May 14 at 11:06












up vote
0
down vote













It looks (from the USER=$(whoami) line in your script) that you're running this service as a non-root user (probably by setting User= in your daily-backup.service file.)



You might want to consider setting up the service and timer units as user services, run by the systemd --user manager instead.



To do that, just create daily-backup.service and daily-backup.timer under the ~$USER/.config/systemd/user/ directory. You can essentially use the files you created in the system directory, for the most part unmodified. (You can remove the reference to User= since that will be the user you're setting it up for.)



Use systemctl --user ... commands to enable and start them and to check the status. For the install section, use:



[Install]
WantedBy=default.target


Since the user manager only knows about a default.target (and not e.g. multi-user.target.)



In order to have the user session start at boot, you can enable linger, in which case it will start early and stick around:



loginctl enable-linger $USER


(See documentation for loginctl enable-linger.)



In fact, looking at the Fedora Magazine article you referred to, it seems that's what they had in mind. The "Automate with a timer" part has references to $HOME/.config/systemd/user/.



If you want to read more on systemd user units, the Arch Linux Wiki has a nice article on it.






share|improve this answer





















  • Hmmm, re-reading your question and it seems you already have a user service... So when you're talking about "session" I guess you mean GNOME? Have you considered using systemd-mount instead of gio?
    – Filipe Brandenburger
    May 9 at 5:43






  • 2




    The question did say "systemd user service" in both title and first sentence. And the questioner does talk about the timer triggering, and hence the service being activated, by per-user service management starting up at first login.
    – JdeBP
    May 9 at 7:46











  • @JdeBP yes I realized that on re-reading the question, but I left it around as I was unsure whether the enable-linger would help... Indeed, it seems gnome-vfs-daemon is what is required here for gio to work, but it's unclear to me what starts it...
    – Filipe Brandenburger
    May 9 at 13:10










  • @FilipeBrandenburger I was not aware of systemd-mount so I'll investigate that option. One thing to note is that if I allow Gnome to automount the disk and remove the lines concerned with mounting the disk from the script, the script still fails because the disk is not yet mounted at /run/media/user/disk-label when the backup tries to run. Adding the disk to /etc/fstab is another option but iirc I tried that and the script still failed because the gnome-keyring had not yet initialized and that was required to access the GPG keys to run duplicity.
    – suilven
    May 9 at 23:24











  • @suilven One option you might want to consider is to trigger the backup when the disk is mounted (perhaps in addition to a timer.) This came up recently, see my answer at unix.stackexchange.com/a/441913/281844 for more details (though not completely sure whether doing so in a user unit will work, hmmm...)
    – Filipe Brandenburger
    May 10 at 0:18















up vote
0
down vote













It looks (from the USER=$(whoami) line in your script) that you're running this service as a non-root user (probably by setting User= in your daily-backup.service file.)



You might want to consider setting up the service and timer units as user services, run by the systemd --user manager instead.



To do that, just create daily-backup.service and daily-backup.timer under the ~$USER/.config/systemd/user/ directory. You can essentially use the files you created in the system directory, for the most part unmodified. (You can remove the reference to User= since that will be the user you're setting it up for.)



Use systemctl --user ... commands to enable and start them and to check the status. For the install section, use:



[Install]
WantedBy=default.target


Since the user manager only knows about a default.target (and not e.g. multi-user.target.)



In order to have the user session start at boot, you can enable linger, in which case it will start early and stick around:



loginctl enable-linger $USER


(See documentation for loginctl enable-linger.)



In fact, looking at the Fedora Magazine article you referred to, it seems that's what they had in mind. The "Automate with a timer" part has references to $HOME/.config/systemd/user/.



If you want to read more on systemd user units, the Arch Linux Wiki has a nice article on it.






share|improve this answer





















  • Hmmm, re-reading your question and it seems you already have a user service... So when you're talking about "session" I guess you mean GNOME? Have you considered using systemd-mount instead of gio?
    – Filipe Brandenburger
    May 9 at 5:43






  • 2




    The question did say "systemd user service" in both title and first sentence. And the questioner does talk about the timer triggering, and hence the service being activated, by per-user service management starting up at first login.
    – JdeBP
    May 9 at 7:46











  • @JdeBP yes I realized that on re-reading the question, but I left it around as I was unsure whether the enable-linger would help... Indeed, it seems gnome-vfs-daemon is what is required here for gio to work, but it's unclear to me what starts it...
    – Filipe Brandenburger
    May 9 at 13:10










  • @FilipeBrandenburger I was not aware of systemd-mount so I'll investigate that option. One thing to note is that if I allow Gnome to automount the disk and remove the lines concerned with mounting the disk from the script, the script still fails because the disk is not yet mounted at /run/media/user/disk-label when the backup tries to run. Adding the disk to /etc/fstab is another option but iirc I tried that and the script still failed because the gnome-keyring had not yet initialized and that was required to access the GPG keys to run duplicity.
    – suilven
    May 9 at 23:24











  • @suilven One option you might want to consider is to trigger the backup when the disk is mounted (perhaps in addition to a timer.) This came up recently, see my answer at unix.stackexchange.com/a/441913/281844 for more details (though not completely sure whether doing so in a user unit will work, hmmm...)
    – Filipe Brandenburger
    May 10 at 0:18













up vote
0
down vote










up vote
0
down vote









It looks (from the USER=$(whoami) line in your script) that you're running this service as a non-root user (probably by setting User= in your daily-backup.service file.)



You might want to consider setting up the service and timer units as user services, run by the systemd --user manager instead.



To do that, just create daily-backup.service and daily-backup.timer under the ~$USER/.config/systemd/user/ directory. You can essentially use the files you created in the system directory, for the most part unmodified. (You can remove the reference to User= since that will be the user you're setting it up for.)



Use systemctl --user ... commands to enable and start them and to check the status. For the install section, use:



[Install]
WantedBy=default.target


Since the user manager only knows about a default.target (and not e.g. multi-user.target.)



In order to have the user session start at boot, you can enable linger, in which case it will start early and stick around:



loginctl enable-linger $USER


(See documentation for loginctl enable-linger.)



In fact, looking at the Fedora Magazine article you referred to, it seems that's what they had in mind. The "Automate with a timer" part has references to $HOME/.config/systemd/user/.



If you want to read more on systemd user units, the Arch Linux Wiki has a nice article on it.






share|improve this answer













It looks (from the USER=$(whoami) line in your script) that you're running this service as a non-root user (probably by setting User= in your daily-backup.service file.)



You might want to consider setting up the service and timer units as user services, run by the systemd --user manager instead.



To do that, just create daily-backup.service and daily-backup.timer under the ~$USER/.config/systemd/user/ directory. You can essentially use the files you created in the system directory, for the most part unmodified. (You can remove the reference to User= since that will be the user you're setting it up for.)



Use systemctl --user ... commands to enable and start them and to check the status. For the install section, use:



[Install]
WantedBy=default.target


Since the user manager only knows about a default.target (and not e.g. multi-user.target.)



In order to have the user session start at boot, you can enable linger, in which case it will start early and stick around:



loginctl enable-linger $USER


(See documentation for loginctl enable-linger.)



In fact, looking at the Fedora Magazine article you referred to, it seems that's what they had in mind. The "Automate with a timer" part has references to $HOME/.config/systemd/user/.



If you want to read more on systemd user units, the Arch Linux Wiki has a nice article on it.







share|improve this answer













share|improve this answer



share|improve this answer











answered May 9 at 5:39









Filipe Brandenburger

3,451521




3,451521











  • Hmmm, re-reading your question and it seems you already have a user service... So when you're talking about "session" I guess you mean GNOME? Have you considered using systemd-mount instead of gio?
    – Filipe Brandenburger
    May 9 at 5:43






  • 2




    The question did say "systemd user service" in both title and first sentence. And the questioner does talk about the timer triggering, and hence the service being activated, by per-user service management starting up at first login.
    – JdeBP
    May 9 at 7:46











  • @JdeBP yes I realized that on re-reading the question, but I left it around as I was unsure whether the enable-linger would help... Indeed, it seems gnome-vfs-daemon is what is required here for gio to work, but it's unclear to me what starts it...
    – Filipe Brandenburger
    May 9 at 13:10










  • @FilipeBrandenburger I was not aware of systemd-mount so I'll investigate that option. One thing to note is that if I allow Gnome to automount the disk and remove the lines concerned with mounting the disk from the script, the script still fails because the disk is not yet mounted at /run/media/user/disk-label when the backup tries to run. Adding the disk to /etc/fstab is another option but iirc I tried that and the script still failed because the gnome-keyring had not yet initialized and that was required to access the GPG keys to run duplicity.
    – suilven
    May 9 at 23:24











  • @suilven One option you might want to consider is to trigger the backup when the disk is mounted (perhaps in addition to a timer.) This came up recently, see my answer at unix.stackexchange.com/a/441913/281844 for more details (though not completely sure whether doing so in a user unit will work, hmmm...)
    – Filipe Brandenburger
    May 10 at 0:18

















  • Hmmm, re-reading your question and it seems you already have a user service... So when you're talking about "session" I guess you mean GNOME? Have you considered using systemd-mount instead of gio?
    – Filipe Brandenburger
    May 9 at 5:43






  • 2




    The question did say "systemd user service" in both title and first sentence. And the questioner does talk about the timer triggering, and hence the service being activated, by per-user service management starting up at first login.
    – JdeBP
    May 9 at 7:46











  • @JdeBP yes I realized that on re-reading the question, but I left it around as I was unsure whether the enable-linger would help... Indeed, it seems gnome-vfs-daemon is what is required here for gio to work, but it's unclear to me what starts it...
    – Filipe Brandenburger
    May 9 at 13:10










  • @FilipeBrandenburger I was not aware of systemd-mount so I'll investigate that option. One thing to note is that if I allow Gnome to automount the disk and remove the lines concerned with mounting the disk from the script, the script still fails because the disk is not yet mounted at /run/media/user/disk-label when the backup tries to run. Adding the disk to /etc/fstab is another option but iirc I tried that and the script still failed because the gnome-keyring had not yet initialized and that was required to access the GPG keys to run duplicity.
    – suilven
    May 9 at 23:24











  • @suilven One option you might want to consider is to trigger the backup when the disk is mounted (perhaps in addition to a timer.) This came up recently, see my answer at unix.stackexchange.com/a/441913/281844 for more details (though not completely sure whether doing so in a user unit will work, hmmm...)
    – Filipe Brandenburger
    May 10 at 0:18
















Hmmm, re-reading your question and it seems you already have a user service... So when you're talking about "session" I guess you mean GNOME? Have you considered using systemd-mount instead of gio?
– Filipe Brandenburger
May 9 at 5:43




Hmmm, re-reading your question and it seems you already have a user service... So when you're talking about "session" I guess you mean GNOME? Have you considered using systemd-mount instead of gio?
– Filipe Brandenburger
May 9 at 5:43




2




2




The question did say "systemd user service" in both title and first sentence. And the questioner does talk about the timer triggering, and hence the service being activated, by per-user service management starting up at first login.
– JdeBP
May 9 at 7:46





The question did say "systemd user service" in both title and first sentence. And the questioner does talk about the timer triggering, and hence the service being activated, by per-user service management starting up at first login.
– JdeBP
May 9 at 7:46













@JdeBP yes I realized that on re-reading the question, but I left it around as I was unsure whether the enable-linger would help... Indeed, it seems gnome-vfs-daemon is what is required here for gio to work, but it's unclear to me what starts it...
– Filipe Brandenburger
May 9 at 13:10




@JdeBP yes I realized that on re-reading the question, but I left it around as I was unsure whether the enable-linger would help... Indeed, it seems gnome-vfs-daemon is what is required here for gio to work, but it's unclear to me what starts it...
– Filipe Brandenburger
May 9 at 13:10












@FilipeBrandenburger I was not aware of systemd-mount so I'll investigate that option. One thing to note is that if I allow Gnome to automount the disk and remove the lines concerned with mounting the disk from the script, the script still fails because the disk is not yet mounted at /run/media/user/disk-label when the backup tries to run. Adding the disk to /etc/fstab is another option but iirc I tried that and the script still failed because the gnome-keyring had not yet initialized and that was required to access the GPG keys to run duplicity.
– suilven
May 9 at 23:24





@FilipeBrandenburger I was not aware of systemd-mount so I'll investigate that option. One thing to note is that if I allow Gnome to automount the disk and remove the lines concerned with mounting the disk from the script, the script still fails because the disk is not yet mounted at /run/media/user/disk-label when the backup tries to run. Adding the disk to /etc/fstab is another option but iirc I tried that and the script still failed because the gnome-keyring had not yet initialized and that was required to access the GPG keys to run duplicity.
– suilven
May 9 at 23:24













@suilven One option you might want to consider is to trigger the backup when the disk is mounted (perhaps in addition to a timer.) This came up recently, see my answer at unix.stackexchange.com/a/441913/281844 for more details (though not completely sure whether doing so in a user unit will work, hmmm...)
– Filipe Brandenburger
May 10 at 0:18





@suilven One option you might want to consider is to trigger the backup when the disk is mounted (perhaps in addition to a timer.) This came up recently, see my answer at unix.stackexchange.com/a/441913/281844 for more details (though not completely sure whether doing so in a user unit will work, hmmm...)
– Filipe Brandenburger
May 10 at 0:18













 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f442587%2fhow-to-write-a-systemd-user-service-that-requires-an-active-session%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

How to check contact read email or not when send email to Individual?

Bahrain

Postfix configuration issue with fips on centos 7; mailgun relay