Share this content:
Are you tired of manually performing repetitive tasks on your Linux system? Do you want to streamline your workflow and automate complex system administration tasks? If so, then this is why you need to learn Bash scripting.
Learn Bash scripting
Bash scripting is a powerful tool for automating tasks on a Linux system, from simple text processing to complex system administration tasks. By mastering Bash scripting, you can become a more efficient and effective developer or system administrator, and streamline your workflows to save time and effort.
But where do you start? With so much to learn, it can be challenging to know where to begin. That’s where our comprehensive guide to Bash scripting comes in. Our guide covers the basics of Bash scripting and provides numerous examples to help you get started. We cover the essential concepts of variables, conditionals, loops, and functions and show how to use these constructs to write simple and complex Bash scripts.
Whether you’re new to Bash scripting or looking to take your skills to the next level, our guide has something for you. We cover advanced topics like command substitution, file I/O, and process management, which can help you write more sophisticated scripts to automate complex tasks.
With our guide, you’ll learn the skills you need to automate your workflows and become a more efficient and effective developer or system administrator. So what are you waiting for? Dive into our guide and start mastering Bash scripting today!
- Part 1: Introduction to Linux Shell Scripting
- Part 2: Basic Linux Shell Scripting
- Part 3: Advanced Linux Shell Scripting
- Reading and Writing Files
- Regular Expressions
- Handling Errors
- Command Line Arguments
- String Manipulation
- Arrays
- File Operations
- Networking
- API Requests
- User Input
- Debugging
- Math Operations
- Environment Variables
- Exit Status
- File Operations
- Process Management
- Script Arguments
- Example Script: Automating System Backup
- Example Script: Sending Email Based on API Response
- Conclusion
Part 1: Introduction to Linux Shell Scripting
What is Linux Shell Scripting?
Linux Shell Scripting is the process of creating and running scripts written in shell language, which is used to automate repetitive tasks on a Linux system. Shell scripts are files that contain a sequence of commands that can be executed by the shell.
Why use Shell Scripting?
Why use Shell Scripting? Shell scripting is useful because it allows you to automate complex tasks that would otherwise be time-consuming to perform manually. It also allows you to create custom commands and tools that can simplify system administration tasks.
Part 2: Basic Linux Shell Scripting
Print Hello World
Code example, but first, create a file with your preferred text editor and name it “hello_world.sh“:
#!/bin/bash
echo "Hello World"
Explanation:
The above code creates a script that will print the phrase “Hello World” to the console. The first line of the code (#!/bin/bash) tells the system that this is a bash script. The second line (echo “Hello World”) tells the script to print the phrase “Hello World” to the console.
To execute that script you have to type from the console “sh hello_world.sh”
Variables and Data Types
Code example:
#!/bin/bash
name="John"
age=30
echo "My name is $name and I am $age years old."
Explanation:
The above code creates a script that sets two variables (name and age) and then prints a message that includes the values of those variables. The first line of the code (#!/bin/bash) tells the system that this is a bash script. The second and third lines set the variables “name” and “age” to “John” and “30”, respectively. The fourth line uses the “echo” command to print a message that includes the values of the “name” and “age” variables.
Conditional Statements
Code example:
#!/bin/bash
if [ "$1" = "hello" ]; then
echo "Hello World"
else
echo "Goodbye"
fi
Explanation:
The above code creates a script that checks the first argument passed to it. If the first argument is “hello”, it prints “Hello World” to the console. If the first argument is anything else, it prints “Goodbye”. The “if” statement checks whether the first argument is “hello” using the “[ ]” syntax. The “then” statement is executed if the condition is true, and the “else” statement is executed if the condition is false. The “fi” statement marks the end of the “if” statement.
Code example:
#!/bin/bash
x=5
if [ $x -gt 0 ]; then
echo "The variable x is positive."
elif [ $x -lt 0 ]; then
echo "The variable x is negative."
else
echo "The variable x is zero."
fi
Explanation:
The above code uses the “if” statement to check the value of the variable “x”. If “x” is greater than 0, the script prints a message saying that “x” is positive. If “x” is less than 0, the script prints a message saying that “x” is negative. If “x” is equal to 0, the script prints a message saying that “x” is zero.
Code example:
#!/bin/bash
echo "Please enter a number between 1 and 5: "
read num
if [ $num -lt 1 ] || [ $num -gt 5 ]; then
echo "Number is out of range."
else
for i in $(seq 1 $num); do
echo "Number: $i"
done
fi
Explanation:
The above code uses a conditional statement to check if the number entered by the user is between 1 and 5, inclusive. If the number is out of range, the script outputs an error message. Otherwise, it uses a “for” loop to print the numbers from 1 up to the number entered by the user.
The conditional statement is constructed using the “if” keyword, followed by the test condition in square brackets. The “||” operator is used to indicate a logical OR operation. The “then” keyword is used to start the block of code that should be executed if the condition is true. The “else” keyword is used to start the block of code that should be executed if the condition is false.
Loops
Code example:
#!/bin/bash
for i in {1..5}; do
echo "Number: $i"
done
Explanation:
The above code creates a script that uses a “for” loop to print the numbers 1 through 5 to the console. The “for” loop iterates through the numbers 1 through 5 using the “{1..5}” syntax. The “echo” command is used to print the current number to the console.
Functions
Code example:
#!/bin/bash
greet() {
echo "Hello, $1"
}
greet "John"
greet "Jane"
Explanation:
The above code creates a function called “greet” that takes a single argument (a name) and prints a greeting message to the console. The function is called twice, passing in different names each time. The output of the script will be two greeting messages, one for “John” and one for “Jane”.
Command Line Arguments
Code example:
#!/bin/bash
echo "The first argument is: $1"
echo "The second argument is: $2"
echo "All arguments are: $@"
Explanation:
The above code creates a script that prints out the first two arguments passed to it, as well as all of the arguments. The “$1” and “$2” variables are used to access the first two arguments, respectively. The “$@” variable is used to access all of the arguments.
Part 3: Advanced Linux Shell Scripting
Reading and Writing Files
Code example:
#!/bin/bash
echo "Hello World" > myfile.txt
echo "The contents of the file are:"
cat myfile.txt
Explanation:
The above code creates a script that writes the phrase “Hello World” to a file called “myfile.txt” using the “>” operator. The “cat” command is used to read the contents of the file and print them to the console.
Regular Expressions
Code example:
#!/bin/bash
if [[ "Hello World" =~ ^Hello.*$ ]]; then
echo "The string starts with 'Hello'"
else
echo "The string does not start with 'Hello'"
fi
Explanation:
The above code creates a script that checks whether the string “Hello World” starts with the word “Hello” using a regular expression. The “=~” operator is used to apply the regular expression to the string. The “^” and “.*” characters are used to match the beginning of the string and any characters after the word “Hello”, respectively.
Handling Errors
Code example:
#!/bin/bash
if [ ! -f myfile.txt ]; then
echo "Error: file does not exist"
exit 1
fi
echo "The file exists"
Explanation:
The above code creates a script that checks whether a file called “myfile.txt” exists. If the file does not exist, it prints an error message to the console and exits the script with a status code of 1. If the file exists, it prints a message to the console.
Explanation:
The above code creates a function called “greet” that takes a single argument (a name) and prints a greeting message to the console. The function is called twice, passing in different names each time. The output of the script will be two greeting messages, one for “John” and one for “Jane”.
Command Line Arguments
Code example:
#!/bin/bash
echo "The first argument is: $1"
echo "The second argument is: $2"
echo "All arguments are: $@"
Explanation:
The above code creates a script that prints out the first two arguments passed to it, as well as all of the arguments. The “$1” and “$2” variables are used to access the first two arguments, respectively. The “$@” variable is used to access all of the arguments.
String Manipulation
Code example:
#!/bin/bash
name="John Doe"
echo "The first name is: ${name%% *}"
echo "The last name is: ${name#* }"
Explanation:
The above code creates a script that manipulates a string containing a first and last name. The “${name%% }” syntax is used to remove the last name from the string, leaving only the first name. The “${name# }” syntax is used to remove the first name from the string, leaving only the last name.
Arrays
Code example:
#!/bin/bash
my_array=(apple banana cherry)
echo "The first element is: ${my_array[0]}"
echo "The second element is: ${my_array[1]}"
echo "The third element is: ${my_array[2]}"
Explanation:
The above code creates an array called “my_array” containing three elements. The elements are accessed using their index number within curly braces (e.g. “${my_array[0]}”). The output of the script will be three lines, each printing out one element of the array.
File Operations
Code example:
#!/bin/bash
if [ -f /etc/passwd ]; then
echo "The file /etc/passwd exists."
else
echo "The file /etc/passwd does not exist."
fi
Explanation:
The above code checks whether the file “/etc/passwd” exists using the “-f” operator, which checks if the file exists and is a regular file. If the file exists, a message is printed to the console. If it does not exist, a different message is printed.
Networking
Code example:
#!/bin/bash
ping -c 5 google.com
Explanation:
The above code sends five ICMP echo requests to the Google website using the “ping” command. The “-c” option is used to specify the number of packets to send. The output of the script will be the ping statistics, including the round-trip time for each packet.
API Requests
Code example:
#!/bin/bash
curl -X GET "https://jsonplaceholder.typicode.com/posts/1"
Explanation:
The above code sends a GET request to the JSONPlaceholder API to retrieve information about a post with an ID of 1. The “curl” command is used to make the request. The output of the script will be the JSON response from the API.
Code example:
#!/bin/bash
curl -s https://api.github.com/users/USERNAME | jq '.name'
Explanation:
The above code demonstrates how to make an API request using the “curl” command and parse the JSON response using the “jq” command. The “curl” command is used to fetch the user profile information for a given GitHub username, and the “-s” flag is used to suppress the progress meter and other extraneous output.
The response from the API is in JSON format, which can be difficult to read and work with directly. The “jq” command is used to parse the response and extract only the “name” field from the JSON object. The resulting output is a string containing the name of the GitHub user associated with the given username.
Code example:
#!/bin/bash
echo "This is the body of the email." | mail -s "Subject of the Email" user@example.com
Explanation:
The above code sends an email to the user “user@example.com” with a subject line of “Subject of the Email” and a body containing the text “This is the body of the email.” The “mail” command is used to send the email.
User Input
Code example:
#!/bin/bash
echo "What is your name?"
read name
echo "Hello, $name!"
Explanation:
The above code prompts the user to enter their name using the “echo” command, then reads in the user’s input using the “read” command and stores it in a variable called “name”. Finally, the script outputs a personalized message that includes the user’s name.
Debugging
Code example:
#!/bin/bash
set -x
echo "Hello, world!"
set +x
Explanation:
The above code enables debugging mode using the “set -x” command, which causes each line of the script to be printed to the console as it is executed. The “echo” command prints the text “Hello, world!” to the console. The “set +x” command disables debugging mode.
Math Operations
Code example:
#!/bin/bash
x=5
y=2
echo "The sum is: $(($x + $y))"
echo "The difference is: $(($x - $y))"
echo "The product is: $(($x * $y))"
echo "The quotient is: $(($x / $y))"
Explanation:
The above code defines two variables “x” and “y” with the values 5 and 2, respectively. The script performs several mathematical operations using the variables and the appropriate operators. The results are printed to the console.
Environment Variables
Code example:
#!/bin/bash
echo "The current working directory is: $PWD"
echo "The username is: $USER"
echo "The home directory is: $HOME"
Explanation:
The above code accesses several environment variables using the “$PWD”, “$USER”, and “$HOME” variables, which correspond to the current working directory, the current user’s username, and the user’s home directory, respectively. The script outputs each variable in turn.
Exit Status
Code example:
#!/bin/bash
ls /fake/directory
echo "The exit status of the previous command is: $?"
Explanation:
The above code uses the “ls” command to list the contents of a non-existent directory. Since the directory does not exist, the “ls” command fails and returns a non-zero exit status. The script uses the “$?” variable to retrieve the exit status of the previous command and outputs it to the console.
File Operations
Code example:
#!/bin/bash
echo "Creating a new file..."
touch newfile.txt
echo "Writing to the new file..."
echo "This is a new file." > newfile.txt
echo "The contents of the file are:"
cat newfile.txt
echo "Deleting the new file..."
rm newfile.txt
Explanation:
The above code creates a new file called “newfile.txt” using the “touch” command. The script then writes the text “This is a new file.” to the file using the “echo” command and the “>” operator. The script uses the “cat” command to output the contents of the file to the console. Finally, the script deletes the file using the “rm” command.
Process Management
Code example:
#!/bin/bash
echo "Starting background process..."
sleep 10 &
echo "Waiting for background process to finish..."
wait
echo "Background process has finished."
Explanation:
The above code uses the “sleep” command to start a background process that waits for 10 seconds. The “&” operator runs the process in the background. The “wait” command waits for the background process to finish before continuing, and the script outputs a message when the background process has completed.
Script Arguments
Code example:
#!/bin/bash
echo "The script name is: $0"
echo "The first argument is: $1"
echo "The second argument is: $2"
echo "All arguments are: $@"
echo "The number of arguments is: $#"
Explanation:
The above code uses special variables to access the arguments passed to the script. The variable “$0” holds the name of the script itself. The variables “$1” and “$2” hold the first and second arguments, respectively. The variable “$@” holds all arguments passed to the script, and the variable “$#” holds the number of arguments passed.
Example Script: Automating System Backup
To bring everything together, let’s walk through an example Bash script that automates the process of backing up important files on a Linux system.
#!/bin/bash
# Backup directory
BACKUP_DIR=/home/user/backups
# Create backup directory if it doesn't exist
if [ ! -d "$BACKUP_DIR" ]; then
mkdir "$BACKUP_DIR"
fi
# Archive file name
ARCHIVE_FILE="backup_$(date +%Y%m%d).tar.gz"
# Paths to important files to back up
FILE_1="/etc/nginx/nginx.conf"
FILE_2="/etc/ssh/sshd_config"
# Create archive of important files
tar czf "$BACKUP_DIR/$ARCHIVE_FILE" "$FILE_1" "$FILE_2"
# Upload archive to remote server
curl -X POST -F "file=@$BACKUP_DIR/$ARCHIVE_FILE" https://example.com/api/backup
# Clean up old backups
find "$BACKUP_DIR" -type f -name 'backup_*' -mtime +7 -exec rm {} \;
Explanation:
This script automates the process of backing up important configuration files on a Linux system, archiving them, and uploading the archive to a remote server for safekeeping. The script starts by defining a backup directory where the archives will be stored. If the directory doesn’t exist, the script creates it. Next, the script generates a unique archive filename based on the current date, using the “date” command and the “+%Y%m%d” format string to generate a filename with the current year, month, and day. The script then defines the paths to the important files to back up, in this case, the Nginx configuration file and the SSH daemon configuration file. The “tar” command is used to create an archive of the specified files, with the resulting archive stored in the backup directory with the generated filename. The “curl” command is used to upload the archive to a remote server, with the “-F” flag used to specify the file to upload and the URL of the remote server API endpoint. Finally, the script cleans up old backups that are older than 7 days, using the “find” command to locate all files in the backup directory with names that match the “backup_*” pattern and are older than 7 days, and the “exec” option to remove them.
Example Script: Sending Email Based on API Response
Let’s walk through another example Bash script that uses the “curl” command to send an API request and sends an email based on the response.
#!/bin/bash
# API endpoint to check server status
SERVER_STATUS_URL="https://example.com/api/server-status"
# Email configuration
EMAIL_TO="admin@example.com"
EMAIL_FROM="noreply@example.com"
EMAIL_SUBJECT="Server Status"
EMAIL_BODY="The server is currently "
# Get server status from API
SERVER_STATUS=$(curl -s "$SERVER_STATUS_URL")
# Check server status and set email body accordingly
if [ "$SERVER_STATUS" == "online" ]; then
EMAIL_BODY="$EMAIL_BODY online"
else
EMAIL_BODY="$EMAIL_BODY offline"
fi
# Send email
echo "$EMAIL_BODY" | mail -s "$EMAIL_SUBJECT" -r "$EMAIL_FROM" "$EMAIL_TO"
Explanation:
This script uses the “curl” command to send an API request to check the status of a remote server. The response is stored in the “SERVER_STATUS” variable. The script then checks the server status and sets the email body accordingly. In this case, if the server is online, the email body will be “The server is currently online,” and if it’s offline, the email body will be “The server is currently offline.” Finally, the script uses the “mail” command to send an email with the configured email subject, body, from address, and to address. Note: The “mail” command requires a working email server configured on the system.
Conclusion
Bash scripting is a powerful tool for automating tasks on a Linux system, from simple text processing to complex system administration tasks. By mastering Bash scripting, you can become a more efficient and effective developer or system administrator, and streamline your workflows to save time and effort. With the examples and explanations in this guide, you should have a solid foundation for creating your own Bash scripts and automating tasks on your Linux system.
If I had to highlight the 20% most important things to know about shell scripting, they would be:
- Command execution: Understanding how to execute commands in a shell script is essential. You should know how to use basic commands like echo, cat, grep, awk, and sed, and how to execute shell commands with pipes and redirects.
- Variables: Shell scripting uses variables to store and manipulate data. You should know how to declare and use variables, including environment variables, and how to manipulate strings and numbers.
- Conditional statements: Conditional statements allow you to control the flow of your shell script. You should know how to use if, elif, and else statements to make decisions based on the value of variables.
- Loops: Loops allow you to repeat a section of code multiple times. You should know how to use for loops, while loops, and until loops, and how to control the loop’s behavior with break and continue statements.
- Functions: Functions allow you to break your script into reusable blocks of code. You should know how to define and call functions, and how to pass arguments to functions.
- File I/O: File input/output (I/O) is a crucial part of shell scripting. You should know how to read and write files using commands like cat, echo, and tee, and how to redirect input and output with <, >, and >>.
- Process management: Shell scripts can interact with running processes on a system. You should know how to start and stop processes, and how to capture their output.
- Debugging: Debugging is an essential skill for shell scripting. You should know how to use debugging techniques like set -x and set -e to identify errors and trace the execution of your script.
- Scripting best practices: Writing shell scripts that are easy to read and maintain is essential. You should follow best practices like using comments, naming conventions, and error handling to make your scripts more robust and reliable.
- Automation: Finally, automation is the ultimate goal of shell scripting. You should know how to use your shell scripts to automate repetitive tasks and streamline your workflow, freeing up time for more critical tasks.