In Part 1 of this tutorial series, we introduced the basics of Bash scripting on Linux. We learned how to write simple scripts, use variables, loops, conditionals, and even schedule tasks with cron. Now, let’s build on that knowledge with some beginner-friendly, yet more advanced, techniques.

In this article, we’ll explore:

  • Functions: Reusable blocks of code to keep your scripts clean and organized.
  • Command-line arguments: How to make your scripts accept input directly from the terminal.
  • Basic error handling: Checking for problems so your scripts can deal with them gracefully.
  • Simple logging: How to capture the output of your script for future reference.

Don’t worry, we’ll keep things simple and explain everything along the way. By the end of this guide, you'll feel more confident about writing Bash scripts that are a little more dynamic and smarter!


1. Using Functions to Keep Things Organized

As your scripts get bigger, you’ll notice you’re doing similar things in different parts of the script. That’s where functions come in handy. A function is a way to group commands together and reuse them throughout your script.

Think of it like a recipe you can call anytime you need it!

How to Create a Function

The syntax for creating a function is simple:

Bash:
function_name() {
# Your commands here
}

Let’s say you want to greet the user. Instead of writing the same command over and over again, you can create a function for it:

Bash:
#!/bin/bash
# Define a function to greet the user
greet_user() {
echo "Hello, $1! Welcome to Bash scripting!"
}

# Call the function
greet_user "Alice"
greet_user "Bob"

In this script:

  • We define the function greet_user that prints a greeting.
  • $1 represents the first argument passed to the function (in this case, the user’s name).

When you run the script, you’ll see:

Hello, Alice! Welcome to Bash scripting!
Hello, Bob! Welcome to Bash scripting!

You can pass different names to the function, making it reusable. Functions are super helpful when you need to use the same logic multiple times in your script.


2. Command-Line Arguments: Making Your Script Interactive

Wouldn’t it be great if you could pass information to your script when you run it, instead of hardcoding values into it? Bash lets you do that with command-line arguments.

What Are Command-Line Arguments?

Command-line arguments allow you to pass data to your script from the terminal. For example, instead of telling the script what to do beforehand, you give it instructions when you run it.

Here’s an example script that accepts a name and a favorite color as arguments:

Bash:
#!/bin/bash
# The first argument is the name, the second is the favorite color
greet_user() {
name=$1
color=$2

echo "Hello, $name! Your favorite color is $color."

Let’s say you save this script as greet.sh. You can run it from the terminal like this:

./greet.sh Alice blue

And the output will be:

Hello, Alice! Your favorite color is blue.

Accessing Command-Line Arguments

  • $1, $2, $3, etc., represent the first, second, third argument, and so on.
  • $0 represents the script's name.
  • $# gives the total number of arguments passed.

This makes your scripts much more flexible. Now, instead of changing the script every time you want to run it with different inputs, you just pass new arguments directly from the terminal!


3. Basic Error Handling: Dealing with Problems

Not everything goes smoothly in scripting, especially when dealing with files or commands that might fail. That's why it’s important to include error handling in your script. You don’t want your script to keep running if something goes wrong!

Checking the Exit Status of a Command

Every command in Bash returns an exit status:

  • 0 means the command was successful.
  • Any number other than 0 means something went wrong.

We can use this exit status to handle errors. For example, let’s check if a file exists before trying to copy it:

bash:
#!/bin/bash

# Check if the file exists before copying
if [ -f "$1" ]; then
cp "$1" /backup/
echo "File copied successfully."
else
echo "Error: $1 does not exist."
exit 1 # Exit with an error code
fi

Here’s how this script works:

  1. The if [ -f "$1" ] checks if the file exists (-f checks for a file).
  2. If the file exists, it copies the file.
  3. If the file doesn’t exist, it prints an error message and exits the script with an error code (1).

If you run the script like this:

./copy.sh myfile.txt

And myfile.txt doesn’t exist, you’ll see:

Error: myfile.txt does not exist.

Adding error handling like this helps your script avoid continuing with bad data or broken commands.


4. Simple Logging: Keeping Track of What Happens

Logging is a way to record what your script does. Instead of relying on memory or watching the terminal, you can save everything that happens into a file for future reference.

Redirecting Output to a Log File

You can easily redirect the output of your script to a file. Here’s how:

Bash:
#!/bin/bash
# Redirect output to a log file
exec > script.log 2>&1

echo "This is a log of everything that happens in this script."
date # Logs the current date and time
echo "Done!"

Let’s break it down:

  • exec > script.log 2>&1 redirects all output (both standard output and error messages) to a file called script.log.
  • Now, anything the script prints will go to the log file instead of the terminal.

After running the script, open script.log, and you’ll see:

This is a log of everything that happens in this script.
Tue Oct 17 10:00:00 UTC 2024
Done!

Logging is incredibly useful for tracking what happens in long-running or automated scripts.


5. Combining It All: A Simple Example

Now, let’s combine everything we’ve learned so far into one simple script. This script will:

  1. Accept a filename as an argument.
  2. Check if the file exists.
  3. If it exists, copy it to a backup directory and log the action.
  4. If it doesn’t exist, log an error.

Here’s the script:

bash:
#!/bin/bash

# Redirect all output to a log file
exec > backup.log 2>&1

# Check if exactly one argument (a file name) is passed
if [ $# -ne 1 ]; then
echo "Usage: $0 filename"
exit 1
fi

# Check if the file exists
if [ -f "$1" ]; then
# Copy the file to the backup directory
cp "$1" /backup/
echo "$(date): $1 copied to /backup/"
else
echo "$(date): Error - $1 does not exist."
exit 1
fi

If you run this script and provide a valid file, it will copy the file to /backup/ and log the success message. If the file doesn’t exist, it will log an error.


Conclusion

In this article, we’ve built on the basics of Bash scripting by introducing functions, command-line arguments, error handling, and logging. These are essential skills that will help you write more effective and robust scripts.

As you practice these new techniques, you’ll see how much more dynamic and powerful your scripts can become. Whether you’re automating backups, processing files, or just learning to make the most out of the Linux command line, you now have some new tools to get the job done!

In the next article, we’ll dive deeper into more intermediate scripting techniques, but for now, keep practicing with what you’ve learned here. Happy coding!

Share To: