Skip to content

Instantly share code, notes, and snippets.

@carloswm85
Created June 7, 2025 23:40
Show Gist options
  • Save carloswm85/221e8e55091b3d0b3d15e3a3f81ec797 to your computer and use it in GitHub Desktop.
Save carloswm85/221e8e55091b3d0b3d15e3a3f81ec797 to your computer and use it in GitHub Desktop.
#!/bin/bash
# shellcheck disable=SC2002
# shellcheck disable=SC2020
# shellcheck disable=SC2086
# shellcheck disable=SC2317
# shellcheck disable=SC1073
# shellcheck disable=SC1009
# shellcheck disable=SC1072
## Common BASH shell environment files and the order in which they are typically
## executed are as follows:
# /etc/profile
# /etc/profile.d/*
# /etc/bashrc
# ~/.bashrc
# ~/.bash_profile
# ~/.bash_login
# ~/.profile
## WEEK 07
## =============================================================================
## PROJECT 7-1
## Objective: Perform shell redirection.
## Description: In this hands-on project, you use the shell to redirect the
## stdout and stderr to a file and take stdin from a file.
touch sample1 sample2 # Create two empty files: sample1 and sample2
ls -F # List files in the directory with special characters to indicate type
ls -l sample1 sample2 sample3 # List detailed info for sample1, sample2, and non-existent sample3 (stderr expected)
ls -l sample1 sample2 sample3 > file # Redirect stdout to 'file'; stderr (if any) still appears on screen
cat file # Display contents of 'file' (only stdout from previous command)
ls -l sample1 sample2 sample3 2> file # Redirect stderr to 'file'; stdout (if any) appears on screen
cat file # Display contents of 'file' (only stderr from previous command)
ls -l sample1 sample2 sample3 > file 2>file2 # Redirect stdout to 'file' and stderr to 'file2'
cat file # Show stdout from previous ls command
cat file2 # Show stderr from previous ls command
ls -l sample1 sample2 sample3 > file 2>&1 # Redirect both stdout and stderr to 'file'
cat file # Show combined stdout and stderr from previous command
ls -l sample1 sample2 sample3 >&2 2>file2 # Redirect both stdout and stderr to stderr, then redirect stderr to 'file2'
cat file2 # Show captured stderr from previous command
date > file # Overwrite 'file' with current date
cat file # Show contents of 'file' (should be the current date)
date >> file # Append current date to 'file'
cat file # Show both dates; first from overwrite, second from append
tr o O /etc/hosts # Incorrect usage: tr doesn't take filenames as arguments (stderr expected)
tr o O </etc/hosts # Correct: replaces all 'o' with 'O' from /etc/hosts and outputs result
tr o O <<EOF # Start here-doc input redirection to tr (until EOF is entered)
oranges
Toronto
Donkey Kong
EOF
## =============================================================================
## PROJECT 7-2
## Objective: Perform shell piping.
## Description: In this hands-on project, you redirect stdout and stdin using
## pipe metacharacters.
cat /etc/services # Display the contents of /etc/services
cat /etc/services | less # View the contents page-by-page using less via a pipe
cat /etc/services | grep NFS # Filter lines containing "NFS"; grep reads from stdin
cat /etc/services | grep NFS | tr F f # Replace uppercase 'F' with lowercase 'f' in the grep output
cat /etc/services | grep NFS | tr F f | sort -r # Sort the modified lines in reverse order
cat /etc/services | grep NFS | tr F f | sort -r | tee file # Save output to 'file' and display on screen
cat file # Show contents of 'file'; matches previous output
cat /etc/services | grep NFS | tr F f | sort -r | tee file | wc -l # Count number of lines; saves intermediate output to 'file'
cat file # Show contents of 'file' to verify tee output
cat /etc/services | grep NFS | tr F f | sort -r | sed /udp/d | sed /tcp/s/mount/MOUNT/g # Remove lines with 'udp', replace 'mount' with 'MOUNT' in 'tcp' lines
cat /etc/hosts # Display contents of /etc/hosts
cat /etc/hosts | awk '/localhost/ {print $1, $3}' # Print first and third fields of lines containing 'localhost'
## =============================================================================
## PROJECT 7-3
## Objective: Create and manage variables.
## Description: In this hands-on project, you create and use an alias, as well
## as view and change existing shell variables. In addition, you export
## user-defined variables and load variables automatically upon shell startup.
# shellcheck disable=SC2002
set | less # View all shell variables; scroll with arrow keys, quit with 'q'
env | less # View exported environment variables; usually fewer than `set` because it only shows exported ones
PS1="Hello There:" # Temporarily change the shell prompt to "Hello There:"
echo $PS1 # Display current value of the PS1 variable
exit # Log out of the shell
# After re-login:
# The prompt reverts because the PS1 change wasn't persisted
vi .bash_profile # Open user's shell profile to persist settings
# Add the following to the bottom of .bash_profile:
# echo -e "Would you like a hello prompt? (y/n) -->\c"
# read ANSWER
# if [ $ANSWER = "y" -o $ANSWER = "Y" ]
# then
# PS1="Hello There: "
# fi
# This script prompts user at login, and sets the prompt to "Hello There: " if they answer 'y' or 'Y'
exit # Log out to test the new .bash_profile behavior
# Log back in and enter 'y' at the prompt — prompt changes to "Hello There:"
exit # Log out again
# Log in again and enter 'n' at the prompt — default prompt appears
MYVAR="My sample variable" # Create a shell variable called MYVAR
echo $MYVAR # Display value of MYVAR
set | grep MYVAR # MYVAR appears because it's set in the shell
env | grep MYVAR # MYVAR does not appear — not exported yet
export MYVAR # Export MYVAR to make it available to subshells
env | grep MYVAR # MYVAR now appears in environment list
exit # Log out again
# After re-login:
echo $MYVAR # MYVAR is not defined — because it wasn't set in .bash_profile
vi .bash_profile # Edit profile to make MYVAR persistent
# Add this line at the bottom of .bash_profile:
# export MYVAR="My sample variable"
exit # Log out again
# After re-login:
echo $MYVAR # MYVAR is now available automatically
alias # Show defined aliases
alias asample="cd /etc ; cat hosts ; cd ~ ; ls -F" # Define alias: go to /etc, display hosts file, return home, list files with markers
asample # Run the alias; output from each command is displayed in sequence
# To persist this alias across sessions, add it to ~/.bashrc
exit # Logout of the shell
## =============================================================================
## PROJECT 7-4
## Objective: Create a basic shell script.
## Description: In this hands-on project, you create a basic shell script and
## execute it on the system.
vi myscript # Open a new file called 'myscript' in the vi editor
# Inside vi, enter the following lines:
# ------------------------------------
# #!/bin/bash
# echo -e "This is a sample shell script. \t It displays mounted filesystems: \a"
# df -hT
# ------------------------------------
# Save and quit vi with :wq
ls -l myscript # List file details and permissions for 'myscript'
bash myscript # Run the script using the bash interpreter directly
# \t = horizontal tab, \a = alert/bell (may make a sound or flash)
./myscript # Try to execute script directly (will likely fail due to missing execute permission)
chmod u+x myscript # Add execute permission for the file owner
./myscript # Now run the script directly after setting execute permission
exit # Log out of the shell
## =============================================================================
## PROJECT 7-5
## Objective: Create system administration shell scripts.
## Description: In this hands-on project, you create a shell script that uses
## decision and loop constructs to analyze user input.
vi diskconfig.sh # Open a new shell script file named diskconfig.sh in the vi editor
# Inside vi, enter the following script:
# --------------------------------------
# #!/bin/bash # Use the Bash shell to interpret the script
# # This script creates a report of our disk configuration
# FILENAME=$(hostname) # Assign the system's hostname to the variable FILENAME
# echo "Disk report saved to $FILENAME.report" # Print message showing the name of the output report file
# echo -e "\n LVM Configuration: \n\n" >> $FILENAME.report # Write LVM section header into the report file
# lvscan >> $FILENAME.report # Append output of logical volume scan to the report
# echo -e "\n\n Partition Configuration: \n\n" >> $FILENAME.report # Write partition section header into the report
# fdisk -l | head -17 >> $FILENAME.report # Append first 17 lines of partition info to the report
# echo -e "\n\n Mounted Filesystems: \n\n" >> $FILENAME.report # Write mounted filesystems header into the report
# df -hT | grep -v tmp >> $FILENAME.report # Append mounted filesystems (excluding tmpfs) to the report
# --------------------------------------
# Save and quit vi with :wq
chmod u+x diskconfig.sh # Grant execute permission to the script
./diskconfig.sh # Run the disk configuration script
less "$(hostname).report" # View the generated report with less
vi dirbackup.sh # Open a new shell script file named dirbackup.sh
# Inside vi, enter the following first version:
# --------------------------------------
# #!/bin/bash # Use the Bash shell to interpret the script
# # This script backs up a directory of your choice
# if [ $# -ne 1 ]; then # Check if exactly one argument (directory) was passed
# echo "Usage is $0 <directory to back up>" # Print usage message with script name if not
# exit 255 # Exit with status code 255 indicating error
# fi
# echo "Performing backup....." # Inform user that backup is starting
# sleep 3 # Pause for 3 seconds for dramatic effect
# tar -zcvf ~/backupfile.tar.gz $1 # Create compressed archive of the directory passed as argument
# echo "Backup completed successfully to ~/backupfile.tar.gz" # Inform user that the backup has completed
# --------------------------------------
# Save and quit vi with :wq
chmod u+x dirbackup.sh # Make script executable
./dirbackup.sh # Run without argument to see the error
./dirbackup.sh /etc/samba # Run with argument to back up /etc/samba
ls -F # List files in current directory to check for backup
vi dirbackup.sh # Edit the script for input-based backup
# Modify the script to:
# --------------------------------------
# #!/bin/bash # Use the Bash shell to interpret the script
# # This script backs up a directory of your choice
# echo -e "What directory do you want to back up?-->\c" # Prompt user to input a directory path (with no newline)
# read ANS # Read the user input into the variable ANS
# echo "Performing backup....." # Inform user that backup is starting
# sleep 3 # Pause for 3 seconds for user clarity
# tar -zcvf ~/backupfile.tar.gz $ANS # Create compressed archive of the specified directory
# echo "Backup completed successfully to ~/backupfile.tar.gz" # Inform user that the backup has completed
# --------------------------------------
# Save and quit vi with :wq
./dirbackup.sh # Run and input e.g. /etc/httpd when prompted
vi dirbackup.sh # Modify the script to include directory and date in filename
# Modify the script to:
# --------------------------------------
# #!/bin/bash # Use the Bash shell to interpret the script
# # This script backs up a directory of your choice
# echo -e "What directory do you want to back up?-->\c" # Prompt user for directory path (no newline after prompt)
# read ANS # Read user input into the variable ANS
# echo "Performing backup....." # Notify the user that the backup is starting
# sleep 3 # Pause for 3 seconds for visibility
# FILE=$(echo $ANS | sed 's#/#-#g') # Replace all forward slashes in directory path with dashes for filename
# DATE=$(date +%F) # Store current date in YYYY-MM-DD format
# tar -zcvf ~/backup-$FILE-$DATE.tar.gz $ANS # Create a gzipped tarball named with sanitized path and current date
# echo "Backup performed to ~/backup-$FILE-$DATE.tar.gz" # Notify the user of successful backup and its location
# --------------------------------------
# Save and quit vi with :wq
./dirbackup.sh # Run and input e.g. /etc/httpd to create a timestamped backup
vi familydatabase.sh # Open a new shell script file named familydatabase.sh
# Enter the following:
# --------------------------------------
# #!/bin/bash # Use the Bash shell to interpret the script
# while true; do # Start an infinite loop
# clear # Clear the screen before each iteration
# echo -e "What would you like to do? # Display the menu options
# Add an entry (a)
# Search an entry (s)
# Quit (q)
# Enter your choice (a/s/q)-->\c" # Prompt the user (no newline after prompt)
# read ANSWER # Read user input into variable ANSWER
# case $ANSWER in # Begin case block to handle user choice
# a|A) # If user selects 'a' or 'A':
# echo -e "Name of the family member --> \c" # Prompt for name
# read NAME # Read name input
# echo -e "Family member's relation to you -->\c" # Prompt for relation
# read RELATION # Read relation input
# echo -e "Family member's telephone number --> \c" # Prompt for phone number
# read PHONE # Read phone number input
# echo -e "$NAME\t$RELATION\t$PHONE" >> database # Append entered info to 'database' file, tab-separated
# ;; # End of 'a' case block
# s|S) # If user selects 's' or 'S':
# echo -e "What word would you like to look for? --> \c" # Prompt for search term
# read WORD # Read search term input
# grep "$WORD" database # Search the 'database' file for the term
# sleep 4 # Pause for 4 seconds to view output
# ;; # End of 's' case block
# q|Q) # If user selects 'q' or 'Q':
# exit # Exit the script
# ;; # End of 'q' case block
# *) # For any other input:
# echo "You must enter either the letter a or s." # Display usage error message
# sleep 4 # Pause for 4 seconds
# ;; # End of default case block
# esac # Close the case block
# done # Repeat the loop
# --------------------------------------
# Save and quit vi with :wq
chmod u+x familydatabase.sh # Make the script executable
./familydatabase.sh # Run the family database script
# Test all options: a (add), s (search), x (invalid), q (quit)
exit # Log out of the shell
## =============================================================================
## PROJECT 7-6
## Objective: Practice using Git.
## Description: In this hands-on project, you create a local Git repository for
## the shell scripts that you created in Project 7-5 and explore Git version
## control.
mkdir /shellscripts # Create a new directory called /shellscripts
mv diskconfig.sh dirbackup.sh familydatabase.sh /shellscripts # Move the three scripts to the /shellscripts directory
git config --global user.email "[email protected]" # Set the global Git email
git config --global user.name "root user" # Set the global Git username
git config --global init.defaultBranch main # Set the default Git branch name to main
cd /shellscripts # Change to the /shellscripts directory
git init # Initialize a new Git repository
ls -a # List all files including hidden ones to confirm .git directory
git status # Check current Git status (untracked files)
git add . # Add all files to the Git staging area
git status # Confirm that files are staged
git commit -m "First commit" # Create the first commit with a message
vi diskconfig.sh # Open diskconfig.sh in vi editor
# (Add the following lines at the end of the file in vi)
echo -e "\n\n RAID Configuration: \n\n" >>$FILENAME.report # Add RAID section heading to the report
mdadm --detail /dev/md0 >>$FILENAME.report # Add RAID details to the report
git status # Check Git status to see if the file was modified
git add . # Stage the modified file
git commit -m "Added RAID to diskconfig.sh" # Commit the changes with a message
git log # Show Git commit history
git reset --hard <commit> # Reset the repo to the specified previous commit
cat diskconfig.sh # Display the contents of diskconfig.sh
cd # Return to the home directory
git clone /shellscripts # Clone the /shellscripts repository into the current directory
cd shellscripts # Change into the cloned repository directory
ls -a # List all files including .git to verify the clone
git branch # Show current branch (should be main)
git checkout -b AddRAID # Create and switch to a new branch named AddRAID
git branch # List branches to confirm AddRAID is the current branch
vi diskconfig.sh # Open diskconfig.sh in vi editor
# (Add the following lines at the end of the file in vi)
echo -e "\n\n RAID Configuration: \n\n" >>$FILENAME.report # Add RAID section heading again in branch
mdadm --detail /dev/md0 >>$FILENAME.report # Add RAID details again in branch
git add . # Stage the modified file for commit in AddRAID branch
git commit -m "Added RAID to diskconfig.sh" # Commit the change to the AddRAID branch
cat diskconfig.sh # Show contents to confirm RAID lines are present
git checkout main # Switch back to the main branch
cat diskconfig.sh # Confirm the RAID lines are not present in main
git push origin AddRAID # Push AddRAID branch to the origin repository
cd /shellscripts # Go to the original repository
git branch # Verify that AddRAID exists and main is still the active branch
git show AddRAID # Show the changes made in the AddRAID branch
git merge AddRAID # Merge AddRAID into the current main branch
cat diskconfig.sh # Confirm RAID lines are now in the main branch
cd ~/shellscripts # Go back to the cloned repo in the home directory
git pull origin main # Pull latest changes from the origin main branch
exit # Log out of the terminal
## =============================================================================
## PROJECT 7-7
## Objective: Set up and use the Z shell.
## Description: In this hands-on project, you install and explore the Z shell.
dnf -y install zsh # Install the Z shell non-interactively with auto-confirm
exit # Log out of the root shell session
zsh # Start the Z shell and enter the interactive configuration menu
vi .zshrc # Open Zsh config file in vi for manual editing; edit `setopt autocd` to `setopt autocd correct`, then save with :wq
source .zshrc # Reload .zshrc into the current shell session
grep NFS /etc/services >file1 >file2 # Only file2 gets the output; second redirection overrides the first
cat file1 # View contents of file1 (likely empty)
cat file2 # View contents of file2 (contains grep output)
grep NFS /etc/services >file1 | grep protocol >file2 # file1 gets output from grep NFS; file2 gets filtered result from the pipe
cat file1 # View file1 contents
cat file2 # View file2 contents
sort <file1 <file2 >file3 # Incorrect: only file2 is used due to conflicting redirections
cat file3 # View file3 contents (likely only sorted file2)
grp NFS /etc/services # Typo triggers autocorrect; press y to fix to `grep`
date - # Press Tab to list valid options
date --universal # Show current date/time in UTC
pwd # Show current working directory
Desktop # Change to Desktop directory using autocd
pwd # Show new working directory (should be ~/Desktop)
exit # Log out of Z shell session
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment