You are not logged in.

#1 2015-09-04 23:07:17

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,734
Website

Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

How can I have query systemd to see if a user service is running in a post_install script (which pacman will run as root)?  This is straightforward for system services:

systemctl is-enabled foo.service

But for user services, how can I query all user services that are running and the see if foo.service is running for any and all users?

Last edited by graysky (2015-09-06 11:59:54)

Offline

#2 2015-09-04 23:25:45

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,543
Website

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

Why would you want to do this?  You could do some variation of `find /home/*/.config/systemd ...` instead, but I can't imagine a case in which any such query would be a good idea.


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#3 2015-09-04 23:27:42

WorMzy
Administrator
From: Scotland
Registered: 2010-06-16
Posts: 13,718
Website

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

I would recommend that you leave user services alone. I would also recommend that you leave system services alone.

If a user/system service should be reloaded/restarted post-upgrade, you should alert the user in a postinstall message. It is the end-user's responsibility to restart these services, not the package's.


Sakura:-
Mobo: MSI MAG X570S TORPEDO MAX // Processor: AMD Ryzen 9 5950X @4.9GHz // GFX: AMD Radeon RX 5700 XT // RAM: 32GB (4x 8GB) Corsair DDR4 (@ 3000MHz) // Storage: 1x 3TB HDD, 6x 1TB SSD, 2x 120GB SSD, 1x 275GB M2 SSD

Making lemonade from lemons since 2015.

Offline

#4 2015-09-04 23:30:12

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,734
Website

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

Well, if the service needs to be stopped before pacman removes executable, a message to the user would be too late.

Offline

#5 2015-09-04 23:55:17

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,543
Website

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

Trilby wrote:

Why would you want to do this?

Is the executable target being renamed?  Would the executable already be running, or is is run periodically on a timer?  Give us a hint here.

If the executable target is being renamed, perhaps you could use a symlink for a transitional version for a while where the old executable name would link to the new executable.  But this might also be nonsense as you haven't clarified what actually needs to change.


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#6 2015-09-05 07:28:35

mauritiusdadd
Member
From: Benevento, Italy
Registered: 2013-10-27
Posts: 776

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

graysky wrote:

Well, if the service needs to be stopped before pacman removes executable, a message to the user would be too late.

This sounds like an X-Y problem: as Trilby already asked, why the service needs to be stopped? If something changes in the service file, usually executing systemctl --user daemon-reload should be enough. Maybe It's because you need ExecStop to be run before the installation? However...

graysky wrote:

How can I have query systemd to see if a user service is running in a post_install script (which pacman will run as root)?

since you need to stop the service before pacman removes the executable (that means the package is already installed), you could put this in the pre_upgrade() function:

# NOTE: you can use systemctl --user only if the user is logged in
#            that's why we use $(users) here

for x in $(users); do
  enabled="$(su $x -c 'systemctl --user is-enabled gpg-agent')"
  if [[ "$enabled" == "enabled" ]]; then
    # do somthing here, for example
    # su $x -c 'systemctl --user stop foo.service'
  fi
done

but this approach has several drawbacks:

  1. It's ugly

  2. There is no easy way to keep track of which user had the service running, so you can't restart the service just for them in post_upgrade() and you will have to alert the user in a postinstall message anyway (maybe you can save a list of users in a tempfile, but it's even more ugly)

  3. Users don't expect their services to be started/stopped by others, especially by pacman

--edit: typo

Last edited by mauritiusdadd (2015-09-05 07:29:18)


About me - github

-- When you have eliminated the impossible, whatever remains, however improbable, must be the truth -- Spock | Sherlock Holmes

Offline

#7 2015-09-05 10:10:50

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,734
Website

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

Trilby wrote:

Is the executable target being renamed?  Would the executable already be running, or is is run periodically on a timer?  Give us a hint here.

I am only talking about if the user wants to remove the package.  In this case, the executable would be getting removed by pacman.  So in this case, it needs to be called to run a clean-up function before it is removed from the system.

mauritiusdadd wrote:
# NOTE: you can use systemctl --user only if the user is logged in
#            that's why we use $(users) here

for x in $(users); do
  enabled="$(su $x -c 'systemctl --user is-enabled gpg-agent')"
  if [[ "$enabled" == "enabled" ]]; then
    # do somthing here, for example
    # su $x -c 'systemctl --user stop foo.service'
  fi
done

I came up with a similar code snippet.  Just to clarify, I don't think using it in the pre_upgrade is right, just in the pre_remove since this would only need to be called if the package were to be removed.

mauritiusdadd wrote:

but this approach has several drawbacks:

  1. It's ugly

  2. There is no easy way to keep track of which user had the service running, so you can't restart the service just for them in post_upgrade() and you will have to alert the user in a postinstall message anyway (maybe you can save a list of users in a tempfile, but it's even more ugly)

  3. Users don't expect their services to be started/stopped by others, especially by pacman

point #1) Yes.
point #2) I don't know how to figure out which users on the system could be running it, i.e. how to define the contents of $(users) in your code in a general fashion such that the scriptlet could auto populate it based on any generic system.
point #3) Yes, I agree with this as well but again, cannot think of an alternative.

EDIT: Maybe the following would work to populate $(user):

users=$(getent passwd | grep home | awk -F: '{print $1}' | awk 1 ORS=' ')

Last edited by graysky (2015-09-05 10:36:23)

Offline

#8 2015-09-05 10:39:52

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,734
Website

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

@mauritiusdadd - Nope, the script fails when executed by root:

% cat test 
#!/bin/sh
users=$(getent passwd | grep home | awk -F: '{print $1}' | awk 1 ORS=' ')
echo $user
for i in $users; do
 running="$(su $x -c 'systemctl --user is-active psd')"
 if [[ "$running" = "active" ]]; then
  echo $i is running it
 fi
done

% sudo su
# ./test
Failed to get D-Bus connection: No such file or directory
Failed to get D-Bus connection: No such file or directory

Last edited by graysky (2015-09-05 10:51:17)

Offline

#9 2015-09-05 11:00:35

mauritiusdadd
Member
From: Benevento, Italy
Registered: 2013-10-27
Posts: 776

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

graysky wrote:

@mauritiusdadd - Nope, the script fails when executed by root:

users=$(getent passwd | grep home | awk -F: '{print $1}' | awk 1 ORS=' ')

It's because in your code ${users} is a variable containing also users which has not logged in. In the code I posted, the for loop was based on the output of the program users (note the round brackets) which shows only the name of the users already logged in. You can ignore users not logged in because their user services are not running,


About me - github

-- When you have eliminated the impossible, whatever remains, however improbable, must be the truth -- Spock | Sherlock Holmes

Offline

#10 2015-09-05 11:03:30

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,734
Website

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

mauritiusdadd wrote:

It's because in your code ${users} is a variable containing also users which has not logged in. In the code I posted, the for loop was based on the output of the program users (note the round brackets) which shows only the name of the users already logged in. You can ignore users not logged in because their user services are not running,

Ah!  Didn't know about /usr/bin/users which is more simplistic.  But substituting it still yields the same dbus connection errors when run as root hmm

Offline

#11 2015-09-05 11:12:35

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,543
Website

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

graysky wrote:

I am only talking about if the user wants to remove the package.  In this case, the executable would be getting removed by pacman.  So in this case, it needs to be called to run a clean-up function before it is removed from the system.

Why?  What needs to be cleaned up?  No other package "cleans up" files in a user's home directory when its package is removed.  What is unique about your case such that this would be called for.


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#12 2015-09-05 11:27:18

mauritiusdadd
Member
From: Benevento, Italy
Registered: 2013-10-27
Posts: 776

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

graysky wrote:

Ah!  Didn't know about /usr/bin/users which is more simplistic.  But substituting it still yields the same dbus connection errors when run as root hmm

It seems that you use $i as variable for the for loop, but you are passing $x (which is empty) to su

for i in $users; do
 running="$(su $x -c 'systemctl --user is-active psd')"

Last edited by mauritiusdadd (2015-09-05 11:27:51)


About me - github

-- When you have eliminated the impossible, whatever remains, however improbable, must be the truth -- Spock | Sherlock Holmes

Offline

#13 2015-09-05 11:37:00

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,734
Website

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

Trilby wrote:
graysky wrote:

I am only talking about if the user wants to remove the package.  In this case, the executable would be getting removed by pacman.  So in this case, it needs to be called to run a clean-up function before it is removed from the system.

Why?  What needs to be cleaned up?  No other package "cleans up" files in a user's home directory when its package is removed.  What is unique about your case such that this would be called for.

https://aur.archlinux.org/packages/profile-sync-daemon

Symlinks a directory to tmpfs.  If removed before the unsync, it will leave a broken symlink on the filesystem and a renamed profile.

Offline

#14 2015-09-05 11:53:07

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,734
Website

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

@mar - that was a typo.  If you run the code on your system as root do you get the same dubs errors?

Offline

#15 2015-09-05 12:15:33

mauritiusdadd
Member
From: Benevento, Italy
Registered: 2013-10-27
Posts: 776

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

It works fine on both my desktop and my laptop: I tested it by adding a coulpe of users and then I tested it also in a clean chroot... what happens if you run the following code? Is there a user with a broken dbus session?

#!/bin/sh
for i in $(users); do
 echo "---[$i]---"
 su $i -c 'env | grep DBUS'
 running="$(su $i -c 'systemctl --user is-active psd')"
 if [[ "$running" = "active" ]]; then
  echo $i is running it
 else
  echo $i is not running it
 fi
done

on my machine it outputs

---[daddona]---
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-GBmTt3wzt0,guid=9ef2acf2b3c851fcfc97382155ead6c7
daddona is not running it
---[user1]---
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-GBmTt3wzt0,guid=9ef2acf2b3c851fcfc97382155ead6c7
user1 is not running it
---[user2]---
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-GBmTt3wzt0,guid=9ef2acf2b3c851fcfc97382155ead6c7
user2 is not running it
---[user3]---
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-GBmTt3wzt0,guid=9ef2acf2b3c851fcfc97382155ead6c7
user3 is not running it

--edit: typo

Last edited by mauritiusdadd (2015-09-05 14:17:17)


About me - github

-- When you have eliminated the impossible, whatever remains, however improbable, must be the truth -- Spock | Sherlock Holmes

Offline

#16 2015-09-05 18:55:17

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,734
Website

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

Didn't work for me either in a clean chroot or out.

% sudo ./test
---[facade]---
Failed to get D-Bus connection: No such file or directory
facade is not running it
---[facade]---
Failed to get D-Bus connection: No such file or directory
facade is not running it

EDIT: I also tried running it on 2 other machines and was met with the same results hmm

Last edited by graysky (2015-09-05 19:24:39)

Offline

#17 2015-09-06 08:15:16

mauritiusdadd
Member
From: Benevento, Italy
Registered: 2013-10-27
Posts: 776

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

Ok, I was running the script using su but using sudo I was able to reproduce the problem: it seems that systemctl --user needs to access the user's $XDG_RUNTIME_DIR. The problem is that this environment variable is set by systemd-logind at login trough the module pam_systemd, but this module is not loaded when using su or sudo, so $XDG_RUNTIME_DIR is not available in the environment of the target user. Therefore, the only option left is to set the variable in the script: according to the pam_systemd documentation, the default value for the runtime directory is /run/user/$USER so this should work

#!/bin/sh
for i in $(users); do
  echo "---[$i]---"
  running="$(su $i -c 'XDG_RUNTIME_DIR=/run/user/$UID systemctl --user is-active psd')"
  if [[ "$running" = "active" ]]; then
    echo $i is running it
  else
    echo $i is not running it
  fi
done

It will however fail if a user have set a different runtime directory (is this even possible using systemd-logind?) other than the default one hmm

Last edited by mauritiusdadd (2015-09-06 08:16:22)


About me - github

-- When you have eliminated the impossible, whatever remains, however improbable, must be the truth -- Spock | Sherlock Holmes

Offline

#18 2015-09-06 11:59:17

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,734
Website

Re: Query systemd --user mode in a pre_remove for PKGBUILD [SOLVED]

Nice!  Thank you!  Defining the XDG_RUNTIME_DIR was the key.

pre_remove() {
 for i in $(users); do
  running="$(su $i -c 'XDG_RUNTIME_DIR=/run/user/$UID systemctl --user is-active psd')"
   if [[ "$running" = "active" ]]; then
    echo "--> In order to preserve your profiles, pacman will now stop your psd service."
    echo "--> Any running and managed browsers will be exited."
    su $i -c 'XDG_RUNTIME_DIR=/run/user/$UID systemctl --user stop psd.service'
   fi
  done
}

Last edited by graysky (2015-09-06 12:27:26)

Offline

Board footer

Powered by FluxBB