Home / Alt manpages / pam_getenv(8)

  • pam_getenv(8)
  • Admin command
  • linux

Read Debian Environment Values Safely with pam_getenv

pam_getenv reads one named value out of the system environment configuration and tells you, cleanly, whether it found something or not. Allow about ten minutes. You need a Debian or Ubuntu system with libpam-runtime installed; the examples only read configuration and never touch a service or account.

1. Check the installed command and version

Start by confirming which executable will actually run. On this machine, pam_getenv is supplied by libpam-runtime version 1.5.3-5ubuntu5.7. Your host's output can differ, and the package version matters here, this is a small Perl utility whose behaviour can shift between distribution packages.

$ command -v pam_getenv
/usr/sbin/pam_getenv
$ dpkg-query -W -f='${Package} ${Version}\n' libpam-runtime
libpam-runtime 1.5.3-5ubuntu5.7

Warning

If command -v finds nothing, stop here and install the package through your normal distribution process. Do not paper over it with a script dropped into /usr/sbin, package ownership and future upgrades are part of this command's safety boundary.

Checkpoint

You have a package-managed pam_getenv, and you know which version you are testing.

2. Read a known variable

The required argument is the environment variable name, not a shell assignment and not a path. The command prints the value followed by a newline. On this host, PATH is defined in /etc/environment, which makes it a handy read-only test:

$ pam_getenv PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

Quote the name when it comes from another command or script, even though ordinary shell variable names never contain spaces:

$ ENV_NAME='PATH'
$ pam_getenv "$ENV_NAME"
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

Reading the value is normally unprivileged. sudo is not needed for the installed files on a standard system, and using it anyway just muddies troubleshooting by changing the execution context.

3. Compare the result with the source file

The manual describes the command as reading /etc/environment. Inspect that file directly when you need to know what is configured, rather than what a shell happens to have inherited:

$ sed -n '/^[[:space:]]*#/!{/^[[:space:]]*$/!p;}' /etc/environment
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"

Warning

Do not use printenv PATH as a substitute for this check. printenv reports the current process environment, which can carry shell or service-specific changes, while pam_getenv does its own lookup from the PAM environment configuration files.

The installed 1.5.3-5ubuntu5.7 script also reads /etc/security/pam_env.conf before it reads /etc/environment. A value found later in /etc/environment overrides the same name from pam_env.conf, so the two files are not independent namespaces. Treat the installed script and package version as the authority whenever a host has non-empty pam_env.conf rules.

4. Understand expansion and quoting

The utility tries to expand environment references inside values. In the installed script, a reference written as ${NAME} is looked up in the process environment, and an unset name referenced this way just becomes an empty string. That is not the same thing as the shell expanding the whole configuration file before pam_getenv even runs.

Values in /etc/environment can be quoted. The installed parser strips a matching leading and trailing quote, following the parsing rules pam_env itself uses. Keep the configuration syntax simple, and verify the final value with the command:

$ pam_getenv LANG
en_GB.UTF-8
$ printf 'value length: %s\n' "$(pam_getenv LANG | wc -c)"
value length: 12

The exact locale value is host-specific. What matters is that the returned value is the one you expect, not that it matches this example.

A value containing a PAM item reference, such as an unescaped @{PAM_USER} form, gets rejected outright by the installed implementation with Cannot handle PAM items. Do not read that as proof the referenced PAM item is empty, it just means this standalone utility cannot expand that kind of reference.

5. Check missing names without changing anything

Ask for a deliberately unlikely name to see how this version behaves when a variable is absent:

$ pam_getenv PAM_GETENV_NAME_THAT_IS_NOT_SET
$ printf 'exit status: %s\n' "$?"
exit status: 0

There is no output, but the installed script still exits 0. That is the single most distracting default here: a clean exit status does not prove a value was found. In a script, capture the output and test whether it is non-empty, if an empty value is not valid for your use case:

$ value=$(pam_getenv PAM_GETENV_NAME_THAT_IS_NOT_SET)
$ if [ -n "$value" ]; then printf '%s\n' "$value"; else printf '%s\n' 'no value returned'; fi
no value returned

An empty configured value and a genuinely missing variable produce the same empty output in this test. If that distinction matters to you, inspect the relevant configuration files directly and settle a policy for empty values before automating around the command.

6. Treat the compatibility flags correctly

The synopsis accepts -l and -s. The manual says -l is reserved for default locale information and -s for a system default environment, but also says plainly that neither option currently does anything. They exist as compatibility flags for a possible future Debian split of the configuration sources.

$ pam_getenv -l PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
$ pam_getenv -s PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

Do not add either flag expecting locale selection, service isolation or a different file to be read. On this installed version the output is identical either way. If a later package version gives these options real meaning, re-read that package's manual before relying on the old behaviour.

7. Diagnose failures and avoid configuration damage

No argument at all is a plain usage error:

$ pam_getenv
Usage: pam_getenv [-l] [-s] env_var
$ printf 'exit status: %s\n' "$?"
exit status: 255

A failure to open /etc/security/pam_env.conf is a configuration or permissions problem too, not evidence the requested variable is absent. Check file ownership, mode and package integrity with your normal admin tools. Reading the file usually needs no elevation; changing it does, and can affect live login sessions.

Warning

Do not edit /etc/environment or /etc/security/pam_env.conf just to make a test value appear. A malformed environment file can break graphical logins, remote sessions and any service that uses PAM. If a change is genuinely required, save a root-owned backup first, make the smallest documented edit during a maintenance window, then start a fresh session and verify with pam_getenv. To undo it, restore the backup or remove only the line you added, then repeat the fresh-session check.

Done means

  • pam_getenv is installed from libpam-runtime, and you recorded its package version.
  • You read a known variable and compared it against the relevant configuration file.
  • You know this installed version also reads /etc/security/pam_env.conf.
  • You tested missing-name handling instead of trusting exit status alone.
  • You understand -l and -s are currently no-op compatibility flags.
  • No configuration, login session or service was changed.