Build a Linux System Monitor

Write a shell script to monitor CPU, memory, and disk usage on Linux.

Introduction

30 Second Summary

Every server needs someone watching its vital signs. When CPU spikes or disk fills up, the difference between a quick fix and a full outage is knowing about it early.

In this project, you will write a Bash shell script that monitors your Linux system's health, add colour-coded alerts when resources cross thresholds you set, and push it to GitHub as a portfolio-ready repository.

What You'll Build

When you run your finished script, you see a clean colour-coded report of your machine's CPU, memory, disk usage, and uptime printed straight to your WSL2 terminal.

By the end of this project, you'll have:

  • A single command that instantly shows your system's health status: CPU, memory, disk, and uptime in one glance.
  • Custom thresholds (e.g., 80% CPU) that fire red alerts when a resource is under pressure.
  • A GitHub repository with a professional README that demonstrates Linux and scripting skills to recruiters.
  • Secret Mission: Add network interface monitoring and log historical snapshots to a timestamped file.

Are there any prerequisites?

This project assumes you already have Windows 11 with WSL2 installed, VS Code installed, and a GitHub account created. Step 1 handles everything else, including configuring Git and setting up SSH authentication.

Before We Start

Before we dive into the terminal, let's lock in what you're about to build and why it matters for your career.

Verify Your WSL2 Environment and Configure Git

Before writing any scripts, you need a working Linux environment and a configured Git identity. Without Git set up, your commits show as "unknown author" and you cannot push code to GitHub.

In this step you will verify your WSL2 Ubuntu environment, configure Git with your name and email, and connect to GitHub using SSH keys. This SSH connection is the same authentication method Cloud Engineers use daily to connect to remote servers.

In this step, get ready to:
  • Verify your Ubuntu environment is working and up to date.
  • Configure Git with your identity and default branch name.
  • Generate an SSH key and connect it to your GitHub account.
Verify your WSL2 environment and update packages

Your Ubuntu terminal is already open. The first thing to confirm is that the system can see itself and reach the internet to download updates.

  • Check your Ubuntu version by running this command:
cat /etc/os-release

You should see output that includes Ubuntu and a version number. This confirms WSL2 is running a real Linux distribution.

  • Update your package lists and upgrade installed packages by running this command:
sudo apt update && sudo apt upgrade

What does this command do?

This is actually two commands joined by &&. The first part (sudo apt update) downloads the latest list of available packages. The second part (sudo apt upgrade) installs newer versions of packages you already have.

The && means the second command only runs if the first one succeeds.

What prompts will I see?

If this is your first time using sudo in this session, you will be asked for your Ubuntu password. Type it and press Enter (the characters will not appear on screen as you type).

If there are packages to upgrade, you will see a prompt asking Do you want to continue? [Y/n]. Type Y and press Enter.

Once the upgrade completes, you should see a line ending with something like 0 newly installed, X upgraded or All packages are up to date. Your environment is now current.

Seeing a password error or permission denied?

Make sure you are typing your Ubuntu user password (the one you set when WSL2 was first installed), not your Windows password. The cursor stays blank while you type because Linux hides password input.

help me troubleshoot a password or permission error with sudo in WSL2 Ubuntu

Install and configure Git

Git tracks every change you make to your code and lets you push it to GitHub. Before it can do that, it needs to know who you are.

  • Check if Git is already installed by running:
git --version

✔️ I see a version number

Git is already installed. Move on to the configuration commands below.

ⓧ Command not found

  • Install Git by running:
sudo apt install git

After the install finishes, run git --version again to confirm you see a version number.

  • Configure your Git identity by running these three commands (replace the placeholder values with your own name and GitHub email):
git config --global user.name "[[YOURNAME="your full name"]]"
git config --global user.email "[[YOUR_EMAIL="your GitHub email address"]]"
git config --global init.defaultBranch main

What do these commands do?

The first two commands attach your name and email to every commit you make. GitHub uses the email to link commits to your profile.

The third command sets main as the default branch name for any new repository you create. This matches GitHub's default convention.

  • Verify your configuration by running:
git config --global --list

You should see your name, email, and init.defaultbranch=main listed in the output.

Not seeing your name or email in the output?

Run the git config --global user.name command again and make sure you included the quotes around your name. If you made a typo, just re-run the command with the correct value.

help me fix my Git configuration in WSL2

Generate an SSH key and connect to GitHub

An SSH key is a pair of files that proves your identity without a password. You will generate this key pair, then give the public half to GitHub so it recognises your machine.

  • Generate a new SSH key by running this command (use the same email you configured in Git above):
ssh-keygen -t ed25519 -C "[[YOUR_EMAIL="your GitHub email address"]]"

What prompts will I see?

You will see three prompts in sequence:

  • "Enter a file in which to save the key" - press Enter to accept the default location.
  • "Enter passphrase (empty for no passphrase)" - press Enter for no passphrase (simplest for this project).
  • "Enter same passphrase again" - press Enter again.

You should see a message saying your key has been saved, along with a randomart image. This confirms the key pair now exists at ~/.ssh/id_ed25519 (private) and ~/.ssh/id_ed25519.pub (public).

  • Start the SSH agent and add your key to it by running these commands:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

You should see Agent pid followed by a number, then Identity added. This means your key is loaded and ready to use.

  • Copy your public key to the Windows clipboard by running:
cat ~/.ssh/id_ed25519.pub | clip.exe

Nothing visible happens in the terminal, but your public key is now on your clipboard ready to paste.

  • Open your browser and go to GitHub.
  • Click your profile picture in the top-right corner.
  • Click Settings.
  • In the left sidebar, click SSH and GPG keys.
  • Click New SSH key.
  • In the Title field, type a name like WSL2 Ubuntu.
  • In the Key field, paste your key (Ctrl+V).
  • Click Add SSH key.

GitHub may ask you to confirm your password. After confirming, you should see your new key listed on the SSH keys page.

Now it is time to test whether GitHub recognises your machine. Before you run this next command, what do you think will happen? Will GitHub accept or reject the connection?

  • Test your SSH connection by running:
ssh -T git@github.com

What about the fingerprint warning?

The first time you connect, you will see a message asking whether you want to continue connecting. It will show a fingerprint for github.com. Type yes and press Enter to add GitHub to your list of known hosts.

You should see the message:

Hi USERNAME! You've successfully authenticated, but GitHub does not provide shell access.

If you see your GitHub username in that message, your SSH connection is working. Your machine can now push code to any repository you own on GitHub.

Seeing Permission denied (publickey)?

This means GitHub did not recognise your key. Double-check that you pasted the full contents of ~/.ssh/id_ed25519.pub (the public key, ending in .pub) into GitHub, not the private key. Run cat ~/.ssh/id_ed25519.pub to see the key and try pasting it again.

help me fix SSH Permission denied when connecting to GitHub from WSL2

Why SSH instead of HTTPS?

SSH teaches a skill you will use every day in Cloud and DevOps roles. Connecting to EC2 instances, configuring servers, and deploying code all rely on SSH keys. Learning it now means one less thing to figure out on the job.

HTTPS authentication requires a personal access token that expires and adds complexity when working across WSL2 and Windows. SSH is a one-time setup that works everywhere.

Your environment is ready. Git knows who you are, and GitHub trusts your machine. Next up, you will write a shell script that reports your system's vital signs.

Write a Basic System Monitor Script

Your Linux environment is ready and Git knows who you are. Now it is time to write something that actually runs.

In this step, you will create a shell script that reads your system's CPU, memory, and disk usage and prints the numbers to your terminal. The output will be raw percentages with no formatting or intelligence. That simplicity is intentional. You need to prove the core Linux commands work before layering alerts on top in the next step.

In this step, get ready to:
  • Create a project directory with an initialized Git repository.
  • Write a Bash script that reports CPU, memory, and disk usage.
  • Run the script and see live system stats in your terminal.
Create your project directory and initialize Git

Every project starts with a dedicated folder and version control. You will create a directory on your Desktop, move into it, and initialize a Git repository so your work is tracked from the very first file.

  • Switch back to your Ubuntu terminal from the previous step.
  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create your project folder, move into it, and initialize a Git repository by running these commands:
mkdir linux-system-monitor
cd linux-system-monitor
git init
  • Confirm the repository was created by running:
ls -la

You should see a .git directory listed in the output. This is where Git stores all version history.

Don't see .git in the output?

Make sure you ran git init inside the linux-system-monitor folder, not in ~/Desktop directly. Run pwd to check you are in ~/Desktop/linux-system-monitor.

help me debug why git init did not create a .git directory

Write the CPU monitoring section

Your script will use three Linux commands to read system metrics: top for CPU, free for memory, and df for disk. You will start with the script header and CPU section, then add the rest.

  • Create system_monitor.sh and open it in your editor by running:
touch system_monitor.sh
code system_monitor.sh

What does this do?

touch creates an empty file. code opens it in VS Code through the WSL integration, so you can edit with a graphical editor while the file lives inside your Linux filesystem.

  • Paste the following code into system_monitor.sh:
#!/bin/bash

# ===========================================
# Linux System Health Monitor
# ===========================================

# Threshold values (percentage)
CPU_THRESHOLD=80
MEMORY_THRESHOLD=80
DISK_THRESHOLD=80

# CPU Usage
cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}')
cpu_usage=${cpu_usage%.*}
echo "CPU Usage: ${cpu_usage}%"

What does this code do?

  • #!/bin/bash is the shebang line. It tells Linux to run this file using the Bash shell.
  • The three _THRESHOLD variables define alert limits. They do nothing yet, but you will wire them up in the next step.
  • top -bn1 runs top in batch mode for one iteration (so it exits immediately instead of running interactively).
  • grep "Cpu(s)" filters to the line showing CPU percentages.
  • awk '{print $2 + $4}' adds the user and system CPU values together to get total usage.
  • ${cpu_usage%.*} strips the decimal portion so you get a clean integer for comparisons.
  • Save the file in VS Code with Ctrl+S.
  • Back in your Ubuntu terminal, make the script executable and run it by running:
chmod +x system_monitor.sh
./system_monitor.sh

You should see a single line like CPU Usage: 12% (your number will vary).

Seeing 'Permission denied' or no output?

If you see Permission denied, confirm chmod +x ran without errors. Run ls -l system_monitor.sh and check the permissions start with -rwx.

If you see no output or a blank line, open the file and check the shebang line is exactly #!/bin/bash with no spaces before the #.

my system_monitor.sh script is not running correctly in WSL2, help me debug

Add memory and disk monitoring

CPU is working. Now add the remaining two metrics so your script reports a complete picture of system health.

  • In VS Code, add the following code at the bottom of system_monitor.sh, below the CPU section:
# Memory Usage
memory_usage=$(free | awk '/Mem/ {printf("%3.1f", ($3/$2) * 100)}')
memory_usage=${memory_usage%.*}
echo "Memory Usage: ${memory_usage}%"

# Disk Usage
disk_usage=$(df -h / | awk '/\// {print $(NF-1)}')
disk_usage=${disk_usage%?}
echo "Disk Usage (/): ${disk_usage}%"

What does this code do?

  • free displays available and used memory. The awk filter finds the Mem line and calculates used memory as a percentage of total.
  • ${memory_usage%.*} strips the decimal, just like the CPU section.
  • df -h / shows disk space for the root partition in human-readable format.
  • $(NF-1) grabs the second-to-last column, which contains the usage percentage with a trailing % sign.
  • ${disk_usage%?} removes that trailing % character so you have a clean number.
  • Save system_monitor.sh in VS Code with Ctrl+S.

✔️ Awesome, I've got everything!

Great. Confirm you have saved the file and move on to the final run below.

ⓧ I'd like to double check the full code

Here is the complete system_monitor.sh file. Make sure yours matches exactly:

#!/bin/bash

# ===========================================
# Linux System Health Monitor
# ===========================================

# Threshold values (percentage)
CPU_THRESHOLD=80
MEMORY_THRESHOLD=80
DISK_THRESHOLD=80

# CPU Usage
cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}')
cpu_usage=${cpu_usage%.*}
echo "CPU Usage: ${cpu_usage}%"

# Memory Usage
memory_usage=$(free | awk '/Mem/ {printf("%3.1f", ($3/$2) * 100)}')
memory_usage=${memory_usage%.*}
echo "Memory Usage: ${memory_usage}%"

# Disk Usage
disk_usage=$(df -h / | awk '/\// {print $(NF-1)}')
disk_usage=${disk_usage%?}
echo "Disk Usage (/): ${disk_usage}%"

Before you run the script, what do you expect to see in the output? Think about what each of the three echo statements will print.

  • Run your completed script by running:
./system_monitor.sh

You should see three lines of output showing your system's current CPU, memory, and disk usage percentages. The exact numbers depend on your machine's current load.

What should I see?

Your output will look something like this (your numbers will differ):

CPU Usage: 5%
Memory Usage: 32%
Disk Usage (/): 12%

As long as you see three lines with percentage values, your script is working correctly.

Seeing an error or missing lines?

If only some lines print, check that you have a blank line between each section in your file. A missing newline can cause Bash to misparse the next command.

If you see awk: command not found, run sudo apt install gawk to install it. This is rare on Ubuntu but can happen on minimal WSL images.

help me debug why my system_monitor.sh is not printing all three metrics correctly

Your system monitor is alive. It reads real data from your Linux kernel and prints it to your terminal. Next up, you will transform these raw numbers into a colour-coded report with threshold alerts that tell you at a glance when something needs attention.

Add Threshold Alerts and Formatted Output

Your script collects CPU, memory, and disk numbers. But right now it just dumps them as plain text.

Real monitoring tools do not make you squint at raw percentages. They highlight problems instantly. In this step, you will add colour-coded labels and threshold alerts so a single glance tells you whether your system is healthy, moderate, or in trouble.

In this step, get ready to:
  • Add a send_alert function that prints red warnings when a metric exceeds its threshold.
  • Add conditional logic that colour-codes each metric as HEALTHY, MODERATE, or HIGH.
  • Add a formatted header with the current date, uptime, and section separators.
Add the alert function and report header

Before you add any conditional logic, you need the function those conditionals will call. You will also add a header that stamps every report with the current date and system uptime.

  • In your WSL2 terminal, open system_monitor.sh in your editor by running:
nano ~/linux-system-monitor/system_monitor.sh
  • Find the # CPU Usage comment. Add the following code above it (below the DISK_THRESHOLD=80 line):
# Function to send alert
send_alert() {
    echo "$(tput setaf 1)  ALERT: $1 usage at $2% - exceeds ${3}% threshold!$(tput sgr0)"
}

# Header
echo "==========================================="
echo "  System Health Report - $(date '+%Y-%m-%d %H:%M:%S')"
echo "==========================================="
echo ""

# Uptime
echo "Uptime:"
echo "  $(uptime -p)"
echo ""

What does this code do?

  • send_alert() is a reusable function. It takes three arguments (the metric name, its current value, and the threshold) and prints a red warning using tput setaf 1 for red text and tput sgr0 to reset the colour.
  • The header uses date '+%Y-%m-%d %H:%M:%S' to stamp the report with the current time.
  • uptime -p prints how long the system has been running in a human-readable format like "up 2 hours, 15 minutes".
  • Save the file by pressing Ctrl+O then Enter, and exit with Ctrl+X.
  • Run the script to see the new header by running:
./system_monitor.sh

You should see a dated header and uptime at the top, followed by the same raw metric lines as before.

Not seeing the header?

  • Make sure you added the new code above the # CPU Usage comment, not below it.
  • Check that you did not accidentally delete the DISK_THRESHOLD=80 line. The function must sit between the thresholds and the CPU section.
  • help me debug my system_monitor.sh header
Add colour-coded conditional logic for CPU

The script still prints plain text for each metric. You will replace the simple echo line for CPU with a conditional block that checks the value against the threshold and prints it in green, yellow, or red.

  • Open system_monitor.sh again by running:
nano ~/linux-system-monitor/system_monitor.sh
  • Find this line in the CPU section:
echo "CPU Usage: ${cpu_usage}%"
  • Delete that line and replace it with the following conditional block:
echo "CPU Usage:"
if ((cpu_usage >= CPU_THRESHOLD)); then
    echo "$(tput setaf 1)  ${cpu_usage}% [HIGH]$(tput sgr0)"
    send_alert "CPU" "$cpu_usage" "$CPU_THRESHOLD"
elif ((cpu_usage >= 50)); then
    echo "$(tput setaf 3)  ${cpu_usage}% [MODERATE]$(tput sgr0)"
else
    echo "$(tput setaf 2)  ${cpu_usage}% [HEALTHY]$(tput sgr0)"
fi
echo ""

What does this conditional do?

  • tput setaf 1 sets text to red, tput setaf 3 sets yellow, and tput setaf 2 sets green. tput sgr0 resets back to normal.
  • If CPU is at or above the threshold (80%), it prints red with [HIGH] and calls send_alert.
  • If CPU is between 50% and 79%, it prints yellow with [MODERATE].
  • Below 50%, it prints green with [HEALTHY].
  • Save the file with Ctrl+O then Enter, exit with Ctrl+X.
  • Run the script to check CPU now has colour:
./system_monitor.sh

Your CPU line should now display a colour-coded percentage with a status label like [HEALTHY] or [MODERATE]. The Memory and Disk lines are still plain text.

CPU line still showing plain text?

  • Make sure you deleted the old echo "CPU Usage: ${cpu_usage}%" line entirely. If both the old echo and the new conditional exist, you will see duplicated output.
  • Check that the if ((cpu_usage >= CPU_THRESHOLD)) line uses double parentheses for arithmetic comparison.
  • help me fix the colour output in my CPU conditional
Add colour-coded status for memory and disk

The pattern is identical for Memory and Disk. You will apply the same conditional structure to both metrics and add a footer to close out the report.

  • Open system_monitor.sh again:
nano ~/linux-system-monitor/system_monitor.sh
  • Find this line in the Memory section:
echo "Memory Usage: ${memory_usage}%"
  • Delete that line and replace it with:
echo "Memory Usage:"
if ((memory_usage >= MEMORY_THRESHOLD)); then
    echo "$(tput setaf 1)  ${memory_usage}% [HIGH]$(tput sgr0)"
    send_alert "Memory" "$memory_usage" "$MEMORY_THRESHOLD"
elif ((memory_usage >= 50)); then
    echo "$(tput setaf 3)  ${memory_usage}% [MODERATE]$(tput sgr0)"
else
    echo "$(tput setaf 2)  ${memory_usage}% [HEALTHY]$(tput sgr0)"
fi
echo ""

Same pattern, different variables

This block is structurally identical to the CPU conditional. The only differences are the variable names (memory_usage, MEMORY_THRESHOLD) and the label passed to send_alert.

  • Now find this line in the Disk section:
echo "Disk Usage (/): ${disk_usage}%"
  • Delete that line and replace it with the Disk conditional plus a report footer:
echo "Disk Usage (/):"
if ((disk_usage >= DISK_THRESHOLD)); then
    echo "$(tput setaf 1)  ${disk_usage}% [HIGH]$(tput sgr0)"
    send_alert "Disk" "$disk_usage" "$DISK_THRESHOLD"
elif ((disk_usage >= 50)); then
    echo "$(tput setaf 3)  ${disk_usage}% [MODERATE]$(tput sgr0)"
else
    echo "$(tput setaf 2)  ${disk_usage}% [HEALTHY]$(tput sgr0)"
fi
echo ""

echo "==========================================="
echo "  Report complete."
echo "==========================================="

What is the footer for?

The closing separator lines visually mark the end of the report. When you run the script inside a busy terminal session, the separator makes it easy to find where the report starts and ends.

  • Save with Ctrl+O then Enter, exit with Ctrl+X.
  • Run the script to see the full formatted report:
./system_monitor.sh

You should now see a clean report with a header, uptime, and all three metrics colour-coded with status labels. The footer closes the report at the bottom.

Seeing a syntax error?

  • Check that every if block ends with fi. A missing fi causes "unexpected end of file" errors.
  • Make sure quotation marks are balanced. Each echo line must have matching opening and closing double quotes.
  • Confirm you typed elif (not elseif or else if). Bash uses elif as one word.
  • help me fix a syntax error in my system_monitor.sh conditionals
Verify the threshold alert fires

Your report looks good, but you have not seen the alert trigger yet. Your disk usage is almost certainly below 80%. To prove the alert works, you will temporarily lower the threshold.

  • Before you test, predict: what do you think will happen if you change DISK_THRESHOLD to 1?
  • Open system_monitor.sh and find this line near the top:
DISK_THRESHOLD=80
  • Change it to:
DISK_THRESHOLD=1
  • Save the file and run the script:
./system_monitor.sh

You should see the Disk Usage line in red with [HIGH], followed by a red ALERT message. That is your send_alert function in action.

  • Now change DISK_THRESHOLD back to 80 and save the file. You do not want a false alert every time you run the script.

No red alert for disk?

  • Make sure you changed DISK_THRESHOLD=80 to DISK_THRESHOLD=1 (the number one, not the letter L).
  • Confirm the Disk conditional uses DISK_THRESHOLD (all caps, matching the variable at the top). A typo like Disk_Threshold creates a different variable in Bash.
  • help me figure out why my disk alert is not triggering

✔️ Awesome, I've got everything!

Great. Make sure you saved system_monitor.sh with DISK_THRESHOLD set back to 80.

ⓧ I'd like to double check the full code

Scroll through your file and confirm these sections appear in order:

  • The shebang line #!/bin/bash and the header comment.
  • Three threshold variables: CPU_THRESHOLD=80, MEMORY_THRESHOLD=80, DISK_THRESHOLD=80.
  • The send_alert() function definition.
  • The Header section with echo separators and date.
  • The Uptime section with uptime -p.
  • The CPU section with top and the if/elif/else/fi conditional block.
  • The Memory section with free and its own conditional block.
  • The Disk section with df and its own conditional block.
  • The footer separator with "Report complete." at the bottom.

If anything is out of order or missing, compare against the chunks above and re-edit the relevant section.

Your script now tells you at a glance whether your system is healthy. Next up, you will write a professional README and push everything to GitHub so recruiters can see your work.

Create a Professional README and Push to GitHub

Your script works, but nobody can find it or understand what it does without documentation. Code without a README is invisible to recruiters browsing your GitHub profile.

A professional README transforms your script from a personal exercise into a portfolio piece. It demonstrates communication skills alongside technical ability. In this step, you will write a README and push everything to GitHub.

In this step, get ready to:
  • Create a professional README documenting your project.
  • Push all files to a public GitHub repository.
Create the README header, features, and requirements

A good README answers three questions immediately: what is this project, what does it do, and how do I run it.

  • Create the first part of your README.md by running this command:
cat > README.md << 'EOF'
# Linux System Health Monitor

A lightweight Bash script that monitors CPU, memory, and disk usage on Linux systems with colour-coded threshold alerts.

## Features

- Real-time CPU, memory, and disk usage monitoring
- Configurable threshold alerts (default: 80%)
- Colour-coded output (green = healthy, yellow = moderate, red = high)
- System uptime display

## Requirements

- Linux environment (Ubuntu on WSL2, or any Linux distribution)
- Bash shell
- Standard utilities: `top`, `free`, `df`, `uptime`, `awk`

## Usage

```bash
chmod +x system_monitor.sh
./system_monitor.sh
```
EOF

What does this command do?

The cat > README.md << 'EOF' syntax is called a heredoc. It writes everything between the two EOF markers into the file.

The single quotes around 'EOF' prevent the shell from interpreting special characters inside the content. This keeps your markdown backticks intact.

  • Confirm the file was created by running:
head -5 README.md

You should see the first five lines of your README, starting with # Linux System Health Monitor.

Add sample output and customisation sections

Sample output lets someone see what your script produces without running it. This is especially useful for recruiters who may not have a Linux machine handy.

  • Append the sample output section to your README by running:
cat >> README.md << 'EOF'

## Sample Output

```
===========================================
  System Health Report - 2026-08-06 14:30:00
===========================================

Uptime:
  up 2 hours, 15 minutes

CPU Usage:
  12% [HEALTHY]

Memory Usage:
  45% [MODERATE]

Disk Usage (/):
  23% [HEALTHY]

===========================================
  Report complete.
===========================================
```
EOF

Why use >> instead of > here?

A single > overwrites the file. A double >> appends to the end of the existing file. Since you already wrote the first section, you need to append the rest.

  • Append the customisation and learning sections by running:
cat >> README.md << 'EOF'

## Customisation

Edit the threshold variables at the top of `system_monitor.sh`:

```bash
CPU_THRESHOLD=80
MEMORY_THRESHOLD=80
DISK_THRESHOLD=80
```

## What I Learned

- Linux system monitoring commands (`top`, `free`, `df`, `uptime`)
- Shell scripting fundamentals (variables, functions, conditionals)
- Text processing with `awk` and string manipulation in Bash
- Git version control and GitHub workflow

## Author

Built as a Cloud/DevOps learning project.
EOF

Why include a What I Learned section?

Recruiters scanning your GitHub want to see self-awareness about the skills you are building. This section signals that you understand the underlying concepts, not just the syntax.

  • Verify the complete README by checking the last few lines:
tail -5 README.md

You should see the ## Author heading and the final line Built as a Cloud/DevOps learning project. in the output.

README looks wrong or has extra blank lines?

If you made a typo in one of the heredoc commands, delete the file and start over by running rm README.md and then re-running the three cat commands from above.

Make sure each EOF appears on its own line with no spaces before it. A leading space prevents the shell from recognising the end marker.

help me fix my README.md heredoc in bash

✔️ Awesome, I've got everything!

Great. Make sure you have saved your file and you are ready to move on.

ⓧ I'd like to double check the full code

Your README.md should contain the following three sections you built above, in order:

  • The header, features, requirements, and usage section (first heredoc).
  • The sample output section (second heredoc).
  • The customisation, what I learned, and author sections (third heredoc).

Run cat README.md to view the entire file and confirm it matches what you expect. Each section heading should start with ## and the file should end with the Author section.

Create a .gitignore and push to GitHub

Before committing, you will add a .gitignore file to exclude future log files from version control. Then you will create a repository on GitHub and push your code.

  • Create the .gitignore file by running:
echo "logs/" > .gitignore

What is .gitignore?

Git reads this file to decide which files and folders to ignore when tracking changes. The logs/ entry tells Git to never commit anything inside a logs directory. You will use this directory in the Secret Mission.

  • Stage all your files for commit by running:
git add .
  • Verify what Git has staged by running:
git status

You should see three files listed in green: .gitignore, README.md, and system_monitor.sh.

  • Commit your files with a meaningful message by running:
git commit -m "Add system health monitor script with README"

Git confirms the commit with a short summary showing the number of files changed.

Now you need to create the remote repository on GitHub so you have somewhere to push to.

  • Open your browser and go to github.com.
  • In the upper-right corner of the page, click the + menu and select New repository.
  • In the Repository name field, type linux-system-monitor.
  • Select Public for the repository visibility.
  • Do NOT select Add a README file or any other initialisation options. You already have a README locally.
  • Click Create repository.

Why leave the repository empty?

If you initialise with a README on GitHub, it creates a commit that conflicts with your local commit. Starting empty lets you push your existing local history cleanly.

GitHub shows a Quick Setup page with instructions. You will use the SSH URL to connect your local repository to GitHub.

  • Back in your WSL2 terminal, add the GitHub remote by running:
git remote add origin git@github.com:[[GITHUB_USERNAME="your-github-username"]]/linux-system-monitor.git
  • Push your code to GitHub by running:
git push -u origin main

What does -u origin main mean?

The -u flag sets origin/main as the default upstream branch. After this, future pushes only need git push without extra arguments.

Before you check your repository in the browser, what do you expect to see on the GitHub page?

  • Open your browser and visit https://github.com/your-github-username/linux-system-monitor.

You should see your rendered README with the project title, features list, sample output, and all other sections displayed nicely. The file list above the README shows .gitignore, README.md, and system_monitor.sh.

Push failed or permission denied?

If you see Permission denied (publickey), your SSH key is not connecting. Run ssh -T git@github.com to test the connection. If it fails, revisit Step 1 where you added your SSH key to GitHub.

If you see an error about the remote already existing, you may have typed the git remote add command twice. Run git remote -v to check, and git remote remove origin to reset it before trying again.

help me fix my git push to GitHub from WSL2

Secret mission

Add Network Monitoring and Log History

Production monitoring tools do not just display data once. They track trends over time and cover network interfaces. In this secret mission, you will add a --log flag that saves plain-text snapshots to a timestamped file, and a network interfaces section that shows active connections and their IP addresses.

Clean Up Your Resources

Clean Up Your Resources

Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs entirely locally and on a free GitHub account, so there are no ongoing costs.

Resources you used:

  • GitHub repository linux-system-monitor (free, no cost).
  • SSH key pair in ~/.ssh/ (local files, no cost).
  • Project directory ~/linux-system-monitor/ (local files, no cost).

Keep everything running

No action needed. Choose this if you want to keep your repository as a portfolio piece on GitHub. Your SSH key stays ready for future projects.

  • Your GitHub repository remains public and visible to recruiters.
  • Your SSH key in ~/.ssh/ continues to authenticate you with GitHub for any future repositories.
  • Your local project directory stays on disk, ready to edit and re-run.

Pause - I'll come back to this later

There are no running processes or paid resources to pause. Everything is stored as files on your local machine and on GitHub's free tier.

  • Your repository stays on GitHub at no cost.
  • Your SSH key and local files remain on disk until you decide to remove them.
  • Come back any time and pick up where you left off by opening your WSL2 terminal and running cd ~/linux-system-monitor.

Delete - I don't want to use this again

Remove all project resources and start fresh. Follow each step below to fully clean up.

  • Delete the GitHub repository: navigate to your repository on GitHub, click Settings, scroll to the Danger Zone section, and click Delete this repository. Confirm by typing the repository name when prompted.
  • Remove the local project directory by running this in your WSL2 terminal:
rm -rf ~/linux-system-monitor
  • Remove the SSH key pair if you no longer need GitHub SSH access:
rm ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub

Keep your SSH key?

If you plan to use GitHub for future projects, keep the SSH key. Deleting it means you will need to generate a new key and add it to GitHub again before you can push code.

Nice Work!

Nice Work!

You just built a production-style Linux system health monitor and shipped it to GitHub. That script is the same pattern Cloud Support Engineers reach for when triaging live server issues.

Here's what you accomplished:

  • Built a system health monitor using core Linux commands (top, free, df, uptime) with colour-coded threshold alerts.
  • Wrote a Bash script using variables, functions, conditionals, and text processing with awk.
  • Configured Git with SSH authentication in WSL2 and pushed to a professional GitHub repository with a documented README.
  • Secret Mission: Extended the script with network interface monitoring and persistent timestamped logging to a daily log file.

Ready to quiz yourself?