Variables in Shell
This article talks about the variable scope in shell, especially how to access variables between different scripts.
Local Variables
The set command displays all functions and local variables defined for a specific process:
1 | # this definition will be in `set`, not in `env` |
It also sorts the display alphabetically.
注意set中的variables 不一定出现在env中,顾名思义, env中显示的才是当前运行shell会被采用的variables.
ENV Variables
Environment variables are visible from the shell session and from any spawned child subshells, and also visable by the command launched from that shell. This makes environment variables useful in applications that create child subshells, which require parent shell information.
To view environment variables, use the env or the printenv command:
1 | env | grep ^HOME |
You can use export to create environment variable.
1 | export demo='hello world' |
You can use unset to remove an existing environment variable.
1 | unset demo |
If you want to only set the variable for one command in one use, just prefix it, eg:
1 | # EDITOR will only works for crontab command |
A common trick for programmers is to include the single dot symbol in their PATH environment variable. The single dot symbol represents the current directory:
1 | PATH=$PATH:. |
Declare Command
Note that declare can print both set and env variables:
1 | declare | grep ^HOME= |
declare command can be used to create local variables in set or export to env:
1 | # -i: integer |
You can mix the option:
1 | declare -x -l EDITOR |
Other ways to convert char to lower/upper case:
1 | val=abcdEFG |
Create constant (read-only) variable, cannot be unset and sustain for the shell session:
1 | ## set name as readonly |
Declare different kind of arrays, see my other blog Array in Script:
1 | ## index-based |
Shell Variables
Shell variables (actually the local variable) are available only in the shell that creates them. In fact, the Linux system also defines standard shell environment variables for you by default.
How to define a Shell environment variable: No space can appear between the variable, the equal sign, and the value:
1 | var1=value |
Variables defined within the shell script maintain their values throughtout the life of the shell script but are vanished when the shell script completes.
If you want to assign the value of one variable to another, must use $:
1 | var2=${var1} |
otherwise, var1 will be interpreted as text string.
1 | var2=var1 |
Variable Scope
My question is how to pass variables from one script to another? Basically there are 3 options:
-
Make the variable an environment variable (
exportit) before calling the child script (./script2). -
sourcethe child script and it will run in the same shell, This would let you share more complex variables like arrays easily, but also means that the other script could modify variables in the caller shell. -
pass as parameters to child script:
./script2 var1 var2 -
if use
execto replace current process, still need export variable.
Preserve ENV variables
Refer to this question. This is interesting and easy to make mistake, if I want to preserve global ENV variable when switch user in shell, use su xxx instead of su - xxx, - option will do:
- clears all environment variables except for TERM
- initializes the environment variables HOME, SHELL, USER, LOGNAME, PATH
- changes to the target user’s home directory
- sets argv[0] of the shell to ‘-’ in order to make the shell a login shell
But be very careful not let shell do variable expanding in command option:
1 | su xxx -c "... echo $a" |
Here $a will be expanded before executing, use single quote or escape the $ sign:
1 | su xxx -c '... echo $a' |