You are not logged in.
I am writing a bootable service in C and D languages.
There is a database of users with thin client settings. I access this database over the network during the download and get from there the data of a specific user linked to the MAC address. The fact is that a user can have two or more monitors connected to a thin client. Data for each monitor is also loaded from the database. Using the xrandr source code, I wrote a program that, knowing the monitor ID, sets the desired monitor in one position or another. The fact is that xrandr uses the global variable DISPLAY, which is unavailable during the loading process.
● myservice-init.service - myservice
Loaded: loaded (/etc/systemd/system/myservice-init.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Thu 2022-05-12 19:15:14 MSK; 55s ago
Process: 1559 ExecStart=/etc/init.d/myservice-init (code=exited, status=1/FAILURE)
Main PID: 1559 (code=exited, status=1/FAILURE)
мая 12 19:15:14 ts_d85ed3156a39 systemd[1]: Starting myservice...
мая 12 19:15:14 ts_d85ed3156a39 thinstation[1562]: Can't open display :0
мая 12 19:15:14 ts_d85ed3156a39 systemd[1]: myservice-init.service: Main process exited, code=exited, status=1/FAILURE
мая 12 19:15:14 ts_d85ed3156a39 systemd[1]: myservice-init.service: Failed with result 'exit-code'.
мая 12 19:15:14 ts_d85ed3156a39 systemd[1]: Failed to start myservice.
Although, looking at the Xorg service - this data is there:
~# cat /etc/X11/xinit/xinitrc.d/50-systemd-user.sh
#!/bin/sh
systemctl --user import-environment DISPLAY XAUTHORITY
if command -v dbus-update-activation-environment >/dev/null 2>&1; then
dbus-update-activation-environment DISPLAY XAUTHORITY
fi
And I start my service after downloading xorg.service. But even adding this code to the launch of my service, I still get errors:
● myservice-init.service - myservice
Loaded: loaded (/etc/systemd/system/myservice-init.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Thu 2022-05-12 19:08:52 MSK; 18s ago
Process: 1560 ExecStart=/etc/init.d/myservice-init (code=exited, status=1/FAILURE)
Main PID: 1560 (code=exited, status=1/FAILURE)
May 12 19:08:52 ts_d85ed3156a39 systemd[1]: Starting myservice...
May 12 19:08:52 ts_d85ed3156a39 thinstation[1564]: dbus-update-activation-environment: error: unable to connect to D-Bus: Unable to autolaun
May 12 19:08:52 ts_d85ed3156a39 thinstation[1570]: Can't open display :0
May 12 19:08:52 ts_d85ed3156a39 systemd[1]: myservice-init.service: Main process exited, code=exited, status=1/FAILURE
May 12 19:08:52 ts_d85ed3156a39 systemd[1]: myservice-init.service: Failed with result 'exit-code'.
May 12 19:08:52 ts_d85ed3156a39 systemd[1]: Failed to start myservice.
And if I just launch my application, then it works out quite correctly:
IFace("enp3s0", "e8:5b:d2:11:6a:39", "192.168.0.15")
[Monitor("VGA-1", true, 1280, 1024)]
Last edited by alexanderzhirov (2022-05-30 05:25:27)
Offline
The display variable is exported as part of the User session which would be set up when the user logs in. And you could configure your service to be ran as an user service instead, see: https://wiki.archlinux.org/title/Systemd/User
Offline
And you could configure your service to be ran as an user service instead, see: https://wiki.archlinux.org/title/Systemd/User
I tried to do it.
Placed the service in /etc/systemd/user/myprogram.service:
[Unit]
Description=myprogram
[Service]
ExecStart=/etc/init.d/myprogram
[Install]
WantedBy=default.target
Autorun file /etc/init.d/myprogram:
#!/bin/sh
myprogram
The result is still the same:
● myprogram.service - myprogram
Loaded: loaded (/etc/systemd/user/myprogram.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Thu 2022-05-12 22:31:30 MSK; 8min ago
Process: 2550 ExecStart=/etc/init.d/myprogram (code=exited, status=1/FAILURE)
Main PID: 2550 (code=exited, status=1/FAILURE)
мая 12 22:31:30 ts_d85ed3156a39 systemd[2546]: Started myprogram.
мая 12 22:31:30 ts_d85ed3156a39 myprogram[2551]: Can't open display :0.0
мая 12 22:31:30 ts_d85ed3156a39 systemd[2546]: myprogram.service: Main process exited, code=exited, status=1/FAILURE
мая 12 22:31:30 ts_d85ed3156a39 systemd[2546]: myprogram.service: Failed with result 'exit-code'.
Maybe I forgot something else?
Offline
How are the clients logging in/starting xorg? The most guaranteed way of this just working is if you/they use a display manager that already has xorg running before doing the log in, if you wanted to do this with startx then your .xinitrc needs to have some code to source the systemd-users.sh (note the blue note) as well as setting up xorg itself as a user service so you have a unit you can order yourself after: https://wiki.archlinux.org/title/System … er_service
Offline
How are the clients logging in/starting xorg?
I made a build based on Thinstation. icewm starts there at startup. As far as I understand, the /etc/xinitrc script is executed before icewm is started:
#!/bin/bash
xinitrcd=/etc/X11/xinit/xinitrc.d
if [ -d $xinitrcd ]; then
for file in `ls -A $xinitrcd`; do
. $xinitrcd/$file
done
fi
# Just run xrandr 1 time to populate some settings in case we don't use a window manager
xrandr
cd /
if [ -n "$1" ]; then
exec $1
elif [ -e $WKDIR/windowapps ] ; then
exec $WKDIR/windowapps
fi
and windowapps:
export DISPLAY_NUMBER=0
exec pkg console icewm "" "" "1" "" "" "" ""
wait
And it runs exactly, because in /etc/X11/xinit/xinitrc.d there is another script of mine that works. And then (in the script above) xrandr is launched, which means there is access to DISPLAY, and my service does not have access to DISPLAY.
Last edited by alexanderzhirov (2022-05-13 06:23:43)
Offline
"Can't open display :0.0" means that the process is aware of the $DISPLAY but cannot access it either because the DISPLAY doesn't exist or the process has insufficient permissions.
It's kinda unclear to me what you're trying to achieve here, but if the display is on a different host thatn the process, you'll have to signal that host as well (host:server.screen) and allow it w/ xauth
If your goal is to just configure the outputs and you're running some xinitrc anyway, just xrandr configure it in that xinitrc.
Offline
try isolating icewm
you have to create a unique direction for each command that the desktop has to receive ..
in practice xinitricrc cannot run more than one instance in some cases.
fi
fi
Some 'security people are f*cking morons' says Linus Torvalds..
Offline
It's kinda unclear to me what you're trying to achieve here
I want to run a systemd service (even a user) that will run in the background throughout the life of the user session while the user is working at the computer. thus, the administrator through the portal will be able to manage this thin client through this service running in the background, which would have access to the user's display.
It could be done like this /etc/X11/xinit/xinitrc.d/myprogram.sh:
#!/bin/sh
myprogram &
But why can't I do it through the systemd user service?
Offline
It can, but you must ensure that
a) you're accessing the *proper* display
b) invoking the proper XAUTHORITY
c) not before the display is available (to that user)
https://man.archlinux.org/man/systemd.s … User_Units isn't covered by https://wiki.archlinux.org/title/System … er_service
And since we're talking about your own code here, you could check what environment actually makes it to the process (to ensure you're invoking it properly) and then keep calling the server until you can access it (if you need to launch it w/ the session and pot. unrelated to any existing X11 server)
Offline
It can, but you must ensure that
a) you're accessing the *proper* display
b) invoking the proper XAUTHORITY
c) not before the display is available (to that user)https://man.archlinux.org/man/systemd.s … User_Units isn't covered by https://wiki.archlinux.org/title/System … er_service
And since we're talking about your own code here, you could check what environment actually makes it to the process (to ensure you're invoking it properly) and then keep calling the server until you can access it (if you need to launch it w/ the session and pot. unrelated to any existing X11 server)
I still don't understand it yet. Is there an example of a similar service that runs the same way? To see which settings are being used.
Offline
Is there an example of a similar service that runs the same way? To see which settings are being used.
I understand I need to do something like this. Only I don't understand what exactly I need to do. Where to start.
Offline
If you want to keep it really simple, just don't enable the service but put `systemctl --user start myprogram.service` in .xinitrc after DISPLAY is imported into the systemd/user instance (by the snippet in xinitrc.d).
Especially if you might use more services that depend on X, it would be cleaner to start a target instead, which gives you a synchronization point/anchor to hook up such services. This could be a custom target, but you should check seth's link for special units. Currently you're using default.target, which starts immediately on login before the xinitrc stuff runs.
Offline
... it would be cleaner to start a target instead, which gives you a synchronization point/anchor to hook up such services. This could be a custom target, but you should check seth's link for special units. Currently you're using default.target, which starts immediately on login before the xinitrc stuff runs.
Could you write a similar example? I don't quite understand how to do this. I understand I need to do something like this. I can't make a file structure for my service yet. Can anyone tell me?
Offline
You create a user target like "xinit-session.target"
[Unit]
Description=User systemd services for xinit session
Wants=xinit.service
BindsTo=graphical-session.target
The "xinit.service" then Exec's xinit/startx, you don't run that command anywhere but "systemctl --isolate graphical-session.target and base your service on "graphical-session.target" instead of "default.target"
If that sounds clumsy and convoluted, that's because it is.
#8 is the far more straigt forward way - especially if you're operating on a homogenuous xinit environment anyway.
Offline
You can make it as clumsy and convoluted as you want, of course. You and V1del seem to push for "all or nothing": if you're gonna have a user service that does something with X, let's go all the way and put xinit/startx in a user service as well. That gives an already struggling OP more to process.
OTOH, OP hasn't really given any reasons for wanting to move myprogram to a user service in the first place,
And AFAICT, Thinstation has very little to do with Arch (note also the parsing of ls output in xinitrc).
Last edited by Raynman (2022-05-19 14:03:34)
Offline
Well, simply starting the service from the xinitrc is pretty much pointless in comparism to just running the designated process from the xinitrc.
And if you're not doing that, you need to establish the graphical-session.target (or any target) and depend the desired service on that target and the scaling approach is the convoluted one (as it will also apply if you eg. start gnome from GDM)
So the middle ground would be to start a random system target (not graphical-session as thats not startable) from the xinitrc?
Which will get you the xinit ties and modification requirement AND the fragility of systemd…
An alternative solution would be to have the user service or the client ping the server until it responds and act only then.
OP hasn't really given any reasons for wanting to move myprogram to a user service in the first place
Possible reasons are to somehow systemd'ify the process for principle reasons or to cope w/ various session starting mechanisms (as DMs won't run xinitrc)
In the latter case, ~/.xprofile would be the straight path - and not cause xrandr calls if the graphical-session.target is invoked by wayland.
Offline
Yeah, I agree with most or all of that. I hadn't checked when I first replied that
(not graphical-session as thats not startable)
(as I hoped to let OP do further research). But then your example in #14 should also start (isolate seems a bit strong) xinit-session.target and isn't something like After=xinit.service missing?
Well, simply starting the service from the xinitrc is pretty much pointless in comparism to just running the designated process from the xinitrc.
Well, at least for
Possible reasons are to somehow systemd'ify the process for principle reasons
it should be enough and then if it's really nothing more than the idea that "systemd is the cool/new way", I would indeed also say "why not just stick with #8?".
Edit: I guess what I don't fully understand is why the strong preference for xinit-session.target started manually/from shell init (or what did you have in mind?) with ExecStart=startx in xinit.service over a similar xinit-session.target started from .xinitrc (or xinitrc.d snippet) without xinit.service and startx run manually/from shell init.
Last edited by Raynman (2022-05-19 16:52:39)
Offline
I don't fully understand is why the strong preference for xinit-session.target started
It'd certainly not be my preferred approach, but if you want to engage w/ the systemd target/service trigger approach the idea behind it is to use an abstract requirement (the graphical-session.target) that can be met by all sorts of things and serves as a barrier for other services. Intermangling this w/ xinitrc is pointless as that provides a different (simpler and imho more robust…) kind of service launching. If you're using the latter anyway, there's no reason to draw in a different system.
isn't something like After=xinit.service missing
This could get even trickier as, however you go about it, starting xinit and even the Xorg process doesn't mean that you can immediately talk to it (you need to wait for the display socket) so you'd have to depend the target on the socket being ready.
(Typically /tmp/.X11-unix/X0)
Setting up X11 from a dedicated X INITialization process is the more direct and less troublesome approach and unless you *have* to acommodate to a system where you can *only* rely on systemd as infrastructure, I don't see where this approach would be worth the effort.
Offline
Here is the hierarchy of my service:
.
├── bin
│ └── myprogram
└── etc
├── init.d
│ └── myprogram
└── systemd
└── user
├── default.target.wants
│ └── myprogram.service -> ../myprogram.service
└── myprogram.service
Where /bin/myprogram is the program itself.
File /etc/init.d/myprogram:
#!/bin/sh
. /etc/thinstation.global
myprogram
where the /etc/thinstation.global file contains global variables.
And the /etc/systemd/user/myprogram.service file looks like this:
[Unit]
Description=myprogram
BindsTo=graphical-session.target
[Service]
ExecStart=/etc/init.d/myprogram
As a result, it turns out that the service starts, but still does not see the screen:
● myprogram.service - myprogram
Loaded: loaded (/etc/systemd/user/myprogram.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Fri 2022-05-20 01:34:18 MSK; 21s ago
Process: 3454 ExecStart=/etc/init.d/myprogram (code=exited, status=1/FAILURE)
Main PID: 3454 (code=exited, status=1/FAILURE)
may 20 01:34:18 ts_080027b3b812 systemd[3451]: Started myprogram.
may 20 01:34:18 ts_080027b3b812 myprogram[3593]: Can't open display :0.0
may 20 01:34:18 ts_080027b3b812 systemd[3451]: myprogram.service: Main process exited, code=exited, status=1/FAILURE
may 20 01:34:18 ts_080027b3b812 systemd[3451]: myprogram.service: Failed with result 'exit-code'.
Here, at the moment when the xrandr call string is being processed in the code, the service crashes because there is no access to the display.
Other information (network interface) collects and logs into a file:
ts_080027b3b812:~# cat /var/log/myprogram.log
IFace("enp0s8", "08:00:27:ff:42:ed", "192.168.56.107")
Information about the screen should also have been recorded in this file. But alas, the service does not see the display.
I start the service manually - everything works, since the display is available:
ts_080027b3b812:~# systemctl --user start myprogram.service
ts_080027b3b812:~# systemctl --user status myprogram.service
● myprogram.service - myprogram
Loaded: loaded (/etc/systemd/user/myprogram.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Fri 2022-05-20 02:04:39 MSK; 28s ago
Process: 4673 ExecStart=/etc/init.d/myprogram (code=exited, status=0/SUCCESS)
Main PID: 4673 (code=exited, status=0/SUCCESS)
may 20 02:04:39 ts_080027b3b812 systemd[3451]: Started myprogram.
may 20 02:04:39 ts_080027b3b812 systemd[3451]: myprogram.service: Succeeded.
ts_080027b3b812:~# cat /var/log/myprogram.log
IFace("enp0s8", "08:00:27:ff:42:ed", "192.168.56.107")
[Monitor("VGA-1", true, 1280, 1024)]
I still don't understand what I'm doing wrong.
Last edited by alexanderzhirov (2022-05-19 23:09:45)
Offline
The service is still being pulled in/started by default.target. First you should remove the link in default.target.wants that's left over from when you enabled the previous version of the service file. Then you need to hook the service up to something else.
The superuser.com answer you linked to earlier links a service to xsession.target. If you imitate that, it should at least give you a working setup. It uses ~/.xsession (sourced by at least LightDM), but you were using .xinitrc, so you can put the starting of xsession.target there and forget the import-environment command.
But do you have a strong reason for wanting to run it as a service or are you just trying it out now, or...?
isn't something like After=xinit.service missing
This could get even trickier as, however you go about it, starting xinit and even the Xorg process doesn't mean that you can immediately talk to it (you need to wait for the display socket) so you'd have to depend the target on the socket being ready.
(Typically /tmp/.X11-unix/X0)
Ah, yes, the wiki has a warning about that with an upstream bug and socket activation being broken and all that. So it's not like "X as a user service" has come a long way since I looked at it years ago. If you mostly gave that incomplete example to scare the OP back to the simple and robust xinit, it might have helped to emphasize that it does nothing for the timing issues.
Then "intermangling this [= {xinit-session,graphical-session}.target] w/ xinitrc" (if you want to engage with that, yes) is also a way to avoid this trickiness, a lower-effort compromise that doesn't seem too crazy to me, even if I don't see a reason to try and use it now. (Another (small?) thing is that the wiki says you can't use the "rootless X" when started as a service.)
Offline
But do you have a strong reason for wanting to run it as a service or are you just trying it out now, or...?
I want to manage the service in case of its failure. It is very convenient to do this via systemd. This is the answer to your question
In the end, what happened at the moment. I configured the service as follows:
.
|-- bin
| `-- myprogram
`-- etc
`-- systemd
`-- user
|-- myprogram.service
`-- xsession.target
myprogram.service:
[Unit]
Description=myprogram
PartOf=graphical-session.target
[Service]
ExecStart=/usr/bin/myprogram
[Install]
WantedBy=graphical-session.target
xsession.target:
[Unit]
Description=X session managed by systemd
BindsTo=graphical-session.target
~/.xinitrc:
(. /etc/thinstation.global; use_idesk &)
systemctl --no-block --user start xsession.target
After downloading the distribution, I check the services.
systemctl --user status xsession.target:
● xsession.target - X session managed by systemd
Loaded: loaded (/etc/systemd/user/xsession.target; static; vendor preset: enabled)
Active: active since Fri 2022-05-20 10:32:11 MSK; 21min ago
may 20 10:32:11 ts_0800273e9027 systemd[2983]: Reached target X session managed by systemd.
systemctl --user status myprogram.service:
● myprogram.service - myprogram
Loaded: loaded (/etc/systemd/user/myprogram.service; disabled; vendor preset: enabled)
Active: inactive (dead)
As you can see, the service does not start automatically. I tried running it with
[Unit]
Description=myprogram
PartOf=graphical-session.target
[Service]
ExecStart=/usr/bin/myprogram
[Install]
WantedBy=xsession.target
but it still wouldn't run. The service is started manually.
Offline
As you can see, the service does not start automatically.
So, I sort of figured it out. In general, I executed the command in a loaded system:
systemctl --user enable myprogram.service
after that, a link to the service was created.
Created symlink /root/.config/systemd/user/graphical-session.target.wants/myprogram.service → /etc/systemd/user/myprogram.service.
Actually, after that, the service began to start automatically!
Did I do everything right?
Offline
Did I do everything right?
/root/.config/systemd/user/graphical-session.target.wants/myprogram.service → /etc/systemd/user/myprogram.service
implies that you're running an X11 (graphical) session as root what is about as wrong as it can get.
Don't.
I want to manage the service in case of its failure. It is very convenient to do this via systemd. This is the answer to your question
I'm not really sure what that means, but if you just want to be able to "systemctl status myprogram.service" the easist way to get there is indeed to "systemctl --user start myprogram.service" instead of "myprogram" from your xinitrc.
Offline
implies that you're running an X11 (graphical) session as root what is about as wrong as it can get.
Don't.
Yes, you are right, in the Thinstation project, some assemblies log in as root, which is why the service being launched is like this.
I'm not really sure what that means, but if you just want to be able to "systemctl status myprogram.service" the easist way to get there is indeed to "systemctl --user start myprogram.service" instead of "myprogram" from your xinitrc.
I redid it without an anchor, now the service is launched as a single service.
Offline
Thank you all so much for your help!
Offline