7 ‐ Shell Scripting - CloudScope/DevOpsWithCloudScope GitHub Wiki
What is a Shell Script ?
- A shell script is a file containing a series of commands that the shell (command-line interpreter) executes. It allows you to automate repetitive tasks, manage system operations, and handle complex workflows.
Creating a Shell Script
To create a shell script:
-
Open a text editor (like nano, vi, or gedit).
-
Write your commands.
-
Save the file with a .sh extension (e.g., myscript.sh).
Basic Syntax
-
Shebang: The first line of a shell script is usually a shebang (#!) followed by the path to the shell.
-
For example, #!/bin/bash specifies that the script should be run with the Bash shell.
#!/bin/bash
echo "Hello, World!"
-
Comments: Comments begin with #. They are ignored by the shell.
#
-
variables: Variables are used to store data. Define a variable by assigning a value without spaces around the = sign.
name="John"
echo "Hello, $name!"
- Commands: Commands are executed in sequence. You can use built-in commands like echo, ls, cd, and mkdir.
echo "Listing files:"
ls
-
Control Structures: Shell scripts support conditional statements and loops.
-
Conditional Statements (if)
if [ "$name" == "John" ]; then echo "Hello, John!" else echo "Hello, stranger!" if
-
-
Loops (for, while):
for i in 1 2 3; do
echo "Number $i"
done
count=1
while [ $count -le 3 ]; do
echo "Count $count"
count=$((count + 1))
done
Making a Script Executable
After creating the script, you need to make it executable. Use the chmod command:
chmod +x myscript.sh
Run the script with:
./myscript.sh
Basic Commands in Shell Scripts
echo
: Outputs text to the terminal.
read
: Reads input from the user.
cp, mv, rm
: Copy, move, and remove files, respectively.
grep
: Searches for patterns in files.
awk, sed
: Text processing tools.
$?
: last command execution result
0: success
1: General error
130: Terminated by ctrl + c
127: Command not found
Using Functions
You can define functions in a shell script to organize and reuse code.
my_function() {
echo "This is a function"
}
my_function
Error Handling
Use exit
to end the script with a status code, and trap to handle errors or cleanup.
trap 'echo "An error occurred. Exiting..."; exit 1;' ERR
Debugging
Use -x
option to debug scripts, which prints each command before executing it.
bash -x myscript.sh
Variables
- Global Variables
Definition: Global variables are variables that are accessible throughout the entire script. Once a global variable is defined, it can be used anywhere within the script.
Usage: Global variables are useful when you need to share data between different parts of the script or across functions.
#!/bin/bash
# Define a global variable
global_var="I am global"
# Function that uses the global variable
function print_global() {
echo $global_var
}
print_global # Output: I am global
- Local Variables
Definition: Local variables are variables that are confined to the scope of a function. They are not accessible outside the function in which they are defined.
Usage: Local variables are useful for keeping function-specific data and avoiding unintended interactions with global variables.
#!/bin/bash
# Define a global variable
global_var="I am global"
# Function that uses a local variable
function my_function() {
local local_var="I am local"
echo $local_var
echo $global_var # Accessing global variable inside function
}
my_function # Output: I am local
echo $local_var # Output: (nothing, as local_var is not accessible outside the function)
echo $global_var # Output: I am global
- Environment Variables
Definition: Environment variables are global variables that are available to all processes running in the shell session. They are typically used to pass configuration data to programs and scripts.
Usage: Environment variables can be used to configure system settings, specify paths, and more. They are set and exported so that they are inherited by subprocesses and child processes.
#!/bin/bash
# Set an environment variable
export MY_ENV_VAR="I am an environment variable"
# Function that uses the environment variable
function print_env_var() {
echo $MY_ENV_VAR
}
print_env_var # Output: I am an environment variable
Summary of Key Differences
-
Global Variables: Accessible throughout the script, including all functions.
-
Local Variables: Restricted to the function where they are defined; not accessible outside that function.
-
Environment Variables: Available to all processes in the shell session and its child processes. Defined with export to ensure they are available outside the current shell.
Array Elements
In Bash, @
is used with arrays to represent all elements of the array. It is often used with double quotes to handle elements that contain spaces.
#!/bin/bash
# Define an array
my_array=("one" "two" "three")
# Print all elements of the array
echo "All elements of the array:"
for item in "${my_array[@]}"; do
echo "$item"
done
In this script, ${my_array[@]} is used to access all elements of my_array.
Quoting "${my_array[@]}" ensures that each element is treated as a separate item, preserving spaces within elements.
Positional Parameters
The @
symbol is also used to refer to all positional parameters in a script. Positional parameters are the arguments passed to a script or function.
#!/bin/bash
# Print all positional parameters
echo "All positional parameters:"
for param in "$@"; do
echo "$param"
done
When you run this script with arguments, for example ./script.sh arg1 arg2 arg3, the output will be:
All positional parameters:
arg1
arg2
arg3
Array Indices
In Zsh, @ is used similarly to how it's used in Bash for arrays, but it can also be used to manipulate array indices.
#!/bin/zsh
# Define an array
my_array=("apple" "banana" "cherry")
# Print all elements of the array
echo "All elements of the array:"
for item in ${my_array[@]}; do
echo "$item"
done
In this Zsh example, ${my_array[@]} accesses all elements of my_array.
tee
Command
Usage: command | tee [options] file
Function: Reads from standard input and writes to both standard output and the specified file. Useful for logging output while still displaying it on the terminal.
Options:
-a
: Append to the file instead of overwriting.
-i
: Ignore the interrupt signals.
echo "Log this line" | tee log.txt
echo "Another log entry" | tee -a log.txt
>
(Redirection with File Descriptor Manipulation)
-
Usage:
command > file 2>&1
-
Function: Redirects both stdout and stderr to the same file. 2>&1 means redirect stderr (2) to the same place as stdout (1).
ls /some_directory > output.log 2>&1
-
Usage:
command > file
-
Function: Redirects the standard output (stdout) of command to file. If file already exists, it will be overwritten.
echo "Hello, World!" > output.txt
2>
(Standard Error Redirection)
Usage: command 2> file
Function: Redirects the standard error (stderr) of command to file. If file already exists, it will be overwritten.
ls non_existent_file 2> error.log
2>> (Append Standard Error)
Usage: command 2>> file
Function: Appends the standard error of command to file. If file does not exist, it will be created.
ls another_non_existent_file 2>> error.log
>>
(Append Standard Output)
Usage: command >> file
Function: Appends the standard output of command to file. If file does not exist, it will be created.
echo "Another line" >> output.txt
File system flag usages
When working with shell scripts, especially in Bash, it's common to use conditional statements (if-else
) with file system flags to check the properties of files and directories. Below are some common flags and how they are used in if-else
conditions:
Common File Flags in Bash:
-
-d
: Checks if the specified path is a directory.if [ -d "/path/to/directory" ]; then echo "It's a directory" else echo "It's not a directory" fi
-
-f
: Checks if the specified path is a regular file.if [ -f "/path/to/file" ]; then echo "It's a file" else echo "It's not a file" fi
-
-e
: Checks if the file or directory exists.if [ -e "/path/to/item" ]; then echo "It exists" else echo "It does not exist" fi
-
-r
: Checks if the file or directory is readable.if [ -r "/path/to/file" ]; then echo "It's readable" else echo "It's not readable" fi
-
-w
: Checks if the file or directory is writable.if [ -w "/path/to/file" ]; then echo "It's writable" else echo "It's not writable" fi
-
-x
: Checks if the file or directory is executable.if [ -x "/path/to/file" ]; then echo "It's executable" else echo "It's not executable" fi
-
-s
: Checks if the file is not empty (size greater than zero).if [ -s "/path/to/file" ]; then echo "File is not empty" else echo "File is empty" fi
-
-L
: Checks if the specified path is a symbolic link.if [ -L "/path/to/link" ]; then echo "It's a symbolic link" else echo "It's not a symbolic link" fi
if-else
Conditions:
Example with Here's an example script that uses multiple flags in an if-else
condition:
#!/bin/bash
FILE="/path/to/some/file"
if [ -e "$FILE" ]; then
if [ -d "$FILE" ]; then
echo "$FILE is a directory."
elif [ -f "$FILE" ]; then
echo "$FILE is a file."
if [ -r "$FILE" ]; then
echo "It is readable."
fi
if [ -w "$FILE" ]; then
echo "It is writable."
fi
if [ -x "$FILE" ]; then
echo "It is executable."
fi
elif [ -L "$FILE" ]; then
echo "$FILE is a symbolic link."
else
echo "$FILE exists but is neither a file nor a directory."
fi
else
echo "$FILE does not exist."
fi
Tips:
- Use
&&
and||
for combining conditions within anif
statement. - Quoting variables is important to handle paths with spaces or special characters.
- Check permissions and ownerships with
-r
,-w
, and-x
to ensure that operations are safe and authorized.
These flags and examples help you control and manage your scripts by making decisions based on the characteristics of files and directories in the file system.