How-To: Create and Run Shell Scripts on a Raspberry Pi
2024-04-22 | By Maker.io Staff
Image Source: https://pixabay.com/photos/code-programming-hacking-html-web-820275/
This article explores the power and versatility of shell scripting, a fundamental skill for anyone looking to automate tasks and manage system processes on their Raspberry Pi. The article dives into the purpose and benefits of shell scripts and gives a practical example of an automated, scheduled task.
Understanding the Benefits of Shell Scripts
Shell scripts offer numerous benefits that tremendously help reduce the time and effort needed to run commands via the terminal. First, you don’t have to manually type out every command you want to execute, offering significant time savings depending on the number and length of the commands. In addition, automating the execution leaves less room for errors such as typos or forgotten parameters, making command execution faster, more reliable, and repeatable.
Further, many tasks involve remembering multiple commands that you must execute in the correct order. Instead, you could type out the commands in a shell script and then perform all the coherent tasks in the proper order by calling the script using a single, easy-to-remember name.
Common Use-Cases for Automated Shell Scripts
Automating terminal command execution opens the doors to various applications that would otherwise not be possible. For example, you can set up scripts that make your Raspberry Pi react to certain system events, such as shutting down or rebooting, and perform an action.
Using shell scripts, you can also define commands that the Pi should execute periodically, like uploading sensor readings or other data to an API or regularly creating backups of vital files by copying them to an external hard drive. Similarly, shell scripts facilitate batch processing, for example, by applying multiple actions to files on the system.
A shell script can also create files on remote servers or search for and apply updates if they are available at night to ensure that the system is always running the most recent versions of programs.
Prerequisites for Writing Automated Shell Scripts
Luckily, you don’t need to install additional software or tools to harness the power of shell scripts on your Raspberry Pi. All standard operating systems already supply everything that’s required, which is only a text editor. Usually, cron — the tool needed to schedule automated jobs — is pre-installed on most modern Linux distributions, including Raspberry Pi OS. However, before getting started, you should have a solid understanding of the basic Linux commands you want to use.
This screenshot shows an example of a custom shell script in nano
Writing an Example Script
The following more concrete example attempts to mount an external drive, and if that succeeds, it creates a new folder on the external drive using the current date. It then copies all files from the source directory, which can be supplied as a parameter, to the newly created folder on the mounted external drive. Finally, it prints the number of files it copied and the target folder to the console before unmounting the external drive.
Type the following commands to create a new shell script in your pi’s home directory named planned_backup.sh and open it in the nano text editor:
touch /home/pi/planned_backup.sh nano /home/pi/planned_backup.sh
Then, type out the following lines of code. The script starts with the following line that tells the system which script interpreter it should use to execute the code:
#!/bin/bash
The script then defines three variables that are used throughout the entire program:
# Define some constants for easy access external_drive="/dev/sdb1" mount_point="/mnt/external" target_folder="$mount_point/$(date +'%Y-%m-%d')"
The first variable defines the name of the external drive to use as the backup target. Note that you may need to change this value to reflect your external drive’s device in the operating system.
The second one states where the external drive should be mounted in the local file system. Finally, the third variable holds the target folder name. In this example, the target destination consists of the mount_point variable’s value followed by the current date.
Next, the script uses a fork that checks whether you supplied a source folder. If you didn’t, the program uses a default value. Otherwise, the script uses the user-defined value:
# Check if a directory parameter is provided. Otherwise, use a default directory (. means the current directory) if [ -z "$1" ]; then source_directory="." else source_directory="$1" fi
Similarly, the program then uses another if-else block to determine whether the mount point already exists. It does that by checking whether it can access the mount point. If it can’t, the program creates the folder. If that fails, too, the script prints an error message and stops:
# Check if the mount point exists if ! cd "$mount_point"; then if mkdir "$mount_point"; then echo "Created mount point: $mount_point" else echo "Could not create a mount point: $mount_point" exit 1 fi fi
Next, the script attempts to mount the external drive using a similar if construct:
# Mount external drive echo "Mounting external drive..." if ! mount "$external_drive" "$mount_point"; then echo "Error: Failed to mount external drive." exit 1 fi
The program then creates the target folder on the external drive and copies the files from the source directory. While doing that, the script keeps track of the number of files it copied:
# Create the target folder mkdir -p "$target_folder" # Copy files from the source directory to the target folder echo "Copying files from $source_directory to $target_folder..." num_files_copied=$(cp -v "$source_directory"/* "$target_folder" | wc -l)
Finally, the script lets you know how many files it copied before unmounting the drive and deleting the mount point folder, created earlier:
# Output the number of files copied and the target folder echo "Number of files copied: $num_files_copied" echo "Target folder: $target_folder" # Unmount external drive echo "Unmounting external drive..." umount "$mount_point" rmdir "$mount_point"
The following listing contains the whole bash script:
#!/bin/bash # Define some constants for easy access external_drive="/dev/sdb1" mount_point="/mnt/external" target_folder="$mount_point/$(date +'%Y-%m-%d')" # Check if a directory parameter is provided. Otherwise, use a default directory (. means the current directory) if [ -z "$1" ]; then source_directory="." else source_directory="$1" fi # Check if the mount point exists if ! cd "$mount_point"; then if mkdir "$mount_point"; then echo "Created mount point: $mount_point" else echo "Could not create a mount point: $mount_point" exit 1 fi fi # Mount external drive echo "Mounting external drive..." if ! mount "$external_drive" "$mount_point"; then echo "Error: Failed to mount external drive." exit 1 fi # Create the target folder mkdir -p "$target_folder" # Copy files from the source directory to the target folder echo "Copying files from $source_directory to $target_folder..." num_files_copied=$(cp -v "$source_directory"/* "$target_folder" | wc -l) # Output the number of files copied and the target folder echo "Number of files copied: $num_files_copied" echo "Target folder: $target_folder" # Unmount external drive echo "Unmounting external drive..." umount "$mount_point" rmdir "$mount_point"
Once done, use Ctrl + O to save the script and then close nano by using Ctrl + X. Next, make the script executable by typing:
chmod u+x /home/pi/planned_backup.sh
This screenshot shows the result of running the script manually.
Registering a Script for Periodic Execution
Finally, the following commands register the script with cron to make it run daily at 4 AM. The first one opens the cron table:
crontab -e
Adding the following line to the end of the file registers it for periodic execution. Once done, use Ctrl + O to save the table and Ctrl + X to exit nano.
0 4 * * * /home/pi/planned_backup.sh
Assuming that the script is named “planned_backup.sh” and is stored in the /home/pi folder. You can also call the script manually at any given point by typing the script’s name and adding any optional parameters if wanted:
sudo /home/pi/planned_backup.sh important_files/code/
Your cron file should look similar to this example. The last line contains the command that executes the script each day at 4 AM.
The Bottom Line
Shell scripts can help you prevent incorrect command execution by avoiding typos, and they can also significantly speed up various tasks on the terminal, especially if they involve multiple, coherent commands. Instead of typing out each command manually and waiting for it to finish, you can group commands in shell scripts.
In addition, shell scripts facilitate tasks that would otherwise not be easy. Examples include complex logic forks in scripts and automated task execution. Tasks can be scheduled to run periodically or after certain system events, for instance, after the Raspberry Pi restarts.
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.
Visit TechForum