Day 2: Linux Shell Scripting & Automation - Challenges

Day 2: Linux Shell Scripting & Automation - Challenges

·

13 min read

Table of contents

Learning points:

  • Basic Shell Scripting – Writing and executing simple Bash scripts.

  • Managing Processes – Understanding ps, top, kill, and htop.

  • Using Package Managers – Installing software with apt (Debian/Ubuntu) or yum (RHEL/CentOS).

  • Basic Networking Commandsping, curl, wget, netstat, ss, ifconfig/ip.

  • Editing Configuration Files – Using nano & vim.


Initial Tasks:

  • Install a Package: Install Git (sudo apt install git or sudo yum install git).

  • Check Network Connectivity: Use ping google.com to verify internet connectivity.

  • Fetch a Web Page: Run curl http://example.com to retrieve HTML content.

  • Explore Processes: Use ps -ef to view running processes and find a specific process.

  • Terminate a Process: Identify a process ID (PID) and kill it using kill -9 <PID>.

  • Use top/htop: Monitor real-time CPU/memory usage.


🔥 Challenges

🔹 Challenge 1: Write a simple Bash script that prints “Hello DevOps” along with the current date and time.
🔹 Challenge 2: Create a script that checks if a website (e.g., https://www.learnxops.com) is reachable using curl or ping. Print a success or failure message.
🔹 Challenge 3: Write a script that takes a filename as an argument, checks if it exists, and prints the content of the file accordingly.
🔹 Challenge 4: Create a script that lists all running processes and writes the output to a file named process_list.txt.
🔹 Challenge 5: Write a script that installs multiple packages at once (e.g., git, vim, curl). The script should check if each package is already installed before attempting installation.
🔹 Challenge 6: Create a script that monitors CPU and memory usage every 5 seconds and logs the results to a file.
🔹 Challenge 7: Write a script that automatically deletes log files older than 7 days from /var/log.
🔹 Challenge 8: Automate user account creation – Write a script that takes the username as an argument, checks, if the user exists, gives the message “user already exists“ else creates a new user, adds it to a “devops“ group, and sets up a default home directory.
🔹 Challenge 9: Use awk or sed in a script to process a log file and extract only error messages.
🔹 Challenge 10: Set up a cron job that runs a script to back up (zip/tar) a directory daily.

💡 Bonus Challenge: Customize your Bash prompt to display the current user and working directory. (Hint: export PS1="\u@\h:\w\$ "), try to make it permanent, so terminal closing and opening don’t default!


Solutions

Challenge 1: Write a simple Bash script that prints “Hello DevOps” along with the current date and time.

1️⃣ Create the script file

🔥 Command:

nano hello_devops.sh

OutPut

2️⃣ Add the following script:

🔥 Command:

#!/bin/bash
echo "Hello DevOps! Today is $(date)"

OutPut

3️⃣ Save and exit (Press CTRL+X, then Y, and Enter).

4️⃣ Make the script executable:

chmod +x hello_devops.sh

5️⃣ Run the script:

./hello_devops.sh

OutPut

🛠Explanation of the Script:

  • echo → Prints the given message.

  • $(date) → Fetches the current date and time.


Challenge 2: Create a script that checks if a website (e.g., https://www.learnxops.com) is reachable using curl or ping. Print a success or failure message.

1️⃣ Create the script file

nano check_website.sh

OutPut

2️⃣ Add the following script:

#!/bin/bash

# Define the website URL
WEBSITE="https://www.learnxops.com"

# Check website reachability using curl
if curl -Is "$WEBSITE" | head -n 1 | grep -q "200\|301\|302"; then
    echo "✅ $WEBSITE is reachable via curl."
else
    echo "❌ $WEBSITE is not reachable via curl."
fi

# Extract domain from URL for ping
DOMAIN=$(echo $WEBSITE | awk -F/ '{print $3}')

# Check reachability using ping (send 1 packet, wait max 2 sec)
if ping -c 1 -W 2 "$DOMAIN" &>/dev/null; then
    echo "✅ $DOMAIN is reachable via ping."
else
    echo "❌ $DOMAIN is not reachable via ping."
fi

It Should look like this

3️⃣ Save and exit (Press CTRL+X, then Y, and Enter)

4️⃣ Make the script executable

chmod +x check_website.sh

5️⃣ Run the script

./check_website.sh

OutPut

🛠 Explanation:

  • Define the website → Stores the website URL in a variable (WEBSITE).

  • Check with curl → Sends an HTTP request and looks for success codes (200, 301, 302).

  • Extract domain → Uses awk to extract the domain name from the URL.

  • Check with ping → Sends 1 packet (-c 1), waits max 2 sec (-W 2), and checks if the site responds.

  • Print results → Shows whether the website is reachable via curl and ping

🚀 This script helps quickly diagnose if a website is up or facing connectivity issues!


Challenge 3: Write a script that takes a filename as an argument, checks if it exists, and prints the content of the file accordingly.

1️⃣ Create the script file

nano file_check.sh

OutPut

2️⃣ Add the following script

#!/bin/bash

# Check if a filename argument is provided
if [ $# -eq 0 ]; then
    echo "Usage: $0 <filename>"
    exit 1
fi

# Assign the provided argument to a variable
FILE="$1"

# Check if the file exists
if [ -f "$FILE" ]; then
    echo "File '$FILE' exists. Here is its content:"
    cat "$FILE"
else
    echo "File '$FILE' does not exist."
fi

It Should look like this

3️⃣ Save and exit (Press CTRL+X, then Y, and Enter)

4️⃣ Make the script executable

chmod +x file_check.sh

5️⃣ Create the sample file with content

echo "Welcome to DEVOPS Challenge DAY 2" > sample.txt
echo "“DevOps is a cultural and professional movement focused on how we build and operate high-velocity organizations.” – Jez Humble" >> sample.txt

6️⃣ Run the script

bash file_check.sh sample.txt

OutPut

🛠 Explanation:

  1. Checks if a filename is provided → If not, prints usage instructions.

  2. Assigns the filename to a variable (FILE) → Stores the user-provided argument.

  3. Checks if the file exists (-f "$FILE") →

    • If yes, prints the message and displays the file content using cat.

    • If no, prints a "file not found" message.

🚀 Now, running bash file_check.sh sample.txt should produce the expected output!


Challenge 4: Create a script that lists all running processes and writes the output to a file named process_list.txt.

1️⃣ Create the script file

nano list_processes.sh

OutPut

2️⃣ Add the following script

#!/bin/bash

# Define output file
OUTPUT_FILE="process_list.txt"

# Get the list of running processes and write to file
ps aux > "$OUTPUT_FILE"

# Print success message
echo "✅ Process list saved to $OUTPUT_FILE"

It Should look like this

3️⃣ Save and exit (Press CTRL+X, then Y, and Enter)

4️⃣ Make the script executable

chmod +x list_processes.sh

5️⃣ Run the script

./list_processes.sh

OutPut

📌 To view the saved process list:

cat process_list.txt

🛠 Explanation:

  • Define output file → Sets process_list.txt as the output file.

  • List running processes → Uses ps aux to get all running processes.

  • Write to file → Redirects output to process_list.txt.

  • Print success message → Confirms the file is created.


Challenge 5: Write a script that installs multiple packages at once (e.g., git, vim, curl). The script should check if each package is already installed before attempting installation.

1️⃣ Create the script file

nano install_packages.sh

OutPut

2️⃣ Add the following script

#!/bin/bash

# List of packages to install
PACKAGES=("git" "vim" "curl")

# Function to check and install a package
install_package() {
    if dpkg -l | grep -qw "$1"; then
        echo "✅ $1 is already installed."
    else
        echo "📦 Installing $1..."
        sudo apt-get install -y "$1" && echo "✅ $1 installed successfully!" || echo "❌ Failed to install $1."
    fi
}

# Loop through each package and install if needed
for package in "${PACKAGES[@]}"; do
    install_package "$package"
done

It Should look like this

3️⃣ Save and exit (Press CTRL+X, then Y, and Enter)

4️⃣ Make the script executable

chmod +x install_packages.sh

5️⃣ Run the script

./install_packages.sh

OutPut

🛠 Explanation:

  1. Defines an array (PACKAGES) → Contains package names (git, vim, curl).

  2. install_package function →

    • Checks if a package is already installed (dpkg -l | grep -qw "$1").

    • If installed, prints a message.

    • If not, installs the package using sudo apt-get install -y.

  3. Loops through each package → Calls install_package for each item in PACKAGES.

    🚀 This script ensures that only missing packages are installed, avoiding redundant installations!


Challenge 6: Create a script that monitors CPU and memory usage every 5 seconds and logs the results to a file

1️⃣ Create the script file

nano monitor_resources.sh

OutPut

2️⃣ Add the following script

#!/bin/bash

# Define log file
LOG_FILE="resource_monitor.log"

# Print header
echo "Monitoring CPU and Memory Usage - Logging to $LOG_FILE"
echo "Timestamp       | CPU Usage (%) | Memory Usage (%)" > "$LOG_FILE"

# Continuous monitoring every 5 seconds
while true; do
    # Get current timestamp
    TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")

    # Get CPU usage (ignoring idle %)
    CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print 100 - $8}')

    # Get Memory usage percentage
    MEM_USAGE=$(free | awk '/Mem/ {printf "%.2f", $3/$2 * 100}')

    # Log data
    echo "$TIMESTAMP | $CPU_USAGE%         | $MEM_USAGE%" >> "$LOG_FILE"

    # Wait 5 seconds before next check
    sleep 5
done

OutPut

3️⃣ Save and exit (Press CTRL+X, then Y, and Enter)

4️⃣ Make the script executable

chmod +x monitor_resources.sh

5️⃣ Run the script

./monitor_resources.sh

📌 Stop the script anytime using CTRL+C

📌 To check logs:

cat resource_monitor.log

OutPut

🛠 Explanation:

  1. Defines log file (resource_monitor.log) → Stores CPU & memory usage logs.

  2. Prints a header → Displays a table format in the log file.

  3. Infinite loop (while true) → Runs every 5 seconds:

    • Gets current timestamp (date).

    • Extracts CPU usage (top command, calculates used %).

    • Extracts Memory usage (free command, calculates used %).

    • Appends results to the log file.

  4. Pauses for 5 seconds (sleep 5) → Prevents excessive CPU usage.

    🚀 This script is useful for monitoring system performance over time!


Challenge 7: Write a script that automatically deletes log files older than 7 days from /var/log

1️⃣ Create the script file

nano cleanup_logs.sh

OutPut

1️⃣ Create the script file

#!/bin/bash

# Define log directory
LOG_DIR="/var/log"

# Find and delete log files older than 7 days
find "$LOG_DIR" -type f -name "*.log" -mtime +7 -exec rm -f {} \;

# Print success message
echo "✅ Deleted log files older than 7 days from $LOG_DIR"

should look like this

3️⃣ Save and exit (Press CTRL+X, then Y, and Enter)

4️⃣ Make the script executable

chmod +x cleanup_logs.sh

5️⃣ Run the script

sudo ./cleanup_logs.sh

OutPut

🛠 Explanation:

  1. Defines the log directory (/var/log) → Target location for cleanup.

  2. Finds old log files (*.log) → Uses find:

    • -type f → Searches for files only.

    • -name "*.log" → Filters log files.

    • -mtime +7 → Selects files older than 7 days.

    • -exec rm -f {}Deletes matching files.

  3. Prints a success message → Confirms cleanup action.

🚀 This script helps in managing disk space by keeping logs under control!

📌 To schedule automatic cleanup, add to corn (crontab -e): ⏰ Runs daily at 2 AM!

0 2 * * * /path/to/cleanup_logs.sh

Challenge 8: Automate user account creation – Write a script that takes the username as an argument, checks, if the user exists, gives the message “user already exists“ else creates a new user, adds it to a “devops“ group, and sets up a default home directory.

1️⃣ Create the script file

nano create_user.sh

2️⃣ Add the following script

#!/bin/bash

# Check if a username argument is provided
if [ $# -eq 0 ]; then
    echo "Usage: $0 <username>"
    exit 1
fi

# Assign the provided argument to a variable
USERNAME="$1"

# Check if the user already exists
if id "$USERNAME" &>/dev/null; then
    echo "✅ User '$USERNAME' already exists."
else
    # Create the user with a home directory
    sudo useradd -m -s /bin/bash "$USERNAME"

    # Ensure the 'devops' group exists, then add the user to it
    sudo groupadd -f devops
    sudo usermod -aG devops "$USERNAME"

    echo "✅ User '$USERNAME' created and added to 'devops' group."
fi

3️⃣ Save and exit (Press CTRL+X, then Y, and Enter)

4️⃣ Make the script executable

chmod +x create_user.sh

5️⃣ Run the script

sudo ./create_user.sh devops_user

🛠 Explanation:

  1. Checks if a username is provided → If not, it prints usage instructions.

  2. Stores the username in a variable (USERNAME).

  3. Checks if the user exists (id "$USERNAME" &>/dev/null):

    • If yes, prints "User already exists."

    • If no, it:

      • Creates the user with a home directory (-m) and default shell (-s /bin/bash).

      • Ensures the devops group exists (groupadd -f ensures no duplicate errors).

      • Adds the user to the devops group.

  4. Prints a success message once the user is created and added to the group.

🚀 Now, running sudo ./create_user.sh devops_user will create the user only if they don’t exist!


✅ Challenge 9: Use awk or sed in a script to process a log file and extract only error messages.

1️⃣ Create the script file

nano extract_errors.sh

Look like this

2️⃣ Add the following script

#!/bin/bash

# Define the log file path
LOG_FILE="/var/log/syslog"  # Change this to your log file path if needed

# Define the output file
ERROR_LOG="error_messages.log"

# Extract lines containing "error" (case-insensitive) and save to output file
grep -i "error" "$LOG_FILE" > "$ERROR_LOG"

echo "✅ Extracted error messages from $LOG_FILE to $ERROR_LOG"

Look like this

3️⃣ Save and exit (Press CTRL+X, then Y, and Enter)

4️⃣ Make the script executable

chmod +x extract_errors.sh

5️⃣ Run the script

sudo ./extract_errors.sh

🚀 Now, you can check extracted errors by running:

cat error_messages.log

OutPut

🛠 Explanation:

  1. Defines the log file (/var/log/syslog) → You can change this to another log file if needed.

  2. Defines the output file (error_messages.log) → This will store extracted error messages.

  3. Uses grep -i "error"

    • grep searches for lines containing "error".

    • -i makes it case-insensitive (matches "Error", "ERROR", etc.).

    • Redirects results to error_messages.log.

  4. Prints a success message confirming extraction.


💡 Bonus Challenge: Customize your Bash prompt to display the current user and working directory. (Hint: export PS1="\u@\h:\w\$ "), try to make it permanent, so terminal closing and opening don’t default!

1️⃣ Try it Temporarily

Run this command in your terminal to customize your Bash prompt:

export PS1="\u@\h:\w\$ "

📌 What does this do?

  • \u → Displays the current username

  • \h → Displays the hostname (computer name)

  • \w → Displays the current working directory

  • \$ → Shows $ (normal user) or # (root user)

After running this, your prompt will look like:

gourob@mint:/home/gourob$

2️⃣ Make it Permanent

To keep this customization even after restarting the terminal:

Step 1: Open the .bashrc file

nano ~/.bashrc

Step 2: Add this line at the bottom of the file

export PS1="\u@\h:\w\$ "

Step 3: Save and exit

Press CTRL+X, then Y, and Enter.

Step 4: Apply the changes immediately

source ~/.bashrc

🛠 Explanation:

  1. Temporarily sets PS1 → Works for the current session only.

  2. Adds PS1 to ~/.bashrc → Ensures the custom prompt remains after closing and reopening the terminal.

  3. Runs source ~/.bashrc → Applies the changes without needing to log out.

🚀 Now, every time you open the terminal, your prompt will show:

gourob@ubuntu:~$

🔥 Enjoy your custom Bash prompt!


Thanks for your time. I hope you enjoy my blog, please follow me on LinkedIn for more updates.