39

When I check on my system's environment, a lot of environmental variables will pop up. How can I just search for a particular variable?

A book I'm reading says:

Sometimes the number of variables in your environment grows quite large, so much so that you don't want to see all of the values displayed when you are interested in just one. If this is the case, you can use the echo command to show an environment variable's current value.

How do I do this in a Linux terminal?

5 Answers5

51

Just:

echo "$VARIABLENAME"

For example for the environment variable $HOME, use:

echo "$HOME"

Which then prints something similar to:

/home/username

Edit: according to the comment of Stéphane Chazelas, it may be better if you use printenv instead of echo:

printenv HOME
chaos
  • 48,171
  • 5
    You forgot the quotes (unless you're implying zsh or rc/es syntax). echo is a poor choice of a command as it could transform the content of the variable. It will output the content of the shell parameter by the same name. That's not necessarily the same if using the Bourne shell or for env vars like 1, * for instance. And you can't use that approach for env vars whose name is not valid as a shell variable name. – Stéphane Chazelas Nov 20 '15 at 12:32
  • 6
    Also note that if there are several environment entries with the same name (OK, a pathological case), which one you'll get depends on the shell (usually either the first one or the last one). printenv VAR will display them all (at least for the GNU implementation). – Stéphane Chazelas Nov 20 '15 at 12:41
  • It is not very clean to edit one's answer from a comment that was already made earlier under another more fitting answer (printenv) when it turns out that printenv and printenv VAR even seem the better way to go. – questionto42 Sep 01 '21 at 13:03
14

By executing:

printenv

You will see all environment variables. For more info you can take a look at:

https://www.digitalocean.com/community/tutorials/how-to-read-and-set-environmental-and-shell-variables-on-a-linux-vps

  • 3
    To come close to actually answering the question, printenv variablename will display only the named variable; e.g., printenv  HOME will do approximately the same thing as echo  "$HOME". – G-Man Says 'Reinstate Monica' Nov 20 '15 at 12:19
5

It is important to understand that every process has its own set of environment variables.

When a process calls the fork() system call, a second process (the child) identical to the first (the parent) is created (this copy includes the environment, which resides just above the stack (or just below, depending how you think of stacks :-) - but in unix/linux the stack grows down from high addresses).

Usually, the child process will then call the execve() system call, which will throw away everything in its (virtual) memory and reconstruct it from the code and data sections in the specified binary file.

However, when it reconstructs the stack, it copies the environment and argument strings passed to execve() onto the stack first (in that order), before calling the main() function (a lot of the work is done in the crt0 bootstrap code after the execve() returns (to the entry point specified in the binary)).

There are wrappers for the execve() system call in the C library that will pass the current environment (i.e. a copy of the parents environment), instead of the caller providing it (so in effect the child will inherit the parent's environment) - see environ(7).

Try running (as root) the command ps axeww | less ... this will show you the environment for all processes! An interesting one is process id 1 (i.e. the init process - the first process created by the kernel at boot time).

If you want to look at the environment for a specific process (and you know it's process id), try running the command cat /proc/<PID>/environ (replacing <PID> with the process id).

Note that if a process has enough privileges, it can rewrite its own stack, which can make it difficult to know what its environment is - you will see some daemon processes like this in the ps output.

But in the end, all this waffle boils down to what @chaos said above, if you want to look at the current value of a specific environment variable in your shell process, just use the (builtin) command echo "$<NAME>" (replacing <NAME> with the name of the environment variable you are interested in) ... just be aware that the same variable may have a different value, or not exist at all, in another process.

  • 1
    (1) Note that the e option to ps, and the /proc/…/environ special file, might not exist on all systems.  (2) AFAIK, every Unix process has the privilege to rewrite its stack and modify its environment variables.  (3) For more discussion, see To whom do environment variables belong? (on [SU]). – G-Man Says 'Reinstate Monica' Nov 20 '15 at 19:25
  • I had it in my head that some systems had a way to prevent an unprivileged process from "hiding" its command line arguments and environment e.g. from root running ps ... but now that you have highlighted this point, I can't recall why I thought that. – Murray Jensen Nov 21 '15 at 02:39
  • @MurrayJensen according to some discussion on the highly voted question I asked about “curl” hiding its arguments in ps—it’s unspecified in POSIX whether ps returns the args as originally passed to the process, or a copy which the process may have modified after it began. Some system (I think Solaris??) shows the original args no matter what. (Here is the link.) This may have been what you were thinking of. :) – Wildcard Jun 17 '19 at 10:04
  • Bingo! Yes, of course Solaris does this "correctly" :-) Thanks for the refresher ... – Murray Jensen Jun 17 '19 at 15:17
2

You can get what you are looking for with export:

export | grep HOME

Will show the contents of the $HOME variable.

1

if you have to set a lot of vars :

  ( set -o posix ; set ) | sort >~/vars.before

after having set them :

  ( set -o posix ; set ) | sort >~/vars.after

than display what has been set:

  comm -3 ~/vars.before ~/vars.after | perl -ne 's#\s+##g;print "\n $_ "'

This way you will find yourself soon, working with multiple sets of shell vars pre-defined in cnf files, which combined with tmux will make you the master of configuration management in shell environments:

  # ---------------------------------------------------------
  # cat cnf/qto.dev.host-name.cnf
  # [MainSection]
  # postgres_db_name     = dev_qto
  # postgres_db_host     = host-name
  #
  # call by: doParseCnfEnvVars cnf/qto.dev.host-name.cnf
  # ---------------------------------------------------------
  doParseCnfEnvVars(){

     cnf_file=$1;shift 1;
     test -z "$cnf_file" && echo " you should set the cnf_file !!!"

     INI_SECTION=MainSection

     ( set -o posix ; set ) | sort >~/vars.before

     eval `sed -e 's/[[:space:]]*\=[[:space:]]*/=/g' \
        -e 's/#.*$//' \
        -e 's/[[:space:]]*$//' \
        -e 's/^[[:space:]]*//' \
        -e "s/^\(.*\)=\([^\"']*\)$/export \1=\"\2\"/" \
        < $cnf_file \
        | sed -n -e "/^\[$INI_SECTION\]/,/^\s*\[/{/^[^#].*\=.*/p;}"`

     # and post-register for nice logging
     ( set -o posix ; set ) | sort >~/vars.after

     echo "INFO added the following vars from section: [$INI_SECTION]"
     comm -3 ~/vars.before ~/vars.after | perl -ne 's#\s+##g;print "\n $_ "'
  }