Instantly share code, notes, and snippets.

Embed
What would you like to do?
execute arbitrary bash code/variable substitution in systemd units
[Unit]
Description=Demonstrate Bash
[Service]
ExecStartPre=/usr/bin/bash -c "/usr/bin/systemctl set-environment MYVAR=$(( 2 + 2 ))"
ExecStart=/usr/bin/ech "2 + 2 = ${MYVAR}"
@gbarrancos

This comment has been minimized.

gbarrancos commented Sep 5, 2014

thanks! saved me some good time figuring out the systemctl set-environment directive :)

@mbabineau

This comment has been minimized.

mbabineau commented Feb 3, 2015

👍 quelled my systemd rage

@adinapoli

This comment has been minimized.

adinapoli commented Jul 10, 2015

🎉 Awesome, heroes!

@flungo

This comment has been minimized.

flungo commented Aug 30, 2015

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.

@andrewmichaelsmith

This comment has been minimized.

andrewmichaelsmith commented Nov 18, 2015

I believe all future units will have this variable in their scope

@chrissnell

This comment has been minimized.

chrissnell commented Dec 13, 2015

Can anybody think of an alternative to this that doesn't bleed into other units?

@LordFPL

This comment has been minimized.

LordFPL commented Mar 2, 2016

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 !

@dinacel

This comment has been minimized.

dinacel commented Mar 3, 2016

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
@vaijab

This comment has been minimized.

vaijab commented May 5, 2016

Note it won't work if user is not root

I believe you can use PassEnvironment= in this case.

@DavidXArnold

This comment has been minimized.

DavidXArnold commented Aug 6, 2016

👍 many thanks

@danieldkim

This comment has been minimized.

danieldkim commented Sep 3, 2016

👍

@gdamjan

This comment has been minimized.

gdamjan commented Jul 24, 2017

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).

@tzkmx

This comment has been minimized.

tzkmx commented Oct 18, 2017

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

@katcaola

This comment has been minimized.

katcaola commented Jan 25, 2018

Must you use ExecStartPre=/usr/bin/bash or ExecStart=/usr/bin/echo ?
Could you use ExecStartPre=/bin/sh?

@a0s

This comment has been minimized.

a0s commented Jun 14, 2018

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment