-
-
Save nickjacob/9909574 to your computer and use it in GitHub Desktop.
[Unit] | |
Description=Demonstrate Bash | |
[Service] | |
ExecStartPre=/usr/bin/bash -c "/usr/bin/systemctl set-environment MYVAR=$(( 2 + 2 ))" | |
ExecStart=/usr/bin/echo "2 + 2 = ${MYVAR}" |
👍 quelled my systemd rage
🎉 Awesome, heroes!
What's the scope of this? I assume just within the units environment and that, environment variables set like this, won't bleed out into other units?
Thinking of using this to assign variables that are output of other commands.
I believe all future units will have this variable in their scope
Can anybody think of an alternative to this that doesn't bleed into other units?
Make my day happiest to have hostname ip in many units that need it to bind on correct interface ! 👍
[Unit]
Description=Set HOSTNAME_IP in global systemd environement
[Service]
ExecStart=/usr/bin/bash -c "/usr/bin/systemctl set-environment HOSTNAME_IP=$(hostname -i)"
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Thx again for this tip !
Note it won't work if user is not root (i.e. if you define "User" in [Service] section). It can be fixed with "PermissionsStartOnly=true", so all commands will be executed as root, and ExecStart command will be run as the defined user as intended.
[Unit]
Description=Demonstrate Bash
[Service]
User=someuser
PermissionsStartOnly=true
ExecStartPre=/usr/bin/bash -c "/usr/bin/systemctl set-environment MYVAR=$(( 2 + 2 ))" #Run as root
ExecStart=/usr/bin/echo "2 + 2 = ${MYVAR}" #Run as "someuser"
ExecStop=#Run as root
[Install]
WantedBy=multi-user.target
Note it won't work if user is not root
I believe you can use PassEnvironment=
in this case.
👍 many thanks
👍
https://www.freedesktop.org/software/systemd/man/systemd.exec.html#EnvironmentFile=
The files listed with this directive will be read shortly before the process is executed (more specifically, after all processes from a previous unit state terminated. This means you can generate these files in one unit state, and read it with this option in the next).
The scope of this variables is at systemd manager, so they are available to all systemd units, you can clean it with ExecStop directive invoking systemctl unset-environment
. Also, you can use templated units, and use the variable %i
to populate a different variable for every different instance thus avoiding variables collision without copypasting unit files.
https://gist.github.com/tzkmx/0ae0d2686ee5da5f245f330e3a6a3329
Must you use ExecStartPre=/usr/bin/bash
or ExecStart=/usr/bin/echo
?
Could you use ExecStartPre=/bin/sh
?
👍
@katcaola Yes. The binary just has to be given with an absolute path.
thx 👍
Thanks! Used it to dynamically set a USB Ethernet dongle to a separate namespace:
https://gist.github.com/PhilipSchmid/55e40dba4e323e9236a1101a7d0d6abb
Note it won't work if user is not root (i.e. if you define "User" in [Service] section). It can be fixed with "PermissionsStartOnly=true", so all commands will be executed as root, and ExecStart command will be run as the defined user as intended.
add --user
to systemctl
and it works.
nice! I have a question why does env variables generated by ExecStartPre can be used by ExecStart?
I prefer to write the variable to a file specific to this unit:
[Service]
EnvironmentFile=-/dev/shm/demo.env
ExecStartPre=/usr/bin/bash -c "echo MYVAR=$(( 2 + 2 )) >/dev/shm/demo.env"
ExecStart=/usr/bin/echo "2 + 2 = ${MYVAR}"
Thanks. I use it to finally make tigervnc work with SDDM:
https://gist.github.com/mjtiempo/8662e88da74236c58115bed5cc78ceaf
Beware that there's a pitfall if you have to use %s
with your command.
echo (date +%s)
SystemD sees this as user shell and resolve to /bin/sh instead. You need to use %%s
to avoid that.
EnvironmentFile=/tmp/timestamp.txt
ExecStartPre=/bin/bash -c "echo TIMESTAMP=$(date +%%s) > /tmp/timestamp.txt;"
Although this seems simple, it was quite hard to find this info. ChatGPT was not yielding a correct result either.
thanks! saved me some good time figuring out the systemctl set-environment directive :)