Linux Internal Variables

What are they?

They are builtin variables which hold information about the environment, the users and the system. There are two main types; shell (bash) and environmental.

The scope of each is different. Shell variables are specific to the running shell and are not shared within other shells. On the other hand, environmental variables are not bound just to the current shell. Their scope extends to subshells.

These variables can have default values which are set either by the shell (bash), the user or some component of the system. Some variables are read-only e.g $PPID, while others can be simply changed by the user e.g $PS1.

For this post I only intend on covering just a few. There's of course plenty of documentation on the matter. See here for a complete list.

$IFS

The internal field separator, as the name suggests, this variable determines how Bash recognizes fields, or word boundaries, when it interprets character strings.

Note: $IFS defaults to whitespace in the form of ' \t\n', but we can change this anytime.

Examples:

Let's say we have a list of colors and I want to print each on a new line using a for loop:

#!/bin/bash
# colors.sh

colors="blue,red,yellow,navy blue,"

for color in $colors  
do  
  echo $color
done

By default this will not accomplish what I want. Bash will interpret blue,red,yellow,navy as one string since there's a space after navy, making blue the second string. This is what we get:

$ bash colors.bash
blue,red,yellow,navy  
blue  

This is not what we want. But, with the help of $IFS we can easily fix this.

#!/bin/bash
# colors.sh

IFS=","

colors="blue,red,yellow,navy blue,"

for color in $colors  
do  
  echo $color
done

Overwriting the original value of $IFS to , allows us to tell Bash we would like to word-split on commas instead of whitespace. We get the following:

$ bash colors.sh
blue  
red  
yellow  
navy blue  

Simple. Now let's see another use case of $IFS. Let's say you are working with metrics related to HTTP codes and you would like to organize this data in csv format.

$ http_codes=(500 404 401 302 200)
$ echo "${http_codes[*]}"
500 404 401 302 200  
$ csv_http_codes=($(IFS=,; echo "${http_codes[*]}"))
$ echo "${http_codes[*]}"
500,404,401,302,200  

In the first example, when we print the http_codes array we see the expected behavior, default whitespace separated strings. In the second example, we set the $IFS variable and echo the array, now separated by commas. Again, very simple yet very powerful.

$PIPESTATUS

You might be familiar with $?, it reads the exit status of the last command executed. This is very useful, we can use exit status to debug our code and handle errors.

But what about when running multiple commands in pipe? Following the execution of a pipe, a $? gives the exit status of the last command executed.

To get the exit status of each respective command executed in a pipe you will need to use $PIPESTATUS. The exit codes are stored in an array and can be called individually e.g $ echo ${PIPESTATUS[2]} to get the exit code for the second command in the pipe or to get all use an *.

Examples:

$ ls -1 | grep water | ls -1 | grep scripts | ls -1
DrawIt  
DrawT00L  
RubyMinProxy  
chef-users  
cli_weather  
ganglia_plugins  
nagios_plugins  
scripts  
splogTASH  
$ echo $?
0  
$ ls -1 | grep water | ls -1 | grep scripts | ls -1
DrawIt  
DrawT00L  
RubyMinProxy  
chef-users  
cli_weather  
ganglia_plugins  
nagios_plugins  
scripts  
splogTASH  
$ echo ${PIPESTATUS[*]}
0 1 0 0 0  

This is a simple example, but $PIPESTATUS can be used in many different ways to handle errors on specific commands in a pipe.

$SSH_CONNECTION

This is an environmental variable set by OpenSSH when logging in. This variable identifies the client and server in the connection. The variable contains four space-separated values: client IP address, client port number, server IP address, and server port number.

$ echo $SSH_CONNECTION
192.168.1.5 62877 172.217.7.142 22  

This one is great when scripting around ssh.

\$.

Finally, all the $ variables:

$0, $1, $2, $3 - Positional parameters, passed from command line to script, passed to a function, or set to a variable.

$? - Exit status of a command.

$# - Number of command-line arguments or positional parameters.

$* - All of the positional parameters, seen as a single word. Must be quoted.

$@ - Same as $*, but each parameter is a quoted string.

$$ - Process ID of the script itself/shell.

$! - Process ID of last job run in background.

$_ - Final argument of previous command executed.

That's just a few of them, make sure to check the links below for more information. Happy Scripting!

Sources:


Tagged under: Linux, bash, shell, variables, IFS, environmental variables, shell variables, builtin