Bash-Scripting¶
System Administration - Bash Scripting¶
Table of Content¶
Introduction¶
Bash Scripting Definition¶
Working in UNIX operating system, we will face this type of a file which contain a sequence of commands that are executed by the bash program line by line to perfrom a series of actions. These actions performed by commands can be repeated multiple times and execute them by running the script.
Advantages¶
Adv |
Description |
|---|---|
Automation |
Bash scripting allows you to automate repetitive tasks, making it incredibly useful for tasks like file manipulation, system maintenance, backups, and more. This automation can significantly save time and reduce human error. |
Accessibility |
Bash is the default shell for most Unix-like operating systems, ensuring its widespread availability. It’s pre-installed on macOS and most Linux distributions, making it easily accessible without the need for additional installations. |
Customization |
Users can customize and tailor scripts according to their needs, making it a flexible tool for various tasks. With conditional statements, loops, and functions, it’s possible to create complex and specific workflows. |
Integration |
Bash scripts can integrate with other command-line utilities and programs seamlessly. This integration allows for powerful scripting by combining the functionality of multiple tools into a single script. |
System Administration |
Bash scripting is extensively used in system administration tasks. It helps in automating system configurations, user management, log analysis, and other administrative tasks. |
Portability |
Bash scripts are often portable across different Unix-like systems. However, it’s essential to consider the differences in commands and functionalities across different versions of Bash and other shells. |
Rapid Development |
Writing scripts in Bash is relatively quick and straightforward due to its simple syntax. For quick solutions or prototyping, it provides a fast development environment. |
Learning Curve |
Compared to more complex programming languages, Bash scripting has a relatively lower learning curve, making it accessible for beginners. It’s a good starting point for those new to scripting or programming concepts. |
Debugging Tools |
Bash provides debugging options like tracing execution, setting breakpoints, and displaying error messages, aiding in identifying and fixing issues in scripts. |
Community Support |
There’s a large community of Bash scripters and developers, resulting in an abundance of online resources, forums, and tutorials to seek help from and learn. |
Note: It is important to note that, bash scripting might not always be the most suitable tool for every task, for complex projects or tasks requiring extensive data manupulation or advanced data structures.
Creating a bash script¶
Let’s start creating our own script!!
Script naming conventions¶
Bash scripts ends with .sh, However, they can run fine without the sh extention.
An Important Observation! In Unix system, a file extention is useless for Unix system, and has no any importants except for the user, to know what is the file type working on. So how does the system knows it is a bash script?
Shebang¶
A shebang, also known as a hashbang (hash # + bang !) or a pound-bang, refers to the first line in a script file in Unix-like operating systems. It begins with the characters “#!” followed by the path to the interpreter that should execute the script. For example:
#!/bin/bashc
Shebang is simply an absoulte path to the bash interpreter
To find the bash shell path:
which bash
Executing the Bash Script¶
In Unix system, any created file by default is not executable, which means user can not execute it.
Make Script Executable¶
To make a file executable:
chmod u+x my_script.sh
Command |
Description |
|---|---|
chmod |
Modifies the ownership of a file |
u |
Modify this ownership for the current user |
x |
adds the execution rights |
u+x |
This means that the user who is the owner can now run the script |
my_script.sh |
The file which the user want to run |
Execute¶
there are several methods to execute the scirpt
sh my_script.sh
bash my_script.sh
./my_script.sh
Basics¶
There are some basics in the bash scripting any user should know
2- Variables & Data Types¶
To easily store, read, and access the data, variables knows how to get this job done.There are no data types in Bash, so variables can easily store any type of data.
Define a Varialbe¶
#!/bin/bash
# this is a variable to store a string
firstname=ahmed
lastname="yousri"
You can enclose the string with quots or just leave it without them, but in case of not using the quotes, make sure the string does not have any spaces
Access a Varialbe¶
To access the value in a variable, use $
#!/bin/bash
echo $firstname
Naming Convention¶
In Bash scripting, variable names should follow certain conventions for readability and consistency. Here are the commonly recommended naming conventions for variables:
Should start with a letter or an underscore
Can contains letters, numbers, and underscores
Case-senstive
Should not contain spaces or special characters
Tips¶
Avoid using reserved keywords, such as if, then, else, fi, and so on.
Avoid using system or Bash reserved variables names like PATH, HOME, PWD, …
Use descriptive names that reflect the purpose of the variables.
Uppercase for Environment Variables
Lowercase or CamelCase for Local Variables
Underscores for Multi-word Variable Names
Constants in Uppercase
3- Inputs¶
Read User Input¶
You can read user input using the read command
#!/bin/bash
# Print a message for the user
echo "What's your name?"
# Read input from user, and store it in varialbe called usernamne
read username
# print user input
echo "Hello, $username! Welcome"
Reading from File¶
#!/bin/bash
# Reading line by line from user
while read line
do
echo $line
done < input.txt
Command |
Details |
|---|---|
while read line |
This line starts a while loop. The read command reads a line from the input and stores it in the variable line. This loop continues until there are no more lines to read. |
do |
Marks the beginning of the loop body. Commands placed after do and before done will be executed repeatedly as long as the read command successfully reads a line from the file. |
echo $line |
This command prints the content of the variable line to the terminal. |
done |
Marks the end of the loop body. |
< input.txt |
Redirects the contents of the file input.txt as input to the while loop. So, the read command reads each line of input.txt sequentially, assigns it to the variable line, and then echo $line prints each line to the terminal. |
Command Line Arguments¶
In many cases, we add arugments along side with the bash script during the execution, like:
./my_script.sh ahmed
So in the bash script, we can access this using the $ operator.
#!/bin/bash
echo "Hello, $1!"
so the expected output will be: “Hello, Ahmed!”
The number notation, indecate the argument position, so in our case, ahmed was the first arguments in the command line, so we can read it using $1. So in case there are other arguments, we can access them using their index number in the command line.
What about $0 you may ask?
This holds the bash script name itself!!.
4- Outputs¶
Prinitng to the Terminal¶
Using Command echo
#!/bin/bash
echo "Hello Bash!"
Writing to a File¶
Using redirect operator >
#!/bin/bash
echo "This is bash text." > my_output.txt
Appending to a File¶
Using the appending operator >> :
#!/bin/bash
echo "More bash text" >> my_output.txt
Redirecting Output¶
You can redirect the output of a command to a file using the redirect operator
ls > my_file.txt
5- Conditional Statements (if/else)¶
TO have a boolean results, with a true or false. this is what is called conditions. To do so using if, if-else, if-elif-else, and nested conitionals.
If¶
#!/bin/bash
if [[ condition ]]; then
statement
elif [[ condition ]]; then
statement
else
do this by default
fi
Multiple Conditions¶
You can combine multiple conditions using AND -a and OR -o to make comparisons that have more significance:
#!/bin/bash
if [ $a -gt 60 -a $b -lt 100]
# To check if varialbe a is greater than 60 AND variable b is less than 100
Case Statements¶
case expression in
pattern1)
# code to execute if expression matches pattern1
;;
pattern2)
# code to execute if expression matches pattern2
;;
pattern3)
# code to execute if expression matches pattern3
;;
*)
# code to execute if none of the above patterns match expression
;;
esac
If Flags¶
Refer to man if manual page to get more about the supported flags used in the conitions.
-a file exists This is identical in effect to -e. It has been "deprecated," [1] and its use is discouraged.
-b file is a block device
-c file is a character device [ -b "/dev/sda2" ]
-d file is a directory
-e file exists
-f file is a regular file (not a directory or device file)
-G group-id of file same as yours
-g set-group-id (sgid) flag set on file or directory
If a directory has the sgid flag set, then a file created within that directory belongs to the group
that owns the directory, not necessarily to the group of the user who created the file.
-h file is a symbolic link
-k sticky bit1 set
-L file is a symbolic link
-N file modified since it was last read
-O you are owner of file
-p file is a pipe [ -p /dev/fd/0 ]
-r file has read permission (for the user running the test)
-S file is a socket
-s file is not zero size
-t file (descriptor) is associated with a terminal device.
-u set-user-id2 (suid) flag set on file
-w file has write permission (for the user running the test)
-x file has execute permission (for the user running the test)
-nt file f1 is newer than f2 f1 -nt f2
-ot file f1 is older than f2 f1 -ot f2
-ef files f1 and f2 are hard links to the same file f1 -ef f2
! "not" -- reverses the sense of the tests above (returns true if condition absent).
6- Looping¶
To repeatily doing same instructions commands as long as a condition is valid (true), you can easily use looping, until a condition become invalid (false) and break the loop.
While Loop¶
It is used in case you want to repeat some commands as long a condition is valid
#!/bin/bash
i=1
while [[ $i -ls 10]]; do
echo $i
(( i +=1 ))
done
For Loop¶
It is more used in case if you know how many times you need to iterate and repeatly do the same commands, so this even used in case of reading a file line by line.
#!/bin/bash
for i in [1..5]
do
echo $i
done
7- Functions¶
In Bash scripting, functions are blocks of code that can be defined once and executed multiple times within a script. They offer modularity, reusability, and help organize code. Here’s an overview of using functions in Bash:
function function_name {
# Commands or code block
# Within the function
}
Example for a cslculator:
#!/bin/bash
# Define functions to perform calculations
function add {
echo $(($1 + $2))
}
function subtract {
echo $(($1 - $2))
}
function multiply {
echo $(($1 * $2))
}
function divide {
echo $(($1 / $2))
}
# Get input numbers from command-line arguments
num1=$1
num2=$2
# Call the functions with input numbers
echo "Addition: $(add $num1 $num2)"
echo "Subtraction: $(subtract $num1 $num2)"
echo "Multiplication: $(multiply $num1 $num2)"
echo "Division: $(divide $num1 $num2)"
8- Schedule Scripts using cron¶
Not all scripts are meant to be immediatly run to do their task, some time we need to set a schedule to automate their work on a specific time. We will use cron to do this schedule feature.
Cron¶
Cron is a time-based job scheduler in Unix-like operating systems, including Linux and macOS. It allows users to schedule tasks, commands, or shell scripts to run automatically at predefined intervals or specific times without manual intervention.
Steps to Shcedule a Bash Script¶
1. Understand Cron Syntax¶
Cron uses a specific syntax to define the schedule. It comprises five fields followed by the command/script to be executed. The fields represent minute, hour, day of the month, month, and day of the week. Here’s the syntax:
* * * * * command_to_execute
- - - - -
| | | | |
| | | | +----- Day of the week (0 - 7) (Sunday is 0 or 7)
| | | +------- Month (1 - 12)
| | +--------- Day of the month (1 - 31)
| +----------- Hour (0 - 23)
+------------- Minute (0 - 59)
2. Edit the User’s Cron Jobs¶
Use the crontab -e command to open the cron job editor for the current user. This command opens the user’s crontabe file for editting in the default text editor.
crontab -e
3.Schedule the Bash Script¶
Add an entry to schedule your bash script by specifying the schedule and the command to execute:
# Schdule a script to run every 0 mins, 4 hours, for every day, month, day of week
0 4 * * * /path/to/your/script.sh
4. Save and exit¶
After adding the entry, save the changes and exit the editor
5. Check Shceduled Scripts¶
crontab -l
Additional Tips:¶
Ensure that the script has executable permissions (chmod +x script.sh).
Specify absolute paths for files, as cron might not use the same environment variables as your interactive shell.
Redirect output (if necessary) to a specific file within the script itself to capture any output or errors that might occur during execution.
Debug & Troubleshoot¶
“Do it work just fine? then do not touch it!!”, we need to be able to debug our script, and can catch the error, so we need to be able to deubg our script.
Debugging Bash scripts involves identifying and resolving issues or errors that occur during script execution. There are several techniques and tools available to debug Bash scripts effectively:
1. Using ‘set -x’¶
Add ‘set -x’ at the beginning of your script to enable debugging mode. This mode displays each command before executing it, allowing you to see the sequence of commands executed.
#!/bin/bash
set -x
# Your script commands here
2. echo Statements:¶
Use ‘echo’ statements within the script to print variables, messages, or checkpoints to the terminal. This helps track the flow of the script and identify where issues might occur.
#!/bin/bash
echo "Starting script..."
# Your script commands here
echo "Script completed."
3. Redirecting Output and Errors¶
Redirect standard output and errors to separate files to capture any issues or messages that might not be displayed in the terminal.
#!/bin/bash
# Redirect standard output to a file
exec > output.log
# Redirect errors to a file
exec 2> error.log
# Your script commands here
4. set -e¶
Use ‘set -e’ to exit immediately if any command returns a non-zero exit status. This helps in catching errors early in the script execution.
#!/bin/bash
set -e
# Your script commands here
5. trap Command¶
Use trap to catch and handle signals or errors that occur during script execution. This helps perform specific actions when an error occurs.
#!/bin/bash
trap 'echo "Error occurred"; exit 1' ERR
# Your script commands here
6. Shellcheck¶
Use external tools like Shellcheck to statically analyze your Bash script for common issues, syntax errors, and pitfalls
7. Debugging with bash -x¶
Run your script with bash -x script.sh to debug it directly from the command line, enabling debugging mode only for that execution.
8. Logging¶
Implement logging mechanisms within your script to track the execution flow, variable values, and errors encountered during script execution.
Tips & Tricks¶
Braces Expansion¶
You can use brace expansion feature to allow user to generate list of words or commands.
To use it, enclose a comma-seperated list of workds or command in curly braces.
touch file.{txt,doc,pdf}
mkdir /var/tmp/{one,two,three}
Braces for Variables¶
Using braces around a variable name can help to avoid ambiguity and improve readability.
output_dir=/path/to/directory
echo "The output file is: ${output_dir}"
Command Substitution¶
It is a good programming tip to use variables for commands substitution instead of
current_time=$(date +%Y-%m-%d_%H:%M:%S)
echo "The current time is: $current_time"
Aliases¶
You can use aliases as shortcuts for commands or command sequences. This could save time and typing by allowing user to use a shorter or more intuitive command.
To create an alias, use the alias command followed by the name of the alias and the command or command sequence you want to alias.
alias ll="ls -la"
The Watch Command¶
Use watch command to allows you to execute a command periodically and display the output in real-time.
Useful for monitoring system resources or processess.
To use watch command:
# display the output of ps aux command every second.
watch -n 1 ps aux
History Expansion¶
History expansion allows user to reuse commands from your command history.
To use it:
# return the last command
!!
# return the command two commands ago
!-2
References¶
freeCodeCamp - Bash Scripting Tutorial – Linux Shell Script and Command Line for Beginners: link
10 must-known Bash shell scripting tips and tricks for beginners - Foos Linux
10 Bash Tricks Every Developer Should Know - tecadmin
Chatgpt - openAI: link
1- Comments¶
A neat bash script is the one that you could understand what is happening inside. To make a script readable, we should add comments.
Comments starts with #, so any line begins with # is a comment and will be ignored by the interpreter. There is exception in the shebang!!