Tuesday, November 6, 2012

Linux Shell environment

http://mylinuxbook.com/linux-shell-environment


Have you ever thought that how can you run a standard command line utility(for example : ‘cp’) from any directory in the shell irrespective of it’s presence in that directory? How does the shell know where the executable is present and whether it is present at all?

These questions might confuse someone who is new to the concept of Linux shell environment. So, in this article we will discuss the concepts related to Linux shell environment and how it is related to Linux command line utilities and other programs.
Please note that the article is aimed to explain generic Linux shell concepts but still assumes the Linux BASH shell as the base for the explanation whenever or wherever required.

Linux shell environment


What is shell environment?

Linux shell environment is nothing but a bunch of information that is generally used by programs and command line utilities for configuration purpose. The information in shell environment is stored in form of ‘VAR_NAME=VALUE’. Where VAR_NAME is the name of configuration variable and ‘VALUE’ is its value. Some typical use of the shell environment information includes the ability to fetch information like default printer, default browser, default text editor, home directory of user etc.
Note that there can be more than one values assigned to a variable present in shell environment. Usually multiple values are separated by a colon ‘:’. The multiple values are used by the programs in order (from beginning to end).
Broadly speaking the information in shell environment can be of two types :
  • Environment variables
  • Shell variables
The Shell variables are local to a shell session while the environment variables are global can be accessed by the child processes of the shell. We will discuss more of this later.

Why shell environment is required?

The shell environment is used to exchange the environment information between shell and the programs being run on the shell. Usually programs use the shell environment information to get basic details of the configuration for the user. For example, if a program uses a standard executable ( like ‘cp’ ) then the program can ask for the the environment variable PATH to get a list of paths where the standard executable can be found for this user. Also, a program can alter the shell information for its use.

An example of shell environment

The following command prints the list of environment variables on my system :
$ env
SSH_AGENT_PID=1744
GPG_AGENT_INFO=/tmp/keyring-IPc8fJ/gpg:0:1
TERM=xterm
SHELL=/bin/bash
XDG_SESSION_COOKIE=b0f3463de8e6bb37b3a6c53400000009-1351314568.473291-1180035551
WINDOWID=73400326
GNOME_KEYRING_CONTROL=/tmp/keyring-IPc8fJ
USER=himanshu
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:
XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0
XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0
SSH_AUTH_SOCK=/tmp/keyring-IPc8fJ/ssh
SESSION_MANAGER=local/himanshu-Inspiron-1525:@/tmp/.ICE-unix/1709,unix/himanshu-Inspiron-1525:/tmp/.ICE-unix/1709
DEFAULTS_PATH=/usr/share/gconf/ubuntu.default.path
XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg
PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
DESKTOP_SESSION=ubuntu
PWD=/home/himanshu
GNOME_KEYRING_PID=1698
LANG=en_IN
MANDATORY_PATH=/usr/share/gconf/ubuntu.mandatory.path
UBUNTU_MENUPROXY=libappmenu.so
COMPIZ_CONFIG_PROFILE=ubuntu
GDMSESSION=ubuntu
SHLVL=1
HOME=/home/himanshu
LANGUAGE=en_IN:en
GNOME_DESKTOP_SESSION_ID=this-is-deprecated
LOGNAME=himanshu
XDG_DATA_DIRS=/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-AoW4gioeCB,guid=79422fae0a11eb4dcc838f3700000026
LESSOPEN=| /usr/bin/lesspipe %s
DISPLAY=:0
XDG_CURRENT_DESKTOP=Unity
LESSCLOSE=/usr/bin/lesspipe %s %s
COLORTERM=gnome-terminal
XAUTHORITY=/home/himanshu/.Xauthority
_=/usr/bin/env
If you want to see the shell variables too then use the set command :
$ set
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:progcomp:promptvars:sourc
epath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_COMPLETION=/etc/bash_completion
BASH_COMPLETION_COMPAT_DIR=/etc/bash_completion.d
BASH_COMPLETION_DIR=/etc/bash_completion.d
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="4" [1]="2" [2]="24" [3]="1" [4]="release" [5]="i686-pc-linux-gnu")
BASH_VERSION='4.2.24(1)-release'
COLORTERM=gnome-terminal
COLUMNS=133
COMPIZ_CONFIG_PROFILE=ubuntu
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-AoW4gioeCB,guid=79422fae0a11eb4dcc838f3700000026
DEFAULTS_PATH=/usr/share/gconf/ubuntu.default.path
DESKTOP_SESSION=ubuntu
DIRSTACK=()
DISPLAY=:0
EUID=1000
GDMSESSION=ubuntu
GNOME_DESKTOP_SESSION_ID=this-is-deprecated
GNOME_KEYRING_CONTROL=/tmp/keyring-IPc8fJ
GNOME_KEYRING_PID=1698
GPG_AGENT_INFO=/tmp/keyring-IPc8fJ/gpg:0:1
GROUPS=()
HIMANSHU=1+3
HISTCONTROL=ignoreboth
HISTFILE=/home/himanshu/.bash_history
HISTFILESIZE=2000
HISTSIZE=1000
HOME=/home/himanshu
HOSTNAME=himanshu-Inspiron-1525
HOSTTYPE=i686
IFS=$' \t\n'
LANG=en_IN
LANGUAGE=en_IN:en
LESSCLOSE='/usr/bin/lesspipe %s %s'
LESSOPEN='| /usr/bin/lesspipe %s'
LINES=41
LOGNAME=himanshu
LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=
30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.z
ip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*
.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.
rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.t
if=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*
.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*
.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cg
m=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mk
a=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:'
MACHTYPE=i686-pc-linux-gnu
MAILCHECK=60
MANDATORY_PATH=/usr/share/gconf/ubuntu.mandatory.path
OPTERR=1
OPTIND=1
OSTYPE=linux-gnu
PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
PIPESTATUS=([0]="0")
PPID=9926
PS1='\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[0;31m\]\u\[\033[0;32m\]@\[\033[0;35m\]\h\[\033[1;35m\]:\[\033[1;33m
\]\w\[\033[0;34m\]$ '
PS2='> '
PS4='+ '
PWD=/home/himanshu
SESSION_MANAGER=local/himanshu-Inspiron-1525:@/tmp/.ICE-unix/1709,unix/himanshu-Inspiron-1525:/tmp/.ICE-unix/1709
SHELL=/bin/bash
SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
SHLVL=1
SSH_AGENT_PID=1744
SSH_AUTH_SOCK=/tmp/keyring-IPc8fJ/ssh
TERM=xterm
UBUNTU_MENUPROXY=libappmenu.so
UID=1000
USER=himanshu
WINDOWID=73400326
XAUTHORITY=/home/himanshu/.Xauthority
XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg
XDG_CURRENT_DESKTOP=Unity
XDG_DATA_DIRS=/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/
XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0
XDG_SESSION_COOKIE=b0f3463de8e6bb37b3a6c53400000009-1351314568.473291-1180035551
XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0
_=set
__grub_script_check_program=grub-script-check
_scp_path_esc='[][(){}<>",:;^&!$=?`|\\'\''[:space:]]'
...
...
...
Lets understand a few of the important environment variables :
  • HOME : The path of user’s home directory.
  • SHELL : The name of user’s default shell program.
  • EDITOR : The name of the default text editor for a user.
  • PATH : The paths that are searched for a program when it is executed from within a shell.
  • PWD : The current working directory of the user.
  • USER : The username of the current user.
  • CDPATH : Additional paths to be searched when cd command is used to change a directory.
  • PS1 : Customize and set the shell command prompt (more on this here).

Environment variables and Shell variables

As specified earlier, there are two types of variables in Linux environment, Shell variables and environment variables. Lets understand them here.
The shell variables are the variables that are restricted to current shell. This means the commands and programs using the current shell will be able to use or modify shell variables. If a separate shell instance is opened or if a program forks a child then shell variables are not visible there. So, the shell variables can be thought of as temporary shell environment variables that last only till the current shell session lasts.
Lets understand shell variables with an example :
$ EXAMPLE_SHELL_VARIABLE=1

$ echo $EXAMPLE_SHELL_VARIABLE
1
The first command above creates a shell variable named ‘EXAMPLE_SHELL_VARIABLE’ with 1 as its value. Next, using the echo command the value of the shell variable is printed on shell.
Now lets check the value of same variable in another instance of the shell:
$ echo $EXAMPLE_SHELL_VARIABLE

$
So we see that no corresponding value was printed. This means that the variable ‘EXAMPLE_SHELL_VARIABLE’ is local to the shell where it was created. Hence, it is a shell variable.
The environment variables are the variables that can be accessed by the child shells and the child processes that are forked from a shell. This is because the children get a copy of environment variables from the parent. The environment variables can be made globally available across the shells if they are entered into start-up files (will discuss later about them).
Lets understand how to create an environment variable. An environment variable can be created in any of the following two ways :
$ EXAMPLE_ENV_VAR=1
$ export EXAMPLE_ENV_VAR
OR
$ export EXAMPLE_ENV_VAR=1
Any of the above two commands creates an environment variable ‘EXAMPLE_ENV_VAR’ with value 1. This can be confirmed using the env command :
$ env | grep EXAMPLE_ENV_VAR
EXAMPLE_ENV_VAR=1
Now to confirm that this environment variable can be accessed in children of this shell, here is a shell script (for bash) that checks the value of this environment variable :
$ cat env_script.sh 
#!/bin/bash
echo "EXAMPLE_ENV_VAR=$EXAMPLE_ENV_VAR"
The reason for choosing a shell script is because when a shell script is run, a child shell is spawn to run the script. So, the child shell should get the copy of our environment variable along with the copy of all the environment variables from parent shell.
Here is the output when the shell script was run :
$ ./env_script.sh 
EXAMPLE_ENV_VAR=1
So we see that environment variable was indeed copied to the child process.
Now, lets go to another instance of a shell and try to fetch this environment variable there :
$ env | grep EXAMPLE_ENV_VAR
$
So we see that this variable was not present in the environment of a new shell. Well, this is because the new shell is not a child shell of the shell in which our environment variable was created. So, in order to make our environment variable accessable globally, it has to be put into one of the start-up files like .bashrc, .profile etc that a shell reads when it is created. The start-up files are discussed in a section below.

Naming conventions of variables in shell environment

Variable names in shell environment must follow the following rules :
  • Variable names can only contain letters (a-z & A-Z) or numbers(0-9)
  • From special characters only underscore _ is allowed
  • A variable name cannot begin with a number
Also, as a guideline, the environment variables would have their name in UPPERCASE.

Some basic commands related to Linux shell environment

1. The echo command
This command can be used to print the values of the variables present in shell environment. Here are some of the examples of this command :
  • Print the value of an environment variable
    $ echo $HOME
    /home/himanshu
  • Do not print the trailing newline using -n option
    $ echo -n $HOME
    /home/himanshu$
  • Enable interpretation of escape sequences using -e option
    $ echo \\n
    \
    $ echo -e \\n
    
    $

2. The env command
This command can be used to print the existing environment. Also, env command can be used to run a program in a modified environment.Here are some of the examples of this command:
  • Remove newline from the end of each output line
    $ env -0
    SSH_AGENT_PID=1744GPG_AGENT_INFO=/tmp/keyring-IPc8fJ/gpg:0:1TERM=xtermSHELL=/bin/bashXDG_SESSION_COOKIE=b0f3463de8e6bb37b3a6c53400000009-1351314568.473291-1180035551WINDOWID=73400326GNOME_KEYRING_CONTROL=/tmp/keyring-IPc8fJUSER=himanshuLS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0SSH_AUTH_SOCK=/tmp/keyring-IPc8fJ/sshSESSION_MANAGER=local/himanshu-Inspiron-1525:@/tmp/.ICE-unix/1709,unix/himanshu-Inspiron-1525:/tmp/.ICE-unix/1709DEFAULTS_PATH=/usr/share/gconf/ubuntu.default.pathXDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdgPATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/gamesDESKTOP_SESSION=ubuntuEXAMPLE_ENV_VAR=1PWD=/home/himanshuGNOME_KEYRING_PID=1698LANG=en_INMANDATORY_PATH=/usr/share/gconf/ubuntu.mandatory.pathUBUNTU_MENUPROXY=libappmenu.soCOMPIZ_CONFIG_PROFILE=ubuntuGDMSESSION=ubuntuSHLVL=1HOME=/home/himanshuLANGUAGE=en_IN:enGNOME_DESKTOP_SESSION_ID=this-is-deprecatedLOGNAME=himanshuXDG_DATA_DIRS=/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-AoW4gioeCB,guid=79422fae0a11eb4dcc838f3700000026LESSOPEN=| /usr/bin/lesspipe %sDISPLAY=:0XDG_CURRENT_DESKTOP=UnityLESSCLOSE=/usr/bin/lesspipe %s %sCOLORTERM=gnome-terminalXAUTHORITY=/home/himanshu/.Xauthority_=/usr/bin/env
  • Unset a variable for a particular process using -u option
    $ cat env_script.sh 
    #!/bin/bash
    echo "EXAMPLE_ENV_VAR=$EXAMPLE_ENV_VAR"
    
    $ ./env_script.sh 
    EXAMPLE_ENV_VAR=1
    
    $ env --unset=EXAMPLE_ENV_VAR ./env_script.sh 
    EXAMPLE_ENV_VAR=
  • Ignore inherited environment using -i option
    $cat env_script.sh 
    #!/bin/bash
    echo "EXAMPLE_ENV_VAR=$EXAMPLE_ENV_VAR"
    echo "HOME=$HOME"
    echo "SHELL=$SHELL"
    echo "USER=$USER"
    
    $./env_script.sh 
    EXAMPLE_ENV_VAR=
    HOME=/home/himanshu
    SHELL=/bin/bash
    USER=himanshu
    
    $env -i ./env_script.sh 
    EXAMPLE_ENV_VAR=
    HOME=
    SHELL=/bin/bash
    USER=

3. The export command
This command is used to export the variable and their values to the shell environment. Once done, these variables become environment variables of the shell. Here are a few examples of this command:
  • Export a variable-value pair to the shell environment
    $export MY_VAR=10
    
    echo $MY_VAR
    10
    
    $cat env_script.sh 
    #!/bin/bash
    echo "MY_VAR=$MY_VAR"
    
    $./env_script.sh 
    MY_VAR=10
  • Export a new value to an existing variable-value pair
    $export MY_VAR=$MY_VAR:50
    
    $echo $MY_VAR
    10:50
  • Display all the environment variables using -p option
    $export -p
    declare -x COLORTERM="gnome-terminal"
    declare -x COMPIZ_CONFIG_PROFILE="ubuntu"
    declare -x DBUS_SESSION_BUS_ADDRESS="unix:abstract=/tmp/dbus-AoW4gioeCB,guid=79422fae0a11eb4dcc838f3700000026"
    declare -x DEFAULTS_PATH="/usr/share/gconf/ubuntu.default.path"
    declare -x DESKTOP_SESSION="ubuntu"
    declare -x DISPLAY=":0"
    declare -x GDMSESSION="ubuntu"
    declare -x GNOME_DESKTOP_SESSION_ID="this-is-deprecated"
    declare -x GNOME_KEYRING_CONTROL="/tmp/keyring-IPc8fJ"
    declare -x GNOME_KEYRING_PID="1698"
    declare -x GPG_AGENT_INFO="/tmp/keyring-IPc8fJ/gpg:0:1"
    declare -x HOME="/home/himanshu"
    declare -x LANG="en_IN"
    declare -x LANGUAGE="en_IN:en"
    declare -x LESSCLOSE="/usr/bin/lesspipe %s %s"
    declare -x LESSOPEN="| /usr/bin/lesspipe %s"
    declare -x LOGNAME="himanshu"
    ...
    ...
    ...

4. The unset command
This command can be used to remove one or more environment variables from the list. Please note that unlike the env command, this command removes the environment variable from the existing shell environment.
Here are a few examples :
  • Remove a single variable
    echo $MY_VAR
    10:50
    
    $unset MY_VAR
    
    $echo $MY_VAR
    
    $
  • Remove multiple variables
    $echo $EXAMPLE_ENV_VAR $EXAMPLE_SHELL_VARIABLE
    1 2
    
    $unset EXAMPLE_ENV_VAR EXAMPLE_SHELL_VARIABLE
    
    $echo $EXAMPLE_ENV_VAR $EXAMPLE_SHELL_VARIABLE
    
    $

Login and Non-Login shells

There are two types of shells namely login and non-login shells.
As the name suggests, login shell is one that prompts for user-name and passowrd to authenticate the user. This type of shell is usually encountered when user log-in’s using command line mode through virtual consoles in Linux. Or this type of shell also comes up if you try to login as some other user through login command in Linux.
On the other end, a non-login shell is one that does not prompt for user-name and password. So, any shell you open once you are authenticated fall under the category of non-login shells.
Now, the question arises that how are they different? Well, a login shell differs from a non-login shell in terms of the start-up configuration files it reads.A login shell reads the following start-up configuration files to setup the environment for the new user :
  • /etc/profile
  • ~/.bash_profile
  • ~/.bash_login
  • ~/.profile
A non-login shell reads the following configuration files :
  • /etc/bash.bashrc
  • ~/.bashrc
To learn more about these start-up configuration files, how they affect Linux shell environment and how they can be used to make an evironment variable permanent, read here and here.

Access and modify Linux shell environment through a C program

Here is an example C program that demonstrates how to access and manipulate shell environment from within the C code:
#include
#include

extern char**environ;

int main(int argc, char *argv[])
{
     int i = 0;
     while(environ[i] != NULL)// environment variables are stored in array 'environ' 
     {
         printf("[%s]\n",environ[i]); // Print each variable
         i++;
     }

     char *ptr = getenv("MY_VAR"); // Get the value of environment variable MY_VAR
     if(NULL == ptr)
     {
         if(putenv("MY_VAR=1")) // If it does not exist, create one with the same name
         {
             printf("\n putenv() failed\n");
             return -1;
         }
         ptr = getenv("MY_VAR"); // Now get it's value
     }
     printf("\nMY_VAR contains value [%s]\n",ptr);

     if(putenv("MY_VAR=2")) // Now change it's value
     {
         printf("\n putenv() failed\n");
         return -11;
     }

     printf("\nMY_VAR value changed successfuly\n");

     ptr = getenv("MY_VAR"); // Now, again fetch the new value
     printf("\nNew Value of MY_VAR is [%s]\n",ptr);

     return 0;
 }

As you would notice :
  • The extern pointer variable environ points to the complete environment list available to a program
  • The function getenv() is used to get value for the environment variable passed to it as an argument.
  • The function setenv() is used to change the value of the environment variable.
When the above code is run, here is the output :
$ ./env
[SSH_AGENT_PID=1764]
[GPG_AGENT_INFO=/tmp/keyring-TylH3s/gpg:0:1]
[TERM=xterm]
[SHELL=/bin/bash]
[XDG_SESSION_COOKIE=b0f3463de8e6bb37b3a6c53400000009-1351342309.287583-21311980]
[WINDOWID=56623110]
[GNOME_KEYRING_CONTROL=/tmp/keyring-TylH3s]
[USER=himanshu]
[LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:]
[XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0]
[XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0]
[SSH_AUTH_SOCK=/tmp/keyring-TylH3s/ssh]
[SESSION_MANAGER=local/himanshu-Inspiron-1525:@/tmp/.ICE-unix/1729,unix/himanshu-Inspiron-1525:/tmp/.ICE-unix/1729]
[DEFAULTS_PATH=/usr/share/gconf/ubuntu.default.path]
[XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg]
[PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games]
[DESKTOP_SESSION=ubuntu]
[PWD=/home/himanshu/practice]
[GNOME_KEYRING_PID=1718]
[LANG=en_IN]
[MANDATORY_PATH=/usr/share/gconf/ubuntu.mandatory.path]
[UBUNTU_MENUPROXY=libappmenu.so]
[COMPIZ_CONFIG_PROFILE=ubuntu]
[GDMSESSION=ubuntu]
[SHLVL=1]
[HOME=/home/himanshu]
[LANGUAGE=en_IN:en]
[GNOME_DESKTOP_SESSION_ID=this-is-deprecated]
[LOGNAME=himanshu]
[XDG_DATA_DIRS=/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/]
[DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-8ry9YDMXxq,guid=19867c56e419543a92d6ba0c00000028]
[LESSOPEN=| /usr/bin/lesspipe %s]
[DISPLAY=:0]
[XDG_CURRENT_DESKTOP=Unity]
[LESSCLOSE=/usr/bin/lesspipe %s %s]
[COLORTERM=gnome-terminal]
[XAUTHORITY=/home/himanshu/.Xauthority]
[OLDPWD=/home/himanshu]
[_=./env]

MY_VAR contains value [1]

MY_VAR value changed successfuly

New Value of MY_VAR is [2]
Whenever a command (like ‘ls’) is run in shell then the shell code works on similar lines to get the list of paths in the PATH variable and then searches in each directory to find the command. Once the command is found in a path, the complete path is used by the shell code to execute that command.

The ? environment variable

This is an interesting and useful environment variable that stores the return of the last command that is run on shell.
For example :
$ cd /home/himanshu
$ echo $?
0
So we see that when the echo $? command was run after a successful change directory (cd) command, the value printed was 0.
Here is another example :
$ shutdown 4
shutdown: Need to be root
$ echo $?
1
So, this time we can see that the echo $? command printed 1 as the shutdown command failed to execute.
NOTE: In Linux most of the programs return 0 in case of success and non-zero value in case of failure. This helps other programs or shell scripts to determine if the program was successful or failure. Usually echo $? command is used in shell scripts to determine the return value of the last run program.
Following are some other similar environment variables that hold useful information :
$$ is the PID of the current process.

$# is the number of arguments in $*

$* is the list of arguments passed to the current process
There are many others. See the complete list here.

Back to the original question

I think now, its the correct point to answer the question that I asked at the begining of this article about how standard commands are accessible from any path within the shell. This is because the shell searches for any executable in the paths mentioned in the PATH variable.
The PATH variable in my system looks like :
PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
And if I search where the standard command line utilities are present on my system :
$ which cp
/bin/cp
We see that the utility ‘cp’ is presnt in /bin which is added in the list of paths in the PATH variable.
So, whenever cp command is run, the shell searches cp in all the paths present in the PATH variable (starting from the first path) and hence finds the ‘cp’ command in /bin path and executes it. Similarly, if you want your custom executable to behave the same way then it can either be kept at any of the locations in the PATH variable list of paths or the PATH variable can be changed to add your own path(where your executable is kept) to it.
Note that one can create a custom command like cp and update the environment variable PATH with the path of directory in which it is kept. If the this path is placed before /bin (in which the standard cp command resides) in the PATH variable then this way one can overrride a standard command.

CONCLUSION

Linux shell environment plays an important role in day to day activities of a user on Linux OS. A good idea about this concept can save you from some complicated software installation and configuration related issues.

REFERENCES

http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_01.html
http://www.arc.vt.edu/resources/software/unix/shells.php
http://www.ucblueash.edu/thomas/Intro_Unix_Text/Env_Vars.html
http://lists.gnu.org/archive/html/bug-coreutils/2009-06/msg00063.html

No comments:

Post a Comment