Management

Managing Environment Variables with the env Command

Learn how Unix and Linux environment variables work and how to inspect, set, unset, and isolate them with the env command.

The env command lets you inspect the environment visible to a process and start a command with temporary, modified, or empty environment variables. It is useful for debugging, reproducible tests, scripts, locale control, and safer command execution.

What is a process environment?

An environment variable is a name-and-value setting associated with a process. Examples include PATH=/usr/bin:/bin and LANG=en_US.UTF-8. Programs read these values to decide where to find executables, which home directory to use, how to format text, and how to select application behavior.

When a process starts a child process, the child normally receives a copy of the parent's process environment. This is called inheritance. The child can change its own copy, but those changes do not modify the environment of its parent.

Shell variables and exported variables

A shell can hold ordinary shell variables that are known only to that shell. A variable becomes an environment variable for child processes when the shell exports it.

CharacteristicShell variableExported environment variable
Visible in the current shellYesYes
Passed to commands started by the shellNoYes
Typical assignmentNAME=valueexport NAME=value
Removal from the shellunset NAMEunset NAME
NAME=local-value
export NAME

# NAME is now inherited by subsequently launched commands

Exporting a variable changes the current shell's future child environments. It still does not make the setting system-wide. Shell startup files, service managers, login configuration, and operating-system-specific settings are separate mechanisms.

What the env command does

With no command argument, env writes the environment entries it can see to standard output:

env

With a command, env prepares an environment and then invokes that command:

env NAME=value command

The launched program receives the altered environment. When that program exits, the shell's environment remains unchanged.

Common env options

OptionMeaningTypical usePortability notes
-i, --ignore-environmentStart with an empty environment before applying assignmentsClean tests and minimal execution contexts-i is widely available; long-option support is commonly associated with GNU implementations
-u NAME, --unset=NAMERemove a variable from the environment passed to the commandDisable proxies or unwanted application settingsOption spelling and repeated-use behavior can vary; check the local manual
-S STRING, --split-string STRINGSplit a string into argumentsPass multiple interpreter arguments in a shebangNot part of the basic POSIX interface and not available on every system

Viewing environment variables

Use env without arguments to list all inherited entries. Ordering is not guaranteed, so sorting can make output easier to compare:

env | sort

A pipe sends the standard output of one command to the standard input of another. For example, grep can select one entry:

env | grep '^PATH='
env | grep '^LANG='
env | grep '^LC_'

The caret in ^PATH= anchors the match to the beginning of the line, avoiding accidental matches in other values.

VariablePurposeExample effectCaution
PATHColon-separated directories searched for commandsls may be found in /usr/binAn unsafe or empty value can select the wrong program or prevent lookup
HOMEUser's home directoryApplications find personal configuration filesA wrong value can make programs read or write the wrong files
USERCommonly identifies the account nameA program displays a user-specific greetingIt is input, not a security proof of identity
SHELLCommonly identifies the user's preferred shellA tool chooses a default interactive shellIt may not describe the shell currently executing a script
LANGDefault localeMessages and formatting use a language and character setLocale-dependent output can be unsuitable for parsers
TERMTerminal capability descriptionFull-screen programs select terminal control sequencesIt can be absent in non-interactive processes
PWDShell's recorded working directoryA prompt or program displays the current directoryUse a system call or pwd when authoritative filesystem state matters

printenv is a related utility focused on displaying environment variables:

printenv
printenv PATH

Shell built-ins have different purposes. export displays or marks exported shell variables, while set commonly displays shell variables, functions, and shell state. Their exact output depends on the shell. env reports the environment passed to a process, not every internal shell variable.

Setting variables for one command

Put NAME=value arguments after env and before the command:

env DEBUG=1 my-program

DEBUG is available to my-program and any descendants it starts. It is not added to the calling shell after my-program exits.

Quoting values

Shell quoting controls argument boundaries before env receives them. Quote values containing spaces, wildcard characters, command-substitution syntax, or other characters meaningful to the shell:

env NAME='value with spaces' command
env MESSAGE="quoted value" command
env EMPTY= command

The last example supplies an existing variable with an empty value. An empty value is different from an unset variable: a program may distinguish NAME= from no NAME entry at all.

Quoting prevents the shell from splitting value with spaces into multiple arguments. It does not automatically escape data for every application; the receiving program still decides how to interpret the value.

Running with an empty or reduced environment

Use -i or --ignore-environment to discard inherited variables before applying new assignments:

env -i /usr/bin/env
env -i PATH=/usr/bin:/bin HOME="$HOME" command

The first command should display little or no environment, depending on the implementation. The second constructs a small environment containing an explicit PATH and the current value of HOME.

A clean environment is useful for:

  • Finding hidden dependencies in build and test commands.
  • Making automated output and behavior more reproducible.
  • Debugging failures caused by shell startup files or inherited configuration.
  • Reducing accidental propagation into sensitive or untrusted workloads.

Many programs need more than PATH and HOME. Add TERM for terminal-aware programs and a suitable LANG or locale variable when text behavior matters. Missing PATH means name-based command lookup may fail, so use an absolute executable path such as /usr/bin/program when appropriate.

Removing inherited variables

Use -u to remove one variable before launching a command. Repeat it to remove several:

env -u HTTP_PROXY -u HTTPS_PROXY command
env -u ALL_PROXY -u http_proxy -u https_proxy network-command

This is useful when a command should bypass inherited proxy settings. The same technique can remove locale variables, application configuration variables, or dynamic-loader-related variables that should not reach a child process.

Variable names are case-sensitive on many Unix-like systems. Proxy conventions often use both uppercase and lowercase names, so remove the forms that may be present. Inspect the environment before deciding which entries to remove.

Command lookup and PATH

When env is asked to run an executable name without a directory separator, the command is normally located using PATH. This is called command lookup:

env PATH=/usr/bin:/bin command

The assignment applies only to this invocation. A command with an absolute path names its executable directly:

env -i /usr/bin/env
/usr/bin/env -i /usr/bin/program

A relative path contains a directory reference such as ./program or tools/program. It is resolved relative to the current working directory and does not use PATH in the same way as a bare executable name.

Scripts should use a minimal, trusted PATH, especially in privileged contexts. Avoid relying on the current directory or on directories writable by untrusted users. In a normal shell, command -v program can help show which executable would be selected, but it does not replace verification of permissions and provenance.

Using env in shebang lines

A shebang is the first line of an executable script beginning with #!. The conventional form below asks env to locate python3 through PATH:

#!/usr/bin/env python3

This can be portable when the interpreter is installed in different locations on different systems. It also means the selected interpreter depends on the execution environment's PATH. An unexpected or attacker-controlled PATH can select an unintended interpreter, so use a controlled environment or a known absolute interpreter path when predictability and security are more important than installation flexibility.

Shebang argument parsing is handled by the operating system and can differ across Unix-like systems. Some systems pass the text after the interpreter as one argument; others provide different splitting behavior. Multiple interpreter options therefore may not work consistently in a simple shebang.

Where supported, env -S splits a string into multiple arguments:

#!/usr/bin/env -S python3 -u

-S is an implementation extension rather than a universal POSIX feature. Check the local env manual and operating-system documentation before depending on it. A wrapper script is often the most portable solution when several interpreter arguments are required.

Locale and application behavior

Locale variables influence messages, sorting, character classification, encoding assumptions, and numeric or date formatting. For predictable command output, especially output consumed by a script, select a known locale:

env LC_ALL=C command
env LANG=C sort file.txt

LC_ALL overrides individual LC_* categories and LANG. If LC_ALL is set, it normally takes precedence over LANG. Use the narrowest override that meets the requirement; setting LC_ALL=C can change user-facing messages and character handling as well as sorting.

The same pattern works for application settings:

env DEBUG=1 APP_CONFIG=/tmp/test.conf application
env HTTP_PROXY= HTTPS_PROXY= ALL_PROXY= network-command

Whether an empty proxy variable disables a proxy depends on the application. Removing the variables with env -u is often clearer when the application treats empty and unset values differently.

Exit status and shell scripting

When env successfully starts a command, it generally returns that command's exit status. An exit status of zero conventionally means success; a nonzero value indicates failure. If env cannot find or execute the command, it reports an error and returns a failure status.

if env LC_ALL=C ./run-tests; then
    echo "tests passed"
else
    status=$?
    echo "tests failed with status $status" >&2
    exit "$status"
fi

For a temporary setting within a shell script, a direct assignment before a command is also common:

DEBUG=1 ./program

Use env when its explicit options, such as -i or -u, make the intended environment easier to see. Do not assume that running env NAME=value command will make NAME remain set in the script's shell.

Ways to run a command with altered settings

MethodScopePersists after command?Best use case
env NAME=value commandThat command and its descendantsNoExplicit one-time overrides
NAME=value commandThat command and its descendantsNoShort shell syntax for a temporary assignment
export NAME=valueCurrent shell and later childrenYes, until unset or shell exitA setting needed for several commands in a session
env -i ... commandThat command and its descendantsNoMinimal, reproducible execution
unset NAMECurrent shell and later childrenYes, until restored or shell exitRemoving a variable from an interactive session

Portability and implementation differences

FeaturePOSIX baselineGNU/Linux considerationsBSD/macOS considerations
Display environmentSupported without a commandProvided by GNU coreutilsProvided by the system utilities
Ignore inherited environmentCommonly available as -iLong form --ignore-environment is commonly availableCheck the local manual for long-option support
Unset variables-u name is commonGNU syntax may also accept a long optionSyntax and repeated options can differ
Split shebang argumentsNot a universal baseline-S may be available depending on GNU coreutils versionAvailability varies by release and implementation

Linux distributions, BSD systems, macOS, and other Unix-like systems may ship different env implementations. Consult the local manual page:

man env
env --help

Do not assume that GNU long options or -S work on every target system. Test scripts on the systems where they will run.

Security and operational guidance

  • Do not trust an uncontrolled PATH when selecting interpreters or executables. Use a known path or a carefully constructed trusted path for privileged work.
  • Environment variables can expose secrets to child processes, diagnostics, crash reports, logs, or process-inspection mechanisms, depending on the operating system and permissions. Prefer a dedicated secret-management mechanism for sensitive credentials.
  • Use env -i or multiple -u options to limit inherited values when running untrusted or sensitive workloads.
  • Check for accidental propagation of credentials, proxy variables, application tokens, and dynamic-loader-related variables.
  • Remember that environment isolation is not a complete security boundary. The child still has the permissions of the account that launched it unless another isolation mechanism is used.

Troubleshooting

“Command not found” or an executable cannot be found

  • The command may be absent from PATH.
  • env -i may have removed PATH.
  • The executable name may be misspelled or the program may not be installed.

Inspect the normal shell's lookup result with command -v program, inspect the value with env | grep '^PATH=' is invalid? No need. Use proper:

env | grep '^PATH='
command -v program
/usr/local/bin/program

A command fails only under env -i

The program may depend on PATH, HOME, locale settings, configuration variables, credentials, or another inherited value. Start with a minimal environment and add only required variables incrementally:

env -i PATH=/usr/bin:/bin HOME="$HOME" LANG=C command

A variable disappears after env finishes

This is expected: env changes the child environment, not the parent shell. Use NAME=value followed by export NAME when the setting must remain available to later commands in the current shell.

The wrong interpreter runs from a shebang

The first matching interpreter in PATH is being selected, or the script is being launched with a modified PATH. Inspect and control PATH, or replace the shebang with a known absolute interpreter path when that is appropriate.

Shebang arguments behave unexpectedly

The operating system's shebang parser may limit or combine arguments, and the installed env may not support -S. Check local documentation, use a simpler shebang, or call a wrapper script.

Sorting or messages differ

Inspect LANG and LC_* variables. For machine-oriented tests, try env LC_ALL=C command, while remembering that this also changes language and character behavior.

A sensitive setting reaches a child unexpectedly

The setting was probably exported and inherited. Construct a reduced environment with env -i, or remove selected values with env -u NAME.

Exam-relevant notes

  • env without a command lists the current process environment.
  • env NAME=value command changes the environment for that command and its descendants only.
  • env -i starts with no inherited environment; essential values such as PATH may need to be restored.
  • env -u NAME command removes an inherited variable for one command.
  • A shell variable is not inherited unless it is exported.
  • A child receives a copy of its parent's environment; child changes do not flow back to the parent.
  • PATH controls lookup of bare executable names, while absolute paths identify executables directly.
  • #!/usr/bin/env interpreter improves interpreter-location portability but depends on PATH.
  • -S is useful for multiple shebang arguments where supported, but it is not universally portable.
  • env normally returns the executed program's exit status, but it returns failure if it cannot start that program.

For related material, see environment management with env.