RocketLaunch
RocketLaunch

Reputation: 61

systemd - how to access current user name from system service?

I want to create system service, which (for each user) will be started just after user login and do some job inside user's $HOME with root privelegies.

Here is sample service:

[Unit]
Description= My User service
After=dbus.service

[Service]
StandardError=journal
ExecStart=/bin/sh -c "cp -r $HOME/.config /root/backup/$USER/$(date)/"  #<- just a sample root task

[Install]
WantedBy=default.target

But $HOME or $USER variables are unavailable. How to access them?

Upvotes: 6

Views: 6160

Answers (2)

Askeli
Askeli

Reputation: 191

To the best of my knowledge, there is no way to access actual user environment variables from a 'system' unit the way you're envisioning.

The approach I would probably use for the example you gave is to have a 'system' path unit that starts at boot and watches for a .needsbackup file in each user's home dir, extracts the username from the path, and in turn triggers your 'system' backup service unit — probably using a template unit so each run of the backup service would get its own instance, eg backup@<user>.service. This makes it easy to pass the username to your backup command, and allows you to see from a glance at your list of running units what user(s) have a backup job running at any given moment. Delete the .needsbackup file before starting the backup command for obvious reasons, and if you want the backup to run every time the user logs in, you can add touch ~/.needsbackup to their .profile (or /etc/profile to make it apply to all users).

I believe there is a more technically correct, elegant way to detect user login directly by having your system service unit hook into the logind D-BUS API, but I can't offer any help there, as I'm really not familiar with those components.

Also note that your question asks about a 'system' service, but your example service file is a 'user' service file. In particular, default.target is only useful in user units. For your 'system' unit, you probably want either multi-user.target or graphical.target.

Upvotes: 1

smac89
smac89

Reputation: 43186

You can use unit specifiers to accomplish this:

%h represents the home folder of the user

%u gets the name of the user

[Unit]
Description= My User service
After=dbus.service

[Service]
StandardError=journal
ExecStart=/bin/sh -c "cp -r %h/.config /root/backup/%u/$(date)/"  #<- just a sample root task

[Install]
WantedBy=default.target

Upvotes: 6

Related Questions