'\" t
.TH "SYSTEMD\&.ENVIRONMENT\-GENERATOR" "7" "" "systemd 255" "systemd.environment-generator"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\" http://bugs.debian.org/507673
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
systemd.environment-generator \- systemd environment file generators
.SH "SYNOPSIS"
.HP \w'\fB/usr/lib/systemd/system\-environment\-generators/some\-generator\fR\ 'u
\fB/usr/lib/systemd/system\-environment\-generators/some\-generator\fR
.HP \w'\fB/usr/lib/systemd/user\-environment\-generators/some\-generator\fR\ 'u
\fB/usr/lib/systemd/user\-environment\-generators/some\-generator\fR
.PP
.nf
/run/systemd/system\-environment\-generators/*
/etc/systemd/system\-environment\-generators/*
/usr/local/lib/systemd/system\-environment\-generators/*
/usr/lib/systemd/system\-environment\-generators/*
.fi
.PP
.nf
/run/systemd/user\-environment\-generators/*
/etc/systemd/user\-environment\-generators/*
/usr/local/lib/systemd/user\-environment\-generators/*
/usr/lib/systemd/user\-environment\-generators/*
.fi
.sp
.SH "DESCRIPTION"
.PP
Generators are small executables that live in
/usr/lib/systemd/system\-environment\-generators/
and other directories listed above\&.
\fBsystemd\fR(1)
will execute those binaries very early at the startup of each manager and at configuration reload time, before running the generators described in
\fBsystemd.generator\fR(7)
and before starting any units\&. Environment generators can override the environment that the manager exports to services and other processes\&.
.PP
Generators are loaded from a set of paths determined during compilation, as listed above\&. System and user environment generators are loaded from directories with names ending in
system\-environment\-generators/
and
user\-environment\-generators/, respectively\&. Generators found in directories listed earlier override the ones with the same name in directories lower in the list\&. A symlink to
/dev/null
or an empty file can be used to mask a generator, thereby preventing it from running\&. Please note that the order of the two directories with the highest priority is reversed with respect to the unit load path, and generators in
/run/
overwrite those in
/etc/\&.
.PP
After installing new generators or updating the configuration,
\fBsystemctl daemon\-reload\fR
may be executed\&. This will re\-run all generators, updating environment configuration\&. It will be used for any services that are started subsequently\&.
.PP
Environment file generators are executed similarly to unit file generators described in
\fBsystemd.generator\fR(7), with the following differences:
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
Generators are executed sequentially in the alphanumerical order of the final component of their name\&. The output of each generator output is immediately parsed and used to update the environment for generators that run after that\&. Thus, later generators can use and/or modify the output of earlier generators\&.
.RE
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
Generators are run by every manager instance, their output can be different for each user\&.
.RE
.PP
It is recommended to use numerical prefixes for generator names to simplify ordering\&.
.SH "EXAMPLES"
.PP
\fBExample\ \&1.\ \&A simple generator that extends an environment variable if a directory exists in the file system\fR
.sp
.if n \{\
.RS 4
.\}
.nf
# 50\-xdg\-data\-dirs\&.sh

#!/bin/sh
# SPDX\-License\-Identifier: MIT\-0

# set the default value
XDG_DATA_DIRS="${XDG_DATA_DIRS:\-/usr/local/share/:/usr/share}"

# add a directory if it exists
if [ \-d /opt/foo/share ]; then
    XDG_DATA_DIRS="/opt/foo/share:${XDG_DATA_DIRS}"
fi

# write our output
echo "XDG_DATA_DIRS=${XDG_DATA_DIRS}"
.fi
.if n \{\
.RE
.\}
.PP
\fBExample\ \&2.\ \&A more complicated generator which reads existing configuration and mutates one variable\fR
.sp
.if n \{\
.RS 4
.\}
.nf
# 90\-rearrange\-path\&.py

#!/usr/bin/env python3
# SPDX\-License\-Identifier: MIT\-0

"""

Proof\-of\-concept systemd environment generator that makes sure that bin dirs
are always after matching sbin dirs in the path\&.
(Changes /sbin:/bin:/foo/bar to /bin:/sbin:/foo/bar\&.)

This generator shows how to override the configuration possibly created by
earlier generators\&. It would be easier to write in bash, but let\*(Aqs have it
in Python just to prove that we can, and to serve as a template for more
interesting generators\&.

"""

import os
import pathlib

def rearrange_bin_sbin(path):
    """Make sure any pair of \&.../bin, \&.../sbin directories is in this order

    >>> rearrange_bin_sbin(\*(Aq/bin:/sbin:/usr/sbin:/usr/bin\*(Aq)
    \*(Aq/bin:/sbin:/usr/bin:/usr/sbin\*(Aq
    """
    items = [pathlib\&.Path(p) for p in path\&.split(\*(Aq:\*(Aq)]
    for i in range(len(items)):
        if \*(Aqsbin\*(Aq in items[i]\&.parts:
            ind = items[i]\&.parts\&.index(\*(Aqsbin\*(Aq)
            bin = pathlib\&.Path(*items[i]\&.parts[:ind], \*(Aqbin\*(Aq, *items[i]\&.parts[ind+1:])
            if bin in items[i+1:]:
                j = i + 1 + items[i+1:]\&.index(bin)
                items[i], items[j] = items[j], items[i]
    return \*(Aq:\*(Aq\&.join(p\&.as_posix() for p in items)

if __name__ == \*(Aq__main__\*(Aq:
    path = os\&.environ[\*(AqPATH\*(Aq] # This should be always set\&.
                              # If it\*(Aqs not, we\*(Aqll just crash, which is OK too\&.
    new = rearrange_bin_sbin(path)
    if new != path:
        print(\*(AqPATH={}\*(Aq\&.format(new))
.fi
.if n \{\
.RE
.\}
.PP
\fBExample\ \&3.\ \&Debugging a generator\fR
.sp
.if n \{\
.RS 4
.\}
.nf
SYSTEMD_LOG_LEVEL=debug VAR_A=something VAR_B="something else" \e
/usr/lib/systemd/system\-environment\-generators/path\-to\-generator
.fi
.if n \{\
.RE
.\}
.SH "SEE ALSO"
.PP
\fBsystemd-environment-d-generator\fR(8),
\fBsystemd.generator\fR(7),
\fBsystemd\fR(1),
\fBsystemctl\fR(1)