# Basic Shell Scripting

> Chapter 8 of the Courseiva LINUX-PLUS curriculum — https://courseiva.com/learn/linux-plus/basic-shell-scripting

**Official objective:** 2.4 — Create and execute basic shell scripts

## Introduction

What's the one skill that turns a Linux user from someone who types commands one at a time into someone who can automate whole tasks in seconds? That's shell scripting. For the XK0-006 exam, you need to understand how to create and execute basic shell scripts because it's the foundation for system administration, automation, and troubleshooting — and it's a topic the exam loves to test.

## The Recipe Card Analogy

Ever watched a friend cook the same pasta dish over and over, but each time they have to dig through the cupboard, check the pasta box for timing, and taste-test the sauce six times because they keep forgetting if they added oregano?

What if they wrote down every step on a single card: 'Boil 500ml water, add 200g pasta, cook 11 minutes. While pasta cooks, heat 1 tbsp olive oil, add 3 cloves garlic, fry 1 minute, add 400g chopped tomatoes and 1 tsp dried oregano, simmer 10 minutes. Drain pasta, mix with sauce, serve'.

That recipe card is a shell script. It's a file that stores a sequence of commands exactly the way a person would type them into a terminal. The computer reads the script and executes each line in order, just like a cook follows a recipe step by step. But here's the important part: the computer doesn't get distracted, doesn't forget the oregano, and doesn't accidentally boil the pasta for 25 minutes. It does exactly what's written, every single time.

In IT, a shell script does the same thing. Instead of an IT person manually typing 'check disk space', 'delete old log files', 'restart the web server', and 'send a confirmation email' every day, they write those commands into a script file. The computer runs that script, making the process fast, consistent, and mistake-proof. Just like making dinner without the chaos.

## Core explanation

A shell script is a plain-text file that contains a series of Linux commands. The 'shell' is the program that interprets and runs those commands — think of it as the translator between you and the operating system's kernel (the core of Linux). The most common shell on Linux is called Bash (Bourne Again SHell), and for the XK0-006 exam, Bash is the one you need to know.

Every shell script needs two things: a shebang line and executable permissions. The shebang is the first line of the script, and it looks like this: #!/bin/bash. That '#!' symbol tells the system which interpreter to use. If you write #!/bin/bash, the system knows to run the script using the Bash shell. Without the shebang, the system might try to use a different shell or just fail. For the exam, always start your scripts with #!/bin/bash.

The second requirement is making the script executable. In Linux, every file has permissions that control who can read, write, or execute it. By default, a new script file has read and write permissions but not execute. You add execute permission with the command: chmod +x scriptname.sh. The 'chmod' stands for 'change mode', and '+x' adds execute permission. Without this step, running the script will give you a 'Permission denied' error, which is a common exam trap.

Now, what goes inside the script? Any command you can type at the shell prompt can go into a script. For example:

- echo 'Hello, world!' prints text to the screen.
- ls lists files in the directory.
- cd changes directory.
- pwd prints the current working directory.
- grep searches text for patterns.
- mkdir creates a new directory.

But the real power of scripting comes from variables, conditionals, and loops. A variable stores data. In Bash, you create a variable by assigning it a value: NAME='Linux'. To use that variable later, you put a dollar sign in front: echo $NAME prints 'Linux'. Variables are case-sensitive, so $name and $NAME are different. By convention, environment variables (like PATH) are uppercase, and script variables are often lowercase.

Conditionals let your script make decisions. The basic structure is:

if [ condition ]
then
   commands
fi

For example:

if [ $AGE -ge 18 ]
then
   echo 'You are an adult.'
fi

The '-ge' stands for 'greater than or equal to'. Other common operators are '-eq' (equal), '-ne' (not equal), '-lt' (less than), '-le' (less than or equal to), and '-gt' (greater than). The spaces around the brackets are mandatory — omitting them is a classic exam mistake.

Loops repeat commands. The two main types are 'for' loops and 'while' loops. A 'for' loop iterates over a list:

for fruit in apple banana cherry
do
   echo 'I like $fruit'
done

A 'while' loop runs as long as a condition is true:

count=1
while [ $count -le 5 ]
do
   echo 'Count is $count'
   count=$((count + 1))
done

The $(( )) syntax performs arithmetic. Without it, Bash treats numbers as text.

To run a script, you have several options. The most common is: ./scriptname.sh. The './' tells the shell to look in the current directory. You can also run it with: bash scriptname.sh, which explicitly invokes the Bash interpreter and doesn't require the script to have execute permission. For the exam, know both methods.

Shell scripts often include comments — lines that start with '#'. Comments are ignored by the shell and are only for humans reading the code. Good scripts include comments explaining what each section does.

Why does this exist? Before shell scripts, system administrators had to type every command by hand, every time. A simple daily task like backing up logs meant remembering and typing a dozen commands. Scripting packages those commands into a single file that can be run with one command, run automatically via cron (a scheduling tool), and shared with other team members. It replaces manual repetition with automated consistency.

## Real-world context

Sarah is a junior Linux administrator at a medium-sized e-commerce company. Every morning at 3 AM, the company's web server rotates its log files — it closes the current log, compresses the old one, and starts a fresh log for the new day. If Sarah had to do this manually, she'd need to log in at 3 AM, type a series of commands, and hope she didn't make a typo. Instead, she writes a shell script.

Here's what Sarah's script does step by step:

1. It checks the current time to make sure it's running during the maintenance window.
2. It finds all log files older than 24 hours.
3. It compresses those files using gzip to save disk space.
4. It moves the compressed files to an archive directory.
5. It deletes any archived logs older than 30 days.
6. It sends a confirmation email to Sarah with a summary of what was done.
7. It logs the execution to a separate audit file.

Sarah writes this script once, tests it on a development server, and then schedules it using cron. The cron entry looks like this: 0 3 * * * /home/sarah/scripts/rotate-logs.sh. That line means 'run the script at 3 AM every day'.

Now, every morning at 3 AM, the script runs automatically. Sarah checks the audit log when she arrives at work. If the script encountered an error — for example, if the disk was too full to compress the logs — the script is written to catch that error and send an alert to Sarah's phone.

In a real business context, this automation does three critical things:

- It saves time. Sarah doesn't spend 20 minutes every day performing a repetitive task. That's over 120 hours per year saved.
- It eliminates human error. A tired administrator at 3 AM might accidentally delete the wrong files. The script follows the exact same steps every time.
- It provides a clear audit trail. The script logs every action, so if something goes wrong, Sarah can review exactly what happened.

Sarah also uses scripts for other tasks: checking server health (disk usage, memory, CPU), deploying software updates across multiple servers, resetting user passwords, and generating reports. Each script starts as a simple set of commands and grows as she adds error handling, logging, and flexibility.

For the XK0-006 exam, the real-world scenario questions will ask you to read a script and identify what it does, what's wrong with it, or what output it produces. You might see a script that checks if a user exists before adding them, or a script that loops through a list of servers to test network connectivity. The exam expects you to understand how the pieces fit together, not just memorise individual commands.

## Exam focus

The XK0-006 exam tests your ability to create, read, and debug basic shell scripts. This isn't about writing complex programs — it's about demonstrating that you understand the structure and syntax of a script.

Here are the exact concepts the exam targets:

- Shebang line: You must know that #!/bin/bash is the standard shebang for Bash scripts. The exam may show you a script without a shebang or with a wrong shebang (like #!/bin/csh) and ask what happens when you run it.
- Making scripts executable: Understand chmod +x and the difference between running ./script.sh and bash script.sh. The exam loves to present a script that produces 'Permission denied' and ask why.
- Variables: Assignment (name=value), referencing ($name), and the fact that spaces around the equals sign cause errors. A common question: 'What is the value of the variable after this assignment? name = John' — the answer is that it's an error because of the spaces.
- Special variables: $0 (script name), $1, $2 (first, second arguments), $# (number of arguments), $? (exit status of the last command). These appear in exam questions regularly.
- Conditionals: The if/then/else/fi structure. Know that the spaces inside the square brackets are mandatory. The exam will give you a snippet like 'if [$x -eq 5]' and ask what's wrong — the answer is missing spaces.
- Comparison operators: -eq, -ne, -lt, -le, -gt, -ge for numbers; = and != for strings (in Bash, the string comparison operator inside brackets is a single equals sign, not ==).
- Loops: for loops over a list, while loops with a condition. The exam might show a loop that counts or iterates through files and ask what the output will be.
- Exit codes: Every command returns a number (0 for success, non-zero for failure). Scripts often use 'exit 0' for success and 'exit 1' for a generic error. The $? variable captures the last exit code.
- Comments: Lines starting with # are ignored. The exam may include commented-out code and ask whether it executes.
- Command substitution: Using $(command) or `command` to capture output into a variable. Modern exam questions prefer the $( ) syntax.
- Arithmetic: $(( expression )) for integer maths. The exam will test that you know this syntax exists.

Exam traps to watch out for:

- The 'test' command vs. square brackets: In Bash, [ is an alias for the test command. So 'if test 5 -eq 5' is the same as 'if [ 5 -eq 5 ]'. The exam might use either, and you must recognise both.
- Variable quoting: If you don't put double quotes around a variable, the shell may split it into multiple words. For example, if filename='my file.txt', then 'rm $filename' tries to remove two files ('my' and 'file.txt'), while 'rm "$filename"' removes the one file. This is a classic exam trap.
- Missing 'then' or 'do': The 'if' keyword must be followed by 'then' on a new line (or on the same line separated by a semicolon). The 'for' keyword must be followed by 'do'. Questions that show 'if [ ... ] echo hi' are missing 'then' and will fail.
- The dollar sign in if statements: When testing variable values in an if condition, you must use the dollar sign: 'if [ $age -eq 18 ]'. But in the assignment, no dollar sign: 'age=18'. Mixing these up is a common error.

To prepare, practise reading scripts line by line and predicting the output. Focus on scripts that combine variables, conditionals, and loops in a short space. The exam will not ask you to write a full script from scratch — instead, you'll debug or analyse existing scripts, choose the correct command to complete a script, or interpret what a script will do.

## Step by step

1. **Create the Script File** — Use a text editor like nano, vim, or a simple echo command to create a file. For example: nano myscript.sh. The .sh extension is a convention that helps humans identify script files, but Linux doesn't require it.
2. **Add the Shebang Line** — Write #!/bin/bash as the first line of the file. This is not a comment — it's a special marker that tells the kernel to use the Bash interpreter. Without this, the script might run in a different shell or fail.
3. **Write Your Commands** — Add the Linux commands you want to automate, one per line. You can use variables, conditionals, and loops to make the script flexible. For example: echo 'Starting backup'; tar -czf backup.tar.gz /home/user/data.
4. **Make the Script Executable** — Run chmod +x myscript.sh to add execute permission. This allows you to run the script with ./myscript.sh. Without this step, the system will refuse to run it, showing 'Permission denied'.
5. **Execute the Script** — Run the script by typing ./myscript.sh if you're in the same directory, or provide the full path like /home/user/myscript.sh. Alternatively, run it with bash myscript.sh, which doesn't require execute permission.
6. **Test and Debug** — Check the output. If something goes wrong, use echo statements to print variable values at different points, or run bash -x myscript.sh to see each command before it executes — this is called a 'debug mode' and is very useful for the exam.

## Comparisons

### Running ./script.sh vs Running bash script.sh

**Running ./script.sh:**
- Requires execute permission (chmod +x)
- Uses interpreter from the shebang line
- If shebang is missing or wrong, may fail or use wrong shell

**Running bash script.sh:**
- Does not require execute permission
- Always uses Bash interpreter regardless of shebang
- Can run scripts without a shebang line

### Variable assignment: name=value vs Variable reference: $name

**Variable assignment: name=value:**
- No dollar sign
- No spaces around equals sign
- Placed in script to store a value

**Variable reference: $name:**
- Has a dollar sign prefix
- Can be used inside double quotes: "$name"
- Retrieves the stored value for use

### if [ $x -eq 5 ] (correct) vs if [$x -eq 5] (incorrect)

**if [ $x -eq 5 ] (correct):**
- Spaces after [ and before ]
- Works correctly
- The [ is treated as a separate command

**if [$x -eq 5] (incorrect):**
- No spaces around brackets
- Causes a syntax error
- Bash sees [$x as a single token and fails

### exit 0 vs exit 1

**exit 0:**
- Indicates success
- Convention for successful script completion
- $? becomes 0 after this command

**exit 1:**
- Indicates failure or error
- Convention for abnormal script termination
- $? becomes 1 after this command

### for loop vs while loop

**for loop:**
- Iterates over a fixed list of items
- Runs a known number of times based on the list
- Syntax: for var in list; do ... done

**while loop:**
- Runs while a condition is true
- Can be infinite if condition never becomes false
- Syntax: while [ condition ]; do ... done

## Diagram

_Flowchart showing the process of creating, making executable, executing, and debugging a basic shell script._

```mermaid
flowchart TD
    A[Start: Create script file] --> B[Add #!/bin/bash shebang]
    B --> C[Write commands, variables, conditionals, loops]
    C --> D[Make executable: chmod +x script.sh]
    D --> E[Run: ./script.sh or bash script.sh]
    E --> F{Script executes successfully?}
    F -->|Yes| G[Output appears, task automated]
    F -->|No| H[Debug: check syntax, permissions, variable quoting]
    H --> C
```

## Common misconceptions

- **Misconception:** You need to be a programmer to write shell scripts. **Reality:** Shell scripting is more like writing a to-do list for the computer. You don't need to know programming theory — just understand the commands you already use, and learn a few rules about how to organise them in a file. (Many beginners come from zero IT background and feel intimidated by the word 'scripting'. They assume it's like Java or Python, but shell scripting is fundamentally about automating command-line tasks.)
- **Misconception:** Spaces don't matter in shell scripts; the computer figures out what you mean. **Reality:** Spaces are critical. For example, 'if [ $x -eq 5 ]' works, but 'if [$x -eq 5]' or 'if[ $x -eq 5 ]' fails. The space after the opening bracket and before the closing bracket is mandatory. (In everyday language, extra spaces don't matter. But the shell is extremely literal. The square bracket is actually a command, and the shell expects spaces to separate the command from its arguments.)
- **Misconception:** A script always runs in the same directory where it's saved. **Reality:** A script runs in the current working directory of the user who executes it, not where the script file is located. If Sarah is in /home/sarah and runs /scripts/log.sh, the script's working directory is /home/sarah, not /scripts. (This confuses beginners because they assume the script's location determines where file operations happen. They often write scripts that create files or refer to relative paths, then get surprised when files appear in unexpected places.)
- **Misconception:** You can use the same variable names as Linux commands without any issue. **Reality:** It's a bad idea to use variable names like 'ls', 'cd', or 'echo' because they shadow (override) the actual commands. If you write 'ls=5', then later use 'ls' in the script hoping to list files, the shell will try to run '5' instead. (Beginners see variable assignment as harmless storage. They don't realise that the shell checks for command names in a specific order, and a variable with the same name as a command can interfere with command resolution.)
- **Misconception:** If a script has an error, it will stop and show a clear error message explaining how to fix it. **Reality:** The shell often continues running past an error, producing unpredictable results or no output at all. A missing quote might cause the rest of the script to be treated as part of a string, with no error message shown. (New users are used to modern applications that give friendly pop-ups. The shell is old-school; it was designed for experienced users who could spot syntax issues. It often fails silently or with cryptic messages.)
- **Misconception:** You can run any text file as a script just by typing its name. **Reality:** To run a script by name (like ./myscript), the file must have the execute permission set. Without chmod +x, you get 'Permission denied'. You can still run it using 'bash myscript' even without execute permission. (This mistake comes from a misunderstanding of Linux file permissions. New users see that they can open and read the file, and think that's enough to execute it. They don't realise that read and execute are separate permissions.)

## Key takeaways

- A shell script is a plain-text file containing a sequence of Linux commands, saved with a .sh extension by convention.
- Every Bash script must start with the shebang line #!/bin/bash to tell the system which interpreter to use.
- To run a script as a program, you must make it executable with chmod +x scriptname.sh.
- Variables in Bash are assigned with no spaces around the equals sign: name=value, and referenced with a dollar sign: $name.
- Conditionals use if [ condition ]; then commands; fi and the spaces inside the square brackets are mandatory.
- The $? variable holds the exit status of the last command, where 0 means success and any non-zero value means an error.
- Always quote variables with double quotes ("$var") to prevent word splitting when the variable contains spaces.
- Use $((expression)) for integer arithmetic, not regular command syntax.

## FAQ

**Why does my script give 'Permission denied' even though I can read it?**

The file has read permission but not execute permission. Run chmod +x scriptname.sh to add execute permission, then try again.

**What's the difference between running ./script.sh and bash script.sh?**

./script.sh requires the script to have execute permission and uses the interpreter specified in the shebang line. bash script.sh explicitly runs the script using the Bash interpreter and does not require the script to be executable.

**Why does my variable not work inside an if statement?**

You probably forgot the dollar sign when referencing the variable. Use if [ $myvar -eq 5 ] not if [ myvar -eq 5 ]. Also check that there are no spaces around the equals sign in the variable assignment.

**How do I pass arguments to a shell script?**

Arguments are accessed using $1, $2, etc. $0 is the script name, $# is the number of arguments, and $@ is all arguments as a list. For example, to use the first argument: echo 'Hello, $1'.

**What does the shebang line #!/bin/bash do?**

It tells the operating system which interpreter to use to run the script. In this case, it says to use the Bash shell located at /bin/bash. Without it, the system may use a different shell or fail.

**Can I run a script without making it executable?**

Yes, by using the bash command: bash scriptname.sh. This invokes the Bash interpreter directly and does not require the file to have execute permission set.

**Why is my for loop not iterating correctly?**

Check that you used the correct syntax: for var in list; do commands; done. Common mistakes are missing the semicolon before 'do', missing 'do', or missing 'done'. Also ensure the list items are separated by spaces.

## Check your understanding

1. **What is the purpose of the shebang line #!/bin/bash in a shell script?**

   Answer: It tells the operating system which interpreter (Bash) to use when executing the script.

2. **Why does the command if [$x -eq 5] fail, and how should it be written correctly?**

   Answer: It fails because spaces are missing between the brackets and the condition. The correct form is if [ $x -eq 5 ].

3. **How do you make a script file executable, and what command do you run it with?**

   Answer: Use chmod +x scriptname.sh to make it executable, then run it with ./scriptname.sh.

4. **What does the variable $? contain in a shell script?**

   Answer: It contains the exit status of the last executed command; 0 means success, and any non-zero value indicates an error.

5. **Write the correct way to assign the value '5' to a variable named 'count' and then use it in an echo statement.**

   Answer: Assignment: count=5 (no spaces). Use: echo $count or echo "$count".

---

Interactive version with quiz and diagrams: https://courseiva.com/learn/linux-plus/basic-shell-scripting
