Fundamental Skills / Automation /

1. Bash Scripting

  1. Intro
  2. Why Automate?
  3. Command Line Automation
    1. Bash Variables
    2. Aliases
  4. Creating a Bash Script
  5. User Input
  6. Conditions
  7. Loops
  8. Custom Functions
  9. Cheatsheet
    1. Define an Alias
    2. For Loops
  10. Worksheet

This guide was written several years ago and has not yet been updated. You may encounter outdated information.

Intro

We’ll go over some simple examples of bash scripting in this lesson, a powerful Unix-based tool for automation.

All examples below with the $ prefix indicate a command that is being typed into the command line.

Why Automate?

Scripting lets you:

Scripting in bash is good for several use cases:

Why not bash?

Command Line Automation

Before we look at scripts, there are some other things we can do to make command-line work faster.

Bash Variables

You can set bash variables (aka environment variables) within your terminal, and then use them within commands.

To set a variable, use the export command:

export VARIABLE=value

You can then print the value:

You can even set the variable to the result of another command with an evaluation using $() - for example:

To set a persistent variable, define it in the ~/.bashrc file in your home directory:

$ nano ~/.bashrc

...[edit the file]...

export VARIABLE_NAME=value

Aliases

Aliases are a simple way of adding a small script straight into your command line. Think of it as a custom terminal command.

If you are using a standard bash terminal, aliases are defined in your ~/.bashrc file. If you’re using something like zsh, you’ll need to edit ~/.zshrc or equivalent.

Tip: See what terminal you’re using by typing echo $TERM

To add an alias, add a line like the following anywhere in your .bashrc file:

alias command_name="command"

For example, you might group up some common aliases based on their purpose, using a comment (#) to indicate what they do:

# Edit common files
alias nanbash="nano ~/.bashrc"
alias nanhosts="sudo nano /etc/hosts"

# Start webserver in enum directory
alias enumserve="cd ~/Documents/enum; python3 -m http.server"

As you can see, you can run commands with root permissions (sudo), chain commands together with ;, and even change your environment (such as with cd)

Creating a Bash Script

These are the main steps to make a new script:

Here’s an example:

Note: in the example above we typed echo “#!/bin/bash” with a backslash before the exclamation mark - this is to ‘escape’ the exclamation mark, which is a special character in bash

User Input

You can take user input as positional arguments. These are supplied after the name of the script (e.g. ./script.sh argument1) and accessed within the script with $x (where x is the x-th argument).

Here’s a (very) simple example script that prints (with echo) the contents of the first argument:

#!/bin/bash
echo "$1"

Here’s an example:

You can also use read to take user input during the execution of the script:

#!/bin/bash
echo "Tell me your name!"
read name
echo "$name"

Here the script waits for input:

After input is received, it’s saved to the $name variable and printed:

You can also use named flags as arguments - this process is a bit more complicated, and there are a few different ways of doing it.

One way is to use a for loop (more on these later) to loop over all the parameters provided, and check which ones are present. Here’s an example:

for arg in "$@"
do
   case $arg in
      -s|--standalone)
      STANDALONE="Standalone flag present"
      shift ;;
      -i|--input)
      INPUT="$2"
      shift
      shift ;;
      -h|--help)
      print_usage
      exit 1 ;;
      *)
      OTHER_ARGUMENTS+=("$1")
      shift ;;
   esac
done

echo "$STANDALONE"
echo "Flag with input present - input: $INPUT"
echo "Other parameters: ${OTHER_ARGUMENTS[*]}"

shift is used to move on and process the next character on the command line. It is also possible to use getopts - an example can be found here.

Conditions

Bash supports simple logical statements, such as if, elif, and else, as well as numerous logical operators (such as =, !=, -gt and -lt for greater than/less than, and -e to check whether files exist).

Here’s an example of a simple script that checks if a provided username is correct, then checks whether a file exists:

#!/bin/bash
echo "Enter username:"
read name
if [ $name != "admin" ]
then
    echo "Get outta here"
elif [ -e "./checkfile" ]
then
    echo "Welcome admin!"
else
    echo "Checkfile doesn't exist"
fi

Here’s an example:

Loops

You can use for and while loops in bash: - for loops repeat the code inside the loop as per a certain number of items (e.g. for every line in a file) - while loops repeat the code inside the loop as long as a condition is true

A simple for loop could be written like so:

for ip in $(seq 1 10)
do
	ping -c 1 10.11.1.$ip
done

This iterates over each number in the sequence 1 to 10, assigns the number to the variable $ip, and runs ping using that variable.

A while loop can be written like so:

count=1
while [ $count -lt 11 ]
do
    echo $count
    count=$[$count + 1]
done

This simply counts up to 10, increasing the count by 1 each time.

Custom Functions

You can define functions in bash, which are repeatable code blocks that can take arguments.

Here’s a simple definition of a function:

get_logs () {
    echo "$(tail /var/log/apache2/access.log)"
}

This will print the most recent 10 lines in the Apache access log (Apache is a common webserver).

You can then call this function multiple times in the script to monitor the logs, with ten second breaks in between:

get_logs () {
    echo "$(tail /var/log/apache2/access.log)"
}

get_logs
sleep 10
get_logs
sleep 10
get_logs

You can also give arguments to a function:

echo_name () {
    echo "$1"
}

echo_name "First Name"
echo_name "Second Name"

Cheatsheet

Define an Alias

alias name="command"

Reload your bash environment:

$ source ~/.bashrc

For Loops

Standard syntax:

for item in $list
do
  [bash command with $item]
done

One line:

$ for item in $list; do [bash command with $item]; done]

Worksheet

  1. Create a script to change directory to /tmp, clone the shefesh.com git repository, and open index.html with the firefox command
  2. Start a simple Python server in the cloned directory. Then write a script that uses curl to request the index.html file, find all the <p> elements with grep, and output their contents with the tags stripped