Skip to main content

Shell Scripting Basics

Now that you're comfortable with Linux command-line operations and system administration tasks, it's time to learn how to automate them! Shell scripting allows you to combine multiple commands into reusable programs, saving time and reducing errors.

Learning Goals

  • Understand what shell scripts are and why they're useful
  • Create and execute your first shell script
  • Use variables, conditionals, and loops in scripts
  • Make scripts executable and portable
  • Handle user input and script arguments

What is Shell Scripting?

Shell scripting is writing a series of shell commands in a text file that can be executed as a program. Think of it as creating your own custom commands by combining existing ones with programming constructs.

Shell scripts are perfect for:

  • Automating repetitive tasks
  • Creating custom system administration tools
  • Batch processing files
  • Setting up development environments

Your First Shell Script

Let's create a simple "Hello World" script to understand the basics.

hello.sh
#!/bin/bash
# This is my first shell script
echo "Hello, World!"
echo "Today is: $(date)"
echo "Current user: $USER"
tip

The first line #!/bin/bash is called a "shebang" and tells the system which interpreter to use. Always include it at the beginning of your scripts.

To run this script:

# Make it executable
chmod +x hello.sh

# Run it
./hello.sh

Variables and User Input

Variables store data that can be used throughout your script.

variables.sh
#!/bin/bash
# Variable assignment
SCRIPT_NAME="system_info"
VERSION="1.0"

# Using variables
echo "Script: $SCRIPT_NAME"
echo "Version: $VERSION"

# Reading user input
echo -n "Enter your name: "
read USERNAME
echo "Hello, $USERNAME!"

# Command substitution
CURRENT_DIR=$(pwd)
echo "You are in: $CURRENT_DIR"

Conditional Statements

Make your scripts smarter with if statements that execute code based on conditions.

check_disk.sh
#!/bin/bash
# Check disk usage and warn if low

DISK_USAGE=$(df / | grep / | awk '{ print $5 }' | sed 's/%//g')

echo "Disk usage is: $DISK_USAGE%"

if [ $DISK_USAGE -gt 90 ]; then
echo "WARNING: Disk space is critically low!"
elif [ $DISK_USAGE -gt 80 ]; then
echo "Warning: Disk space is getting low."
else
echo "Disk space is adequate."
fi

# Check if a file exists
FILE="/etc/passwd"
if [ -f "$FILE" ]; then
echo "$FILE exists and is a regular file."
else
echo "$FILE does not exist."
fi

Loops for Repetition

Loops help you perform the same action multiple times.

backup_scripts.sh
#!/bin/bash
# Backup all .sh files in current directory

echo "Backing up shell scripts..."

# Loop through all .sh files
for file in *.sh; do
if [ -f "$file" ]; then
backup_name="${file}.backup"
cp "$file" "$backup_name"
echo "Backed up: $file -> $backup_name"
fi
done

# While loop example
COUNT=1
echo "Counting to 5:"
while [ $COUNT -le 5 ]; do
echo "Count: $COUNT"
((COUNT++))
done

Handling Script Arguments

Make your scripts more flexible by accepting command-line arguments.

file_manager.sh
#!/bin/bash
# Script that handles command-line arguments

SCRIPT_NAME=$0
FIRST_ARG=$1
SECOND_ARG=$2

echo "Script name: $SCRIPT_NAME"
echo "First argument: $FIRST_ARG"
echo "Second argument: $SECOND_ARG"
echo "Total arguments: $#"
echo "All arguments: $@"

# Practical example: create a directory and file
if [ $# -eq 2 ]; then
mkdir -p "$FIRST_ARG"
touch "$FIRST_ARG/$SECOND_ARG"
echo "Created directory '$FIRST_ARG' with file '$SECOND_ARG'"
else
echo "Usage: $0 <directory> <filename>"
fi

Run it with:

./file_manager.sh projects new_script.sh

Functions for Reusable Code

Organize your scripts with functions to avoid repetition.

system_check.sh
#!/bin/bash
# Functions for system monitoring

# Define functions
check_disk() {
echo "=== Disk Usage ==="
df -h | grep -v tmpfs
}

check_memory() {
echo "=== Memory Usage ==="
free -h
}

check_processes() {
echo "=== Top Processes ==="
ps aux --sort=-%cpu | head -6
}

# Main script logic
echo "System Health Check"
echo "==================="

check_disk
echo
check_memory
echo
check_processes
warning

Always test your scripts with different scenarios. A script that works in your home directory might fail in system directories due to permission issues.

Making Scripts Portable

Follow these practices to ensure your scripts work everywhere:

good_practices.sh
#!/bin/bash
# Example of good scripting practices

# Use full paths for critical commands
LS_CMD="/bin/ls"
DATE_CMD="/bin/date"

# Check if commands exist before using them
if ! command -v docker &> /dev/null; then
echo "Error: docker is not installed"
exit 1
fi

# Set strict mode for better error handling
set -euo pipefail

# Use variables for repeated values
BACKUP_DIR="/var/backups"
LOG_FILE="/var/log/my_script.log"

Common Pitfalls

  • Missing shebang: Always start with #!/bin/bash
  • Spaces in variable assignments: Use VAR=value not VAR = value
  • Forgetting to make scripts executable: Use chmod +x script.sh
  • Not quoting variables: Always use quotes like "$VARIABLE"
  • Using wrong comparison operators: -eq for numbers, == for strings
  • Ignoring error handling: Check exit codes with $?
  • Hardcoding paths: Use variables and command substitution instead

Summary

Shell scripting transforms you from a command-line user to a power user who can automate complex tasks. You've learned to create executable scripts, use variables and conditionals, handle user input, work with loops, and organize code with functions. Remember to test thoroughly and follow best practices for reliable, portable scripts.

Quiz

Show quiz
  1. What is the purpose of the shebang (#!/bin/bash) at the beginning of a script?
  2. How do you make a shell script executable?
  3. What's the difference between $VARIABLE and "$VARIABLE" in shell scripting?
  4. Which operator would you use to compare numbers in an if statement?
  5. How can you access the first argument passed to a shell script?

Answers

  1. The shebang specifies which interpreter should execute the script
  2. Using chmod +x scriptname.sh
  3. "$VARIABLE" preserves spaces in the variable's value, while $VARIABLE might break with spaces
  4. Use -eq, -ne, -lt, -gt for numerical comparisons (not ==, !=, etc.)
  5. Through $1 (the first positional parameter)