0. What happened?
Today a seasoned Linux admin was confused about the below output.
$ echo $UID
1000
$ env | grep UID
$
Yes, he could print the value of $UID but couldn't find it in environment variables.
So the problem is, Is "UID" an environment variable?
1. Environment variables are standards.
Environment variables don't depend on any particular apps/shells. They're just strings formatted by a standard and saved in a specific memory area of a process. In C, the memory area starts at environ.
Below simple code prints all environment variables of the process as which the code running.
#include <stdio.h>
extern char **environ;
int main(int argc, char** argv)
{
int i = 0;
while(environ[i]) {
printf("%s\n", environ[i++]);
}
return 0;
}
In Unix-like OS, by default, child processes inherit all environment variables from their parent process. It's fairly straightforward if we think about the "fork()" system call.
2. Shell variables are for shell only.
There are NO standards for the memory layout of shell variables. It may use a hash table, a list, or anything it likes to store its variables.
Shell variables are like variables in any other programming language, such as Python, Ruby, ...
Shell variables are NOT passed to child processes.
3. Why the confusion?
Environment variables are never so confused with variables in other programming languages other than Bash/shell.
The reason is Bash (or other shells) use the exact same syntax to reference its own variables and the environment variables.
$varaible_name
It can NOT tell if “variable_name" is a shell variable or environment variable simply by its name.
Even though most environment variables have their name capitalized but it's not mandatory.
We can think about this from another way, that's that all environment variables are valid shell variables too.
4. How to differentiate shell variables and environment variables?
For system admins, most of the time, we don't care much about if a variable is a shell variable or an environment variable. But sometimes it's crucial to differentiate the two.
- use "env" to print all Environment Variables.
- use "set" to print Both Environment Variables and Shell Variables.
- use "export" to promote a shell variable to an environment variable.
- use "export -n" to demote an environment variable to a shell variable.
- use "unset" to remove a shell variable or an environment variable.
Back to the problem at the very beginning, "UID" is a shell/bash variable but NOT an environment variable, even though its name is capitalized.
$ echo $UID
1000
$ env | grep ^UID
$ set | grep ^UID
UID=1000
$ export UID
$ env | grep ^UID
UID=1000
$ set | grep ^UID
UID=1000
$ unset UID
bash: unset: UID: cannot unset: readonly variable
$ export -n UID
$ env | grep ^UID
$ set | grep ^UID
UID=1000
No comments:
Post a Comment