Reputation: 306
I was writing a systemd
service named 'spliti3.service' which executes a Python script in /usr/bin/
to help automatically adjust windows within 2 columns vertically for my i3wm.
In my /etc/systemd/system/spliti3.service
:
[Unit]
Description=Launches screen with my config
After=network.target
[Service]
Type=simple
User=raz0229
ExecStart=/usr/bin/spliti3
RemainAfterExit=true
StandardOutput=append:$HOME/log0.log
StandardError=append:$HOME/log1.log
[Install]
WantedBy=multi-user.target
Here's part of my Python code that is causing problems.
In /usr/bin/spliti3
:
#!/usr/bin/python3
from i3ipc import Connection, Event
import os
.
.
.
sock_path = os.environ.get('I3SOCK') # Returns NoneType
c = Connection(sock_path)
Seems like the only way to get sock_path
is either through the $I3SOCK
or i3 --get-socket-path
command and can't be hard coded in the script.
Also, the script works just fine when executed on my machine but gives error on os.environ.get('I3SOCK')
when registered as a service through systemctl
.
In the log file, it suggests that sock_path
is None which is odd.
I know there is something wrong with my spliti3.service
but not sure what's causing it.
Upvotes: 0
Views: 1390
Reputation: 180286
Cant access environment variable [...] for systemd service
[...]
the script works just fine when executed on my machine but gives error on
os.environ.get('I3SOCK')
when registered as a service throughsystemctl
. In the log file, it suggests thatsock_path
is None which is odd.
It's not the least bit odd. You seem to be assuming that systemd will run the service in a login shell of the execution user, or at least one with an environment configured like a login shell's. This is not the case.
It is standard for service management frameworks such as systemd to run services in minimal environments. This serves security and stability objectives. Systemd provides more of an environment than some other frameworks do, but even so, it does not process the execution user's shell configuration files. I don't expect that it even launches the script via a shell in the first place. The environment variables you can rely upon by default are documented in the systemd manual.
Systemd does provide means by which your service file could specify additional environment variables to define for the processes it manages (see docs). However, the only reason I can imagine that you could not hardcode the wanted value into your script is that it has to be determined dynamically at runtime. That would make it challenging to get systemd to set the appropriate value.
Seems like the only way to get sock_path is either through the
$I3SOCK
ori3 --get-socket-path
command.
If the script can get it from an environment variable then in principle, the script could also get it via a command-line argument, read it from a file, obtain it from a web service, or get it many other ways.
In particular, if the command i3 --get-socket-path
indeed provides the wanted information, then I don't see why you wouldn't have the script run that command and capture the output (at least, I assume that it's the program output that conveys the information). If you like, you could make it do that only as a fallback, in the event that the $I3SOCK
environment variable is not set.
As a separate matter, it is unclear why you configure the service to execute as (it appears) your login user. That's not inherently wrong, and it may even be exactly what you want, but if so then you would probably be better off setting it up as a user unit instead of a system-wide unit.
Upvotes: 1