Introduction to Shell Scripting

A Beginner's Guide
Shell scripting is a powerful way to automate tasks in Linux or Unix-like systems. Whether you're managing servers, processing files, or scheduling tasks, shell scripts can save time and reduce errors. This article introduces shell scripting in simple terms, explaining why it's useful and covering key concepts with practical examples.
Why Use Shell Scripting?
Shell scripting allows you to automate repetitive tasks, manage system operations, and execute commands efficiently. Here are some reasons why shell scripting is valuable:
Automation: Automate tasks like file backups, system monitoring, or software installation.
Time-Saving: Run multiple commands with a single script instead of typing them manually.
Consistency: Ensure tasks are performed the same way every time, reducing human error.
Flexibility: Combine commands, logic, and functions to handle complex workflows.
System Management: Manage servers, check disk usage, or schedule jobs with ease.
For example, instead of manually zipping and moving old log files every week, a shell script can do it automatically at 3 AM using a scheduler like crontab
.
What is a Shell Script?
A shell script is a text file containing a series of commands that the shell (a command-line interpreter like Bash) executes. You write commands just as you would type them in a terminal, but the script runs them in sequence.
To create a basic shell script:
Create a file (e.g.,
myscript.sh
).Add a shebang line at the top:
#!/bin/bash
.Write your commands.
Make the script executable:
chmod +x
myscript.sh
.Run it:
./
myscript.sh
.
Key Concepts in Shell Scripting
Let’s explore the fundamental building blocks of shell scripting with simple explanations and examples.
1. Special Variables
Shell scripts come with built-in variables that provide useful information without needing to define them. Here are some common ones:
$0
: Name of the script (e.g.,myscript.sh
).$1
,$2
, ...: Arguments passed to the script (e.g.,./
myscript.sh
arg1 arg2
sets$1
toarg1
).$@
: All arguments passed to the script.$#
: Number of arguments passed.$PWD
: Current working directory.$HOME
: Home directory of the user running the script.$USER
: Username of the user running the script.$$
: Process ID (PID) of the current script.$!
: PID of the last background command.
Example: Create a script to display script details.
#!/bin/bash
echo "Script Name: $0"
echo "First Argument: $1"
echo "All Arguments: $@"
echo "Number of Arguments: $#"
echo "Current Directory: $PWD"
echo "User: $USER"
Run it: ./
myscript.sh
install mysql
Output:
Script Name: myscript.sh
First Argument: install
All Arguments: install mysql
Number of Arguments: 2
Current Directory: /home/user
User: user
2. Conditions
Conditions allow scripts to make decisions based on whether a condition is true or false. The if
statement is commonly used.
Syntax:
if [ condition ]; then
# Commands if condition is true
else
# Commands if condition is false
fi
Operators:
-gt
: Greater than-lt
: Less than-eq
: Equal-ne
: Not equal
Example: Check if a number is less than 10.
#!/bin/bash
number=$1
if [ $number -lt 10 ]; then
echo "Number $number is less than 10"
else
echo "Number $number is not less than 10"
fi
Run it: ./check_
number.sh
5
Output:
Number 5 is less than 10
Example (Root Access Check): Ensure a script runs with root privileges.
#!/bin/bash
if [ $USER == "root" ]; then
echo "Installing MySQL..."
# Installation commands here
else
echo "Error: Please run as root."
exit 1
fi
The exit 1
command stops the script with a failure status (non-zero). A successful exit uses exit 0
.
3. Functions
Functions group reusable code, making scripts modular. You define a function once and call it multiple times with different inputs.
Syntax:
function_name() {
# Commands
}
Example: A function to install software.
#!/bin/bash
install_software() {
echo "Installing $1..."
# Installation commands here
}
install_software "mysql"
install_software "nginx"
install_software "python3"
Run it: ./
install.sh
Output:
Installing mysql...
Installing nginx...
Installing python3...
Functions can take arguments, just like scripts, using $1
, $2
, etc., within the function.
4. Loops
Loops allow you to repeat tasks. Common loop types are for
and while
.
For Loop:
for item in list; do
# Commands
done
Example: Loop through arguments.
#!/bin/bash
for item in $@; do
echo "Processing: $item"
done
Run it: ./
loop.sh
mysql nginx python3
Output:
Processing: mysql
Processing: nginx
Processing: python3
While Loop:
while [ condition ]; do
# Commands
done
Example: Count from 1 to 5.
#!/bin/bash
count=1
while [ $count -le 5 ]; do
echo "Count: $count"
((count++))
done
Output:
Count: 1
Count: 2
Count: 3
Count: 4
Count: 5
5. Redirections
Redirections control where input and output go. Shell scripts use file descriptors to handle output:
File descriptor
1
: Standard output (stdout), typically for successful command output.File descriptor
2
: Standard error (stderr), typically for error messages.>
: Redirects output to a file (overwrites).>>
: Appends output to a file.<
: Takes input from a file.
Note: The variables $1
, $2
, etc., are not used for redirections; they represent arguments passed to the script or function.
Examples:
Redirect stdout to a file:
ls -l 1> output.log
This saves the successful output of
ls -l
tooutput.log
.Redirect stderr to a file:
ls nonexistent 2> error.log
This saves the error message to
error.log
.Combine stdout and stderr: To store both success and failure output in a single file:
ls existing_file nonexistent_file &> combined.log
Or:
ls existing_file nonexistent_file > combined.log 2>&1
Here,
2>&1
redirects stderr to wherever stdout is going.Capture both in a variable:
output=$(ls existing_file nonexistent_file 2>&1) echo "Captured output: $output"
This stores both stdout and stderr in the
output
variable.Display and save output: To show output on the screen and save it to a file:
ls existing_file nonexistent_file &> >(tee combined.log)
Check exit status: Use
$?
to determine if a command succeeded (0) or failed (non-zero):ls nonexistent_file &> output.log if [ $? -eq 0 ]; then echo "Command succeeded, output in output.log" else echo "Command failed, check output.log for details" fi
6. Colors in Shell
You can add colors to script output for better readability using escape codes.
Syntax: \e[<code>m
31
: Red32
: Green33
: Yellow
Example:
#!/bin/bash
echo -e "\e[31mError: Something went wrong!\e[0m"
echo -e "\e[32mSuccess: Task completed.\e[0m"
The \e[0m
resets the color.
7. Calling Other Scripts
You can call one script from another in two ways:
Using
./
script.sh
: Runs the script in a new process. Variables from the parent script are not accessible.Using
source ./
script.sh
: Runs the script in the same process, allowing variable sharing.
Example:
# script1.sh
#!/bin/bash
MY_VAR="Hello"
source ./script2.sh
echo "Back in script1: $SHARED_VAR"
# script2.sh
#!/bin/bash
echo "In script2: $MY_VAR"
SHARED_VAR="World"
Run: ./
script1.sh
Output:
In script2: Hello
Back in script1: World
8. Practical Example: Backup Script
Let’s combine these concepts into a script that zips and moves log files older than a specified number of days.
#!/bin/bash
source_dir=$1
dest_dir=$2
days=$3
timestamp=$(date +%Y%m%d_%H%M%S)
# Check if directories exist
if [ ! -d "$source_dir" ]; then
echo -e "\e[31mError: Source directory does not exist.\e[0m" 1>&2
exit 1
fi
if [ ! -d "$dest_dir" ]; then
echo -e "\e[31mError: Destination directory does not exist.\e[0m" 1>&2
exit 1
fi
# Function to zip and move logs
backup_logs() {
echo -e "\e[32mZipping logs older than $days days...\e[0m"
find "$source_dir" -name "*.log" -mtime +$days -exec zip app-logs-$timestamp.zip {} \; &> backup.log
mv app-logs-$timestamp.zip "$dest_dir"
find "$source_dir" -name "*.log" -mtime +$days -delete
echo -e "\e[32mBackup complete! Files moved to $dest_dir.\e[0m"
}
# Call function
backup_logs
Run it: ./
backup.sh
/home/user/source /home/user/dest 14
This script:
Takes source and destination directories and days as arguments.
Checks if directories exist using conditions.
Uses a function to zip log files older than the specified days, redirecting both stdout and stderr to
backup.log
.Moves the zip file to the destination and deletes old logs.
Uses colors for better output readability.
9. Scheduling with Crontab
To automate the backup script, use crontab
to schedule it during non-business hours (e.g., 3 AM daily).
Crontab Entry:
0 3 * * * /bin/bash /home/user/backup.sh /home/user/source /home/user/dest 14
This runs the script daily at 3 AM.
10. Sending Emails
You can send emails from a script using tools like msmtp
.
Example:
#!/bin/bash
{
echo "To: info@example.com"
echo "Subject: Disk Usage Alert"
echo "Content-Type: text/html"
echo ""
echo "Disk usage exceeds 70%."
} | msmtp info@example.com
This sends an email if, for example, disk usage exceeds 70% (checked using df -hT
).
Conclusion
Shell scripting is a versatile skill for automating tasks, managing systems, and improving efficiency. By mastering special variables, conditions, functions, loops, redirections, and scheduling, you can create powerful scripts for real-world tasks like backups, installations, or monitoring. Start small, experiment with the examples above, and soon you’ll be writing scripts to simplify your workflow!
Subscribe to my newsletter
Read articles from ESHNITHIN YADAV directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
