RizTech Academy logo
RizTech Academy
Linux FundamentalsLesson 6 of 740 min

Shell scripting basics

The moment you find yourself typing the same sequence of commands twice, you should put them in a script. A shell script is just a file of commands the shell runs top to bottom — but with variables, conditionals and loops, it becomes the way you automate the repetitive parts of operations: deployments, backups, setup, checks. Automation is the heart of DevOps, and shell scripting is where it starts. This lesson is writing a shell script that is reliable rather than a footgun.

Your first script

A script is a text file of commands. Create one:

#!/usr/bin/env bash
echo "Starting deploy"
pwd
echo "Done"

Two things make it a proper script:

  • The shebang — the first line #!/usr/bin/env bash tells the system to run the file with bash. It must be the very first line.
  • Execute permission — chmod +x deploy.sh (the permissions lesson), so you can run it with ./deploy.sh.

Run it: ./deploy.sh. The shell reads the file top to bottom and runs each line as if you had typed it. That is the whole idea — a script is your commands, saved and repeatable.

Variables and arguments

Store values in variables and read them back with $:

name="asha"
echo "Hello $name"          # Hello asha
greeting="Hello $name"      # variables can contain other variables

Two rules that trip up everyone:

  • No spaces around =. name="asha" works; name = "asha" does not (bash reads it as a command).
  • Quote your variables. Use "$name", not $name. If a variable contains spaces or is empty, an unquoted use breaks — rm $file when $file is empty or has a space is a classic disaster. Always double-quote variable expansions; it prevents a whole category of bugs.

Scripts also receive arguments from the command line:

#!/usr/bin/env bash
echo "Deploying version $1 to $2"   # $1 is the first argument, $2 the second

Run as ./deploy.sh v1.2 staging and $1 is v1.2, $2 is staging. $0 is the script's name, $# is the number of arguments, and $@ is all of them. Arguments are how you make a script reusable instead of hard-coding values.

Making decisions: if

Scripts make choices with if, testing a condition in [ ... ]:

#!/usr/bin/env bash
if [ "$1" = "production" ]; then
  echo "Deploying to PRODUCTION — are you sure?"
elif [ -z "$1" ]; then
  echo "No environment given" >&2   # >&2 sends this to standard error
  exit 1                             # exit with a non-zero code = failure
else
  echo "Deploying to $1"
fi

Common tests: [ "$a" = "$b" ] (strings equal), [ "$a" != "$b" ], [ -z "$x" ] (empty), [ -n "$x" ] (not empty), [ -f path ] (file exists), [ -d path ] (directory exists), and numeric [ "$n" -gt 5 ] (greater than). Note the spaces inside the brackets are required. exit 1 stops the script with a failure code — which matters because whatever runs your script (a CI pipeline) checks that code.

Repeating: loops

Do something for each item with a for loop:

for env in staging production; do
  echo "Checking $env"
done

for file in /var/log/*.log; do     # loop over matching files
  echo "Rotating $file"
done

And a while loop repeats until a condition stops being true. Loops are how one script handles many things — every server, every file, every environment — without repeating yourself.

The two lines that make scripts safe

Here is the most valuable thing in this lesson. By default, a shell script keeps going after a command fails, and it treats an unset variable as an empty string — both of which cause quiet, dangerous bugs (a deploy that "succeeds" after a step failed; an rm -rf "$DIR/" where $DIR was never set, deleting /). Guard against this by starting serious scripts with:

#!/usr/bin/env bash
set -euo pipefail
  • set -e — exit immediately if any command fails, instead of ploughing on. A failed step stops the script.
  • set -u — treat an unset variable as an error, instead of silently empty. Catches typos and missing arguments.
  • set -o pipefail — a pipeline fails if any command in it fails, not just the last one.

These three (set -euo pipefail) turn a script from "runs to the end no matter what went wrong" into "stops the moment something is wrong" — which is exactly what you want for a deploy or a backup. Add them to the top of every non-trivial script; it is the single biggest reliability upgrade you can make, and its absence is behind a lot of "the script said it worked but it didn't".

Check your work

A script = a file of commands run top to bottom, with a shebang (#!/usr/bin/env bash, first line) and execute permission (chmod +x), run as ./script.sh.

Variables: name="asha" (no spaces around =), read with $name; always double-quote ("$name") to survive spaces/empties (unquoted is a classic bug). Arguments: $1,$2,… ($0 name, $# count, $@ all) make scripts reusable.

if tests [ ... ] (spaces required): =/!=, -z/-n (empty/not), -f/-d (file/dir exists), -gt etc.; exit 1 = failure (checked by CI). Loops: for x in ...; do ... done, while.

Make scripts safe: start with set -euo pipefail — -e exit on any failure, -u error on unset variable, -o pipefail fail if any piped command fails. The biggest reliability upgrade; without it scripts "succeed" after a step failed.

Practice

  1. Write and run a script with a shebang that prints a greeting; chmod +x it first.
  2. Add an argument so it greets $1, and double-quote the variable; test with an argument containing a space.
  3. Add an if that exits with code 1 (and a message to stderr) when no argument is given.
  4. Write a for loop over a list of environment names, printing an action for each.
  5. Add set -euo pipefail to a script, then deliberately reference an unset variable and a failing command; show how the script now stops.
  6. Explain, with an example, why unquoted variables and missing set -e are dangerous in a deploy script.

Official documentation

Next: SSH, keys and connecting to a server.

Stuck on this lesson?

Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.

About the internship