Software

7 Essential Bash Variables That Enhance My Scripts

Are you diving into Bash scripting? Have you encountered variables like $0 and $EUID and found yourself unsure of their meanings? Or perhaps you’re curious about how $UID and $EUID differ? We’ll discuss these variables, their functions, and why they’re crucial for your scripting endeavors.

Special Parameters

Quick Actions Worth Memorizing

Special parameters are a set of variables offered by Bash for specific tasks. There are fewer than ten, but I will highlight the most useful ones.

Finding the Script Path

While scripting, you may need to know the path to your script. For instance, including the script name at the top of a help menu is good practice. You can access the path using the $0 variable, which follows the POSIX standard and is compatible with most shells:

echo "$0"

To retrieve just the name of the script, you can use $(basename $0):

echo "$(basename $0)"

However, keep in mind that $0 might not always be reliable. For example, if you source /path/to/script.sh, it will return “bash” instead of the actual script path. In such cases, use the $BASH_SOURCE variable, which provides a more dependable alternative, but be aware that it’s specific to Bash.

Understanding Process Exit Status

Every program returns an exit status, known as the exit code. This code helps in decision-making when a command results in an error. For example, trying to list a non-existent directory with ls will yield a non-zero exit code.

Zero exit status indicates success, while any non-zero code suggests an error has occurred.

If you encounter a problem, you may want to stop execution. The $? variable will give you the exit code:

ls /system32
echo $?

To handle exit codes, the customary approach is to use a conditional statement to check the value of $?:

if [[ $? -eq 0 ]]; then
   echo "Success"
fi

You can also utilize a case statement for various exit codes:

case $? in
  0) echo "Success";;
  1) echo "Error";;
  *) echo "Unhandled error";;
esac

Another method is to use conditionals without brackets:

if ls /system32; then
  echo "/system32 exists"
fi

Or, the most succinct way with logical operators:

ls /system32 && echo "/system32 exists" # Executes on zero exit status.
ls /system32 || echo "/system32 does not exist" # Executes on non-zero exit status.

Accessing Script Arguments

<pWhen creating a Bash script, passing arguments is essential. Bash handles this through positional parameters. Here’s an example:

foo() {
  echo "$1" # First argument.
  echo "$2" # Second argument.
}
foo "first" "second"

Arguments work the same way at the script’s top level:

#!/usr/bin/env bash
echo "The first argument: $1"
echo "The second argument: $2"

You can then provide these arguments through the command line: script.sh "first" "second".

The "$@" parameter represents all arguments as an array:

foo() {
  for arg in "$@"; do
    echo "$arg"
  done
}
foo "first" "second"

The "$*" variable functions similarly, but it concatenates all arguments into one string (if quoted):

at() {
  printf '@: [%s]\n' "$@"
}

star() {
  printf '*: [%s]\n' "$*"
}

at "one two" "three"
star "one two" "three"

"$@" outputs the arguments across separate lines, while "$*" displays them on a single line.

To determine the count of arguments, use ${#@} or ${#*}:

foo() {
  echo ${#@}
  echo ${#*}
}
foo "one" "two"

Environment Variables

Avoid Situating Your Scripts

Environment variables supply values to running programs via the shell. For instance, $HOME indicates the path to the current user’s home directory.

Obtaining the User ID

At times, you may need the current user ID in a script. For example, you might work with a socket in a directory such as /run/user/1000; here “1000” is the user ID. For a robust script, avoid hardcoding this value, as it might differ for users.

To do this, use the $UID and $EUID variables. $UID shows the ID of the user executing a binary, while $EUID (effective user ID) represents the user ID of the currently running process. Generally, these values align, but they can differ for setuid binaries. For instance, when using sudo, they will be different at various stages.

The following command can illustrate this:

ps --forest -eo cmd,euid,ruid | grep -C 1 '[s]udo'

In the previous example, you can see that the EUID changes to “0” (root) instantly, while the UID does not alter until the final forked command (like “sleep”) runs as root.

When deciding which variable to use, remember that both relate to permissions. Some may use $EUID to check for root privileges, but in forking, it does not significantly differentiate between the two. Understanding their differences is essential, especially in setuid scenarios.

Retrieving Common User Paths

In many scripts, accessing the home directory is a frequent requirement. Hardcoding paths is generally discouraged since they may change. Instead, the XDG Directory Specification offers standard variables from freedesktop.org.

env | grep XDG | sort -u

Using XDG variables ensures that your scripts remain adaptable. Always set sensible defaults where applicable:

export "${XDG_CACHE_HOME:=$HOME/.cache}"

Commonly used variables include:

export "${XDG_CACHE_HOME:=$HOME/.cache}"       # Semi-temporary data.
export "${XDG_CONFIG_HOME:=$HOME/.config}"     # Configuration files.
export "${XDG_DATA_HOME:=$HOME/.local/share}"  # Downloaded data, etc.

Utilizing these variables is advisable instead of saving everything in /tmp or a custom directory within ~/.

Utilizing Variables for Portable Scripts

In addition to the discussed variables, many additional environment variables facilitate scripting in Bash. The variables I highlighted here are among the most frequently used. Hardcoding values can lead to significant issues over time, especially as your script library grows. It’s beneficial to rely on standard variables whenever possible to maintain functionality and ease of maintenance.

In closing, aim to familiarize yourself with and use a wide array of standard variables. The more you know, the more effective your scripting will become.

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button