Read Debian Environment Values Safely with pam_getenv
You will use pam_getenv to read one named value from the system environment configuration, check the result and distinguish a missing variable from a command failure. Allow about ten minutes. You need a Debian or Ubuntu system with the libpam-runtime package installed; the examples only read configuration and do not change a service or account.
The route
Jump straight to the step you need, or tick off Done means at the end.
1. Check the installed command and version
Start by confirming which executable will run. On this machine, pam_getenv is supplied by libpam-runtime version 1.5.3-5ubuntu5.7. The exact output on your host can differ, and the package version matters because this is a small Perl utility whose behaviour can change with the distribution package.
$ command -v pam_getenv
/usr/sbin/pam_getenv
$ dpkg-query -W -f='${Package} ${Version}\n' libpam-runtime
libpam-runtime 1.5.3-5ubuntu5.7
If command -v finds nothing, stop here and install the package through your normal distribution process. Do not copy a script into /usr/sbin as a workaround. Package ownership and future upgrades are part of the 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, so it is a useful 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
Use a quoted name when it comes from another command or a script, even though ordinary shell variable names do not 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 can make troubleshooting less clear 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 when you need to establish what is configured rather than what a shell currently 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"
Do not use printenv PATH as a substitute for this check. printenv reports the current process environment, which can contain shell or service-specific changes. pam_getenv performs 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 reading /etc/environment. Values found later in /etc/environment replace the same variable name, so the two files are not independent namespaces. Treat the installed script and package version as the authority when a host has non-empty pam_env.conf rules.
4. Understand expansion and quoting
The utility attempts to expand environment references in values. In the installed script, references written as ${NAME} are looked up in the process environment, and an unset referenced name becomes an empty string. That is not the same as asking the shell to expand the whole configuration file before pam_getenv runs.
Values in /etc/environment can be quoted. The installed parser removes a matching leading quote and a trailing quote, following the parsing rules used by pam_env. 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. The useful verification 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, is rejected by the installed implementation with Cannot handle PAM items. Do not treat that diagnostic as proof that the referenced PAM item is empty. It means this standalone utility cannot expand that type 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 with status 0. This is the most distracting default: a successful process status does not prove that 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 missing variable produce the same empty output in this simple test. If that distinction matters, inspect the relevant configuration files and define 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 that -l is reserved for default locale information and -s for a system default environment, but also says that neither option currently does anything. They are 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. On this installed version, the output is unchanged. If a later package gives these options meaning, re-read that package's manual before relying on the old behaviour.
7. Diagnose failures and avoid configuration damage
No argument is an actual 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 also a configuration or permissions problem, not evidence that the requested variable is absent. Check file ownership, mode and package integrity with your normal administrator tools. Reading the file can usually be done without elevation; changing it requires elevated privileges and can affect 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 affect graphical logins, remote sessions and services that use 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_getenvis installed fromlibpam-runtime, and its package version is recorded.- A known variable was read and compared with the relevant configuration.
- You know that this installed version also reads
/etc/security/pam_env.conf. - You tested missing-name handling instead of relying on exit status alone.
- You understand that
-land-sare currently no-op compatibility flags. - No configuration, login session or service was changed.