[Linux] fully interpreting Linux environment variables and linux environment variables

Source: Internet
Author: User

[Linux] fully interpreting Linux environment variables and linux environment variables
I. Overview

Environment Variable: Bash shell uses a feature called "environment variables" to store information about shell sessions and work environments. It allows you to store data in memory, this allows you to access programs and scripts running on shell. The data can be used to identify users, accounts, systems, shell features, and any other data you need to store.

The environment variables in shell include global environment variables and local environment variables. A local variable is declared in the form of KV (variable = value). The export local variable is upgraded to a global environment variable. Since shell is used separately, it is obvious that there are differences between the two.

1. Global Environment Variables

Features: Declares a global environment variable, which is available in the current shell Process and sub-shell process. The parent shell process is unavailable, the "available" can be understood as a copy of the global environment variable of the parent shell process, rather than a copy of the global environment variables inherited from the parent class, therefore, adding, deleting, querying, and adding global environment variables of the parent shell process are not affected in the sub-shell process.

Proof 1: 1) the global variables are available in the current shell and sub-shell, but the parent shell process is unavailable; 2) the Sub-shell copies the copy of the global environment variables of the parent shell process, therefore, the sub-shell is transparent to the parent class for variable operations.

#! /Bin/bash # parent shell Process #1. declare a global environment variable #2. fork: A sub-shell process # You can access the global variables defined by the parent class in the sub-shell process # modify or delete the global environment variables defined by the parent class in the sub-shell, no impact on the parent process # Add a global environment variable to the sub-shell. The parent class cannot be accessed #3. the global environment variable modified or deleted by accessing the quilt shell Process in the parent shell process. The variable value has not changed #4. the global environment variable of the subclass added by the parent shell Process access: the result is that the global variable cannot be accessed by export testing = "zhangsan" echo "father. The initial value is: testing = zhangsan "sh son. shecho "father: $ testing" echo "global variable added by father access subclass: $ sonTest"
#! /Bin/bash # subshell process echo "son accesses the global variables defined in the parent shell process: $ testing "testing =" son zhangsan "echo" son modified the global variables of the parent class: testing = $ testing "export sonTest =" son lizi "echo" son added a subclass global variable: $ sonTest"
[Work @ localhost global] $ sh father. sh father defines a global variable. The initial value is testing = zhangsanson to access the global variable defined in the parent shell process: zhangsanson modified the global variable of the parent class: testing = son zhangsanson added the subclass global variable: son lizifather: The global variable added by zhangsanfather to access the quilt class:

Proof 2: log on to a shell fork sub-shell process. The sub-shell process export a global environment variable. After execution, the variable is not found in the logon shell.

#! /Bin/bash # log on to shell fork and create a sub-shell process # declare a global environment variable for the sub-shell process # After the sub-shell is executed, log out to shell # The shell cannot access this variable export userName = "zhangsan"
Run the script. After the script is executed, access the variable with no value.
[work@localhost global]$ sh var.sh [work@localhost global]$ echo $userName[work@localhost global]$ 

2. Local Environment Variables

Features: The current shell process is available. Parent and Child shell processes are unavailable.

Proof: the parent process defines local variables and the child process cannot access them. The child process defines local variables and the parent process cannot access them.

#! /Bin/bashfatherVar = "father var" echo "local variable defined by father: $ fatherVar" sh son. shecho "son-defined local variable: $ sonVar"
#! /Bin/bashecho "son accesses the local variable defined by fanther: $ fatherVar" sonVar = "son var" echo "son-defined local variable: $ sonVar"
[Work @ localhost local] $ sh father. sh father-defined local variable: father varson accesses the local variable defined by fanther: son-defined local variable: son varson-defined local variable:

3. Summary

1. Global Environment Variables: The Current shell Process and sub-process are available, the parent shell process is unavailable, and the modification of the sub-process variables to the current shell is transparent without impact;

2. Local environment variables: The current shell process is available, and the parent process and child process are unavailable;

3. If the environment variable exists in the memory and disappears after power-off, you can access it after the next system power-on:

A. If this variable is system-level (shared by all users), you can export it in/etc/profile;

B. If this variable is valid only for the current user, you can ~ /. Bash_profile (or ~. /Bash_login, or ~. /Profile, or ~. /Bashrc, or export in/etc/bashrc;

Supplement: the fork process mode is discussed in this section, excluding source and exec. The differences between the three methods are discussed later;

2. Start shell

The environment variables are stored in the memory and disappear after power failure. However, you will find environment variables such as USER, PATH, LOGNAME, and HOSTNAME that exist as long as the system is started. Why?

The operating system has at least five features: memory management, file system management, process management, device management (hardware), and user interface management, the user interface here cannot be understood as the init 5 startup interface function or a windows-like interface, but an interface for the user to interact with the system kernel, that is, a set of access interfaces provided by the kernel to the outside world, so when the system is started,Start shellThis is why it was born. It provides users with a set of interfaces to interact with Linux kernel.

The startup shell starts as the system starts. It can be understood as the top-level parent shell environment for subsequent logon to shell, interactive shell, and non-interactive shell, therefore, the global environment variables declared in the startup shell can be accessed by all subsequent shells, except for local variables.

After the shell is started, it first reads and runs the command in/etc/profile to read and execute the file. It mainly does two things:

1. Define and declare global environment variables. export path user logname mail hostname histsize histcontrol can be accessed by all shell processes;

2. to/etc/profile. run the application startup files under this directory in the d directory, which stores the startup files of some applications. These applications are started as the system starts, such as vim and less, it is similar to some self-running software defined in the windows Startup item;

The contents in the/etc/profile. d directory and/etc/profile are as follows:

# /etc/profile# System wide environment and startup programs, for login setup# Functions and aliases go in /etc/bashrc# It's NOT a good idea to change this file unless you know what you# are doing. It's much better to create a custom.sh shell script in# /etc/profile.d/ to make custom changes to your environment, as this# will prevent the need for merging in future updates.pathmunge () {    case ":${PATH}:" in        *:"$1":*)            ;;        *)            if [ "$2" = "after" ] ; then                PATH=$PATH:$1            else                PATH=$1:$PATH            fi    esac}if [ -x /usr/bin/id ]; then    if [ -z "$EUID" ]; then        # ksh workaround        EUID=`id -u`        UID=`id -ru`    fi    USER="`id -un`"    LOGNAME=$USER    MAIL="/var/spool/mail/$USER"fi# Path manipulationif [ "$EUID" = "0" ]; then    pathmunge /sbin    pathmunge /usr/sbin    pathmunge /usr/local/sbinelse    pathmunge /usr/local/sbin after    pathmunge /usr/sbin after    pathmunge /sbin afterfiHOSTNAME=`/bin/hostname 2>/dev/null`HISTSIZE=1000if [ "$HISTCONTROL" = "ignorespace" ] ; then    export HISTCONTROL=ignorebothelse    export HISTCONTROL=ignoredupsfiJAVA_HOME=/usr/java/jdk1.7.0_75CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jarPATH=$PATH:$JAVA_HOME/binexport PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL# By default, we want umask to get set. This sets it for login shell# Current threshold for system reserved uid/gids is 200# You could check uidgid reservation validity in# /usr/share/doc/setup-*/uidgid fileif [ $UID -gt 199 ] && [ "`id -gn`" = "`id -un`" ]; then    umask 002else    umask 022fifor i in /etc/profile.d/*.sh ; do    if [ -r "$i" ]; then        if [ "${-#*i}" != "$-" ]; then            . "$i"        else            . "$i" >/dev/null 2>&1        fi    fidoneunset iunset -f pathmunge

3. log on to shell

No matter which user logs on to the system, the global environment variables printed by printenv are the same, because these values are defined in the startup shell. However, you will find that there are actually differences, which will lead to the illusion that you cannot understand the real meaning of the logon shell.

1. Difference between start shell and login shell

After the system is started, it is followed by user login and access. The result of printenv is different for different users to log on to the system. That is to say, different users have different shell process environments. This also indirectly indicates that the login shell is different from the startup shell, logon to shell is a top-level environment. Verify it first and then describe it.

Verification 1: The global environment variables are different for logon by different users. Select root and work users to test the global environment variable PATH.

Step 1: log on to the work account, echo $ PATH>/home/work/var. path

Step 2: Switch the user and environment to root, su-root, echo $ PATH>/home/work/var. path

Step 3: cat/home/work/var. path and compare the values of the two rows. The execution result is as follows:

[work@localhost ~]$ echo $PATH > /home/work/xx.path[work@localhost ~]$ su - root Password: [root@localhost ~]# echo $PATH >> /home/work/xx.path[root@localhost ~]# cat /home/work/xx.path /usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/java/jdk1.7.0_75/bin:/home/work/bin/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/java/jdk1.7.0_75/bin:/root/bin

2. logon shell details

The logon shell adds personalization to the startup shell. Different users obtain different logon environments. In addition to the root user, the main directory of other users in Linux is/home/xxx, which must be customized here.

Logon to the shell portal ,~ /. Bash_profile file.

A. bash_profile File

When you enter the user name and password to log on to the system, start the shell process to fork a login shell process, which will be read in sequence in the main directory of the current login user (if any) file ~ /. Bash_profile ,~ /. Bash_login ,~ /. Note that not all three files exist (my system only exists in centos 2.6.32. bash_profile). If there are multiple reading commands, read the commands and execute them in the listed order.

Reading to. bash_profile mainly involves two things: source (the last section will have a detailed explanation of source )~ /. Bashrc file. The other is re-export PATH. The details are as follows.

# .bash_profile# Get the aliases and functionsif [ -f ~/.bashrc ]; then        . ~/.bashrcfi# User specific environment and startup programsPATH=$PATH:$HOME/binexport PATH

B. The bashrc file shows the cause of inconsistent PATH environment variables of different users. However, source ~ /. What does the bashrc file do?

. The bashrc file also does two things. One is to define some aliases (defining aliases can be used freely in the current shell, similar to defining local environment variables ), another thing is the source file/etc/bashrc.

# .bashrc# User specific aliases and functionsalias rm='rm -i'alias cp='cp -i'alias mv='mv -i'# Source global definitionsif [ -f /etc/bashrc ]; then        . /etc/bashrcfi

C./etc/bashrc File

What does/etc/bashrc and TM do? Two things are also done in the/etc/bashrc file. One thing is to define some local variables (no export is available, and the sub-shell of fork cannot be accessed ), umask permission is also set according to UID; another thing is to read and execute the/etc/profile again. the file in the d directory already exists with the startup shell. Although it seems to be repeated, it is actually a necessary reason. here we need to combine it with the interactive shell (explained in the next section.

At this point, the user login environment Initialization is complete, all the public global variables of users are available, the personalized global variables of different users are also ready, and the local variables related to themselves are also ready, everything is ready, you can perform system operations.

# /etc/bashrc# System wide functions and aliases# Environment stuff goes in /etc/profile# It's NOT a good idea to change this file unless you know what you# are doing. It's much better to create a custom.sh shell script in# /etc/profile.d/ to make custom changes to your environment, as this# will prevent the need for merging in future updates.# are we an interactive shell?if [ "$PS1" ]; then  if [ -z "$PROMPT_COMMAND" ]; then    case $TERM in    xterm*)        if [ -e /etc/sysconfig/bash-prompt-xterm ]; then            PROMPT_COMMAND=/etc/sysconfig/bash-prompt-xterm        else            PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'        fi          ;;      screen)        if [ -e /etc/sysconfig/bash-prompt-screen ]; then            PROMPT_COMMAND=/etc/sysconfig/bash-prompt-screen        else            PROMPT_COMMAND='printf "\033]0;%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'        fi          ;;      *)          [ -e /etc/sysconfig/bash-prompt-default ] && PROMPT_COMMAND=/etc/sysconfig/bash-prompt-default        ;;        esac  fi    # Turn on checkwinsize  shopt -s checkwinsize  [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "  # You might want to have e.g. tty in prompt (e.g. more virtual machines)  # and console windows  # If you want to do so, just add e.g.  # if [ "$PS1" ]; then  #   PS1="[\u@\h:\l \W]\\$ "  # fi  # to your custom modification shell script in /etc/profile.d/ directoryfiif ! shopt -q login_shell ; then # We're not a login shell    # Need to redefine pathmunge, it get's undefined at the end of /etc/profile    pathmunge () {        case ":${PATH}:" in            *:"$1":*)                ;;            *)                if [ "$2" = "after" ] ; then                    PATH=$PATH:$1                else                    PATH=$1:$PATH                fi        esac    }    # By default, we want umask to get set. This sets it for non-login shell.    # Current threshold for system reserved uid/gids is 200    # You could check uidgid reservation validity in    # /usr/share/doc/setup-*/uidgid file    if [ $UID -gt 199 ] && [ "`id -gn`" = "`id -un`" ]; then       umask 002    else       umask 022    fi    # Only display echos from profile.d scripts if we are no login shell    # and interactive - otherwise just process them to set envvars    for i in /etc/profile.d/*.sh; do        if [ -r "$i" ]; then            if [ "$PS1" ]; then                . "$i"            else                . "$i" >/dev/null 2>&1            fi        fi    done    unset i    unset pathmungefi

4. Interactive shell

After init 3 logs on to the system, the commands you input on the command line interface are actually executed in the login shell environment. You can access any local variables declared in the login shell. But when you enter bash to start an interactive shell explicitly (the command line interface gives you the feeling that you have knocked on the carriage return and nothing else appears to happen ), you will find that the rough event is still on the same interface, but you cannot access the local variables you just accessed. This is because a sub-shell environment is logged on to shell fork, and the sub-shell environment cannot access local variables in the parent shell environment.

1. Differences between logon shell and Interactive shell

Proof 1: the interactive shell is a sub-shell process that logs on to shell fork instead of logging on to shell.

Step 1: After logging on to the system, define a local variable testing = "zhangsan" and input echo $ testing on the command line to test the access result;

Step 2: Enter bash in the command line to start an interactive shell and access the defined local variable echo $ testing. The test is not accessible;

Step 3: Enter the exit command on the command line to exit the Interactive shell and access echo $ testing again;

[work@localhost ~]$ testing="zhangsan"[work@localhost ~]$ echo $testingzhangsan[work@localhost ~]$ bash[work@localhost ~]$ echo $testing[work@localhost ~]$ exitexit[work@localhost ~]$ echo $testingzhangsan[work@localhost ~]$ 
The interactive shell is a sub-process used to log on to the shell.

2. Explanation of Interactive shell

When you enter the bash command in the command line to explicitly enter the Interactive shell environment, what happened to the system? Unlike starting shell and logging on to shell, interactive shell does not occur when the system is started or when the user is logged on. At this time, the system has been started and the user has logged on, the commands and results executed by the previously read files already exist in the memory. What do interactive shell do?

The interactive shell is a sub-process used to log on to the shell. Therefore, it has all the global environment variables declared by the login shell (of course, it also has the global environment variables declared by the startup shell ), however, he does not log on to the local variables declared by shell, nor does he log on to some personalization declared by shell, such as umask and alias. Therefore, the current user does not have any reason to start an interactive shell, and personalization is lost, every time you enable the feature, you have to personalize it again, which is too difficult. Do you use this function? Is it useless?

Don't be excited. It is reasonable to exist.

The first step of Interactive shell startup is to check whether there is a. bashrc file in the current user's home directory (this file is described in detail in the previous section). If so, read and execute commands in the file. Does this file declare local variables and personalized configurations? The first step is to define the alias, and then the source/etc/bashrc file and the/etc/bashrc file define the user's local variables at the beginning, then load and execute/etc/profile. d directory.

You will be surprised to find that opening an interactive shell is exactly the same as logging on to the shell environment! Clean, pure, and original, just like a girl! Excited ?! There are even more exciting things. Don't forget that the child shell can access the global environment variables of the parent shell, but the parent shell cannot access the environment of the child shell, this means that the bad things you do in the interactive shell will never affect the parent shell environment (of course, you do not need to modify the configuration file, but the configuration file is the operation content that persists, instead of changing the memory content, the file will still be restored after the system starts loading after power failure), of course, if you want to feel the parent shell environment, you need to modify the file.

In fact, you can also feel that login to shell is actually the first interactive shell. The user can ask the system to answer a question, which is very friendly and responsive!

5. Non-Interactive shell

Non-interactive shell is not so friendly, which is also the core value of non-interactive shell. It automatically completes the commands specified in the script without user intervention.

Therefore, in simple terms, non-interactive shell means executing shell scripts.

Of course, a non-interactive shell acts as a child process that interacts with the shell fork and has all the global environment variables of the parent process (again: does not have local environment variables of the parent process, you cannot access it in the script), and it will not read and execute it in the user's main directory like the interactive shell. the bashrc file personalize itself. The simplest and most direct example is the ls alias command ll. If you use this command in the script, you will receive the "run. sh: line 3: ll: command not found "error message, as shown in the following code example.

[work@localhost env]$ alias -p |grep llalias ll='ls -l --color=auto'[work@localhost env]$ cat run.sh #!/bin/bashll[work@localhost env]$ sh run.sh run.sh: line 3: ll: command not found[work@localhost env]$ echo $?127[work@localhost env]$ lltotal 16drwxrwxr-x. 2 work work 4096 Apr 23 06:56 aliasdrwxrwxr-x. 2 work work 4096 Apr 23 05:43 globaldrwxrwxr-x. 2 work work 4096 Apr 23 05:59 local-rw-rw-r--. 1 work work   16 Apr 23 07:59 run.sh

To personalize a non-interactive shell, the system also provides the "interface", that is, the environment variable BASH_ENV. When you start a non-interactive shell, the system will check this environment variable to view the Startup file to be loaded and executed. Therefore, you can customize a file path and then export BASH_ENV to achieve your desired purpose and result, this is also the legendary BASH_ENV vulnerability. However, this vulnerability was fixed in the 2014.09 month and will not be repeated here.

1) simple use of the BASH_ENV vulnerability: Click to open the link

2) Introduction to BASH_ENV vulnerability repair: Click to open the link

6. fork, source, and exec

During shell programming, all functions are often not written in one script, which is too difficult to maintain and requires multiple script files to work together. So the question is, how can we call other scripts in one script? There are three methods: fork, source, and exec.

1. fork

Fork is actually the most troublesome. It is to fork a sub-shell process from the current shell process to complete the call. All the situations described above are called in the form of fork. In a simple summary, that is, copy the global environment variable of the parent shell process to the sub-shell process. Because it is a copy, the sub-shell process has no effect on all the operations of this variable on the parent shell process, the local variables of the parent process are not accessed by the shell process. The global environment variables of the sub-shell are useful to the self-and sub-shell processes, and are blocked by the parent shell process, the local variable of the sub-shell is only valid for the current shell process.

In addition,Fork call is actually to call another script in one script. After the called script is executed, it is returned to the parent shell process. The parent shell process continues to execute the remaining commands.In this example, we are glad that all of the above are covered. Here we will show the sample code called by fork.

#! /Bin/bashecho "the parent shell process starts to execute" sh son. sh # The parent shell fork sub-shell environment executes another script echo "the parent shell process is completed"
#! /Bin/bashecho "sub-shell called"
[Work @ localhost fork] $ sh father. sh: the parent shell process starts to execute the subshell. The execution of the parent shell process is completed.

2. source

The source call is to load the called script to the Current shell environment for execution. It is like running in a script. Their defined local variables are shared in the same process., As shown in the following example.

#! /Bin/bash ../son. sh # Load son. sh to the Current shell environment using the source method echo "father accesses the local variable defined in son: $ sonVar"
#! /Bin/bashsonVar = "son var" echo "son defines a variable: sonVar = $ sonVar"
[Work @ localhost source] $ sh father. sh son defines a variable: sonVar = son varfather to access the local variable defined in son: son var

3. exec

Exec call is also a fork sub-shell environment to execute the called script. However, the execution right of the parent shell environment is denied, that is, the execution right is handed over to the called script, the parent shell environment no longer has the execution permission. No matter whether or not the commands in the parent shell script are executed completely, the execution ends with the completion of the sub-shell process.

#! /Bin/bashecho "parent shell starts to execute" exec sh son. shecho "parent shell completes execution, but this statement will not be executed"
#! /Bin/bashecho "the sub-shell is called by the parent shell exec. The execution permission has been preemptible and will not be returned to the parent shell Process"
[Work @ localhost exec] $ sh father. sh the parent shell starts to execute the subshell and is called by the parent shell exec. The execution permission has been preemptible and will not be returned to the parent shell process.

You have already introduced fork, source, and exec on the Internet. If you do not understand it here, you can search for "fork, source, and exec ".

VII. Environment Variable PATH

What is the environment variable PATH? This environment variable is useful when calling shell scripts. The Troubles and problems are mainly concentrated here. The PATH environment variable defines the paths for searching and executing commands in various shell environments, just like the path environment variable on windows. Execute your own script. If you do not want to enter the script directory or enter the full PATH, copy your script to any directory under PATH, however, this is too intrusive and not elegant. The following describes a more elegant development technique.

Development tips: Easy Command Execution

The soft connection and alias allow custom scripts to be called in the Current shell environment.

Step 1: Check the PATH environment variable and select any one with the operation permissions of the current user. In this example, select/home/work/bin.

Step 2: Write a test script run. sh: Put it in the/home/work/shell/myCodes directory. There is only one command "echo $0" to print the name of the current execution script, then make a soft connection ln-s/home/work/shell/myCodes/run. sh/home/work/bin/run

Step 3: Define the alias. First, let's take a look at alias-p. do not define the alias again. Then, define the alias run = "sh run ".

Result: You can call/home/work/shell/myCodes/run without executing the run command in the directory where the script is located. sh script, and support tab key completion, isn't it very NB!

[work@localhost myCodes]$ lsrun.sh[work@localhost myCodes]$ cat run.sh #!/bin/bashecho $0[work@localhost myCodes]$ pwd/home/work/shell/myCodes[work@localhost myCodes]$ cat run.sh #!/bin/bashecho $0[work@localhost myCodes]$ ll /home/work/bin/run  lrwxrwxrwx. 1 work work 31 Apr 23 09:57 /home/work/bin/run -> /home/work/shell/myCodes/run.sh[work@localhost myCodes]$ alias -p |grep runalias run='run'[work@localhost myCodes]$ cd /home/work/[work@localhost ~]$ runi'm bash_env/home/work/bin/run


If there are any mistakes or omissions in this article, please correct them. Thank you!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.