Part 2: Python Server Status Checker
Build a Python monitor that labels and summarizes server disk usage.
Introduction
30 Second Summary
A server can support a website, an application, or a team’s shared tools. When its disk becomes too full, those services can slow down or stop working.
In this project, you will build a local server status checker with Python. It reads disk percentages and labels each server as healthy, warning, or critical.
What You'll Build
You’ll run one script and see a readable report for every server, followed by totals for each health status.
By the end of this project, you'll have:
- Clear Boolean checks that turn comparisons into True or False results.
- Organized server data stored in lists and dictionaries.
- A loop-based report that shows disk percentages and counts healthy, warning, and critical servers.
- Secret Mission: Accept disk usage from a person, handle invalid input, and save a timestamped report to a text file.
Are there any prerequisites?
This project assumes you completed Project 1 or already know how to save and run a .py file.
You only need the local Linux environment, Xed, and the existing python3 command. The project uses no external packages or cloud resources.
Before We Start
Before you start coding, lock in the tool you are building and the problem it solves. You’ll create a local monitor that turns server disk percentages into clear health reports.
Get Ready to Monitor Servers
Server monitoring starts with a simple question: is a machine healthy enough to keep doing its job? Teams answer it by checking measurements such as disk usage, memory, and network activity.
In this step, you’ll learn the monitoring goal and prepare a local folder for the checker. Everything runs on your computer, so no real server or cloud account is required.
In this step, get ready to:
- Understand servers, disk usage, and monitoring.
- Confirm that Python runs in your terminal.
- Create the local project folder.
Understand the monitoring goal
What is a server?
A server is a computer or program that provides something to other computers. A web server sends pages, while a database server stores application information.
Each server name in this project represents one machine that a DevOps or system administration team might watch.
What are disk usage and monitoring?
Disk usage is the percentage of storage space already filled with files. A reading of 72 means 72 percent of the disk is in use.
Monitoring means checking measurements regularly so a team can respond before a service fails.
Confirm that Python runs
- Open the standard Linux terminal from your application search.
- Confirm that Python can run a short instruction by entering this command:
python3 -c 'print("Python is ready")'
You should see Python is ready. This proves that the interpreter can run your scripts.
Python command not working?
- Check that the command begins with python3.
- Keep the words inside matching quotation marks.
- Help me run the Python readiness check.
Create the project folder
- Move to your Desktop by running this command:
cd ~/Desktop
- Create the python-server-status-checker folder and move into it by running these commands:
mkdir -p python-server-status-checker
cd python-server-status-checker
Your terminal prompt should now end with python-server-status-checker. That folder keeps every lesson file together.
Your workspace is ready. Next, you’ll turn server facts into Boolean monitoring checks.
Create Boolean Checks
Your project folder is ready, and Python can run instructions. The checker now needs facts it can evaluate before it can choose a status.
A Boolean stores True or False. Monitoring tools use these values for questions such as whether a server is online or its disk is too full.
In this step, get ready to:
- Store server facts as Boolean values.
- Create results with comparison operators.
- Run the first monitoring script.
Build the Boolean checks
How do comparison operators work?
A comparison asks a question about two values. Python answers with True when the comparison is correct and False when it is not.
- > checks whether the left value is greater.
- == checks whether two values are equal.
- != checks whether two values are different.
- Open booleans.py in Xed by running this command:
xed booleans.py
- Create the first monitoring checks by entering this code in booleans.py:
# Store the server facts that we want to check.
server_is_online = True
disk_usage_percent = 82
disk_limit_percent = 80
# Compare the facts to create new Boolean results.
disk_is_over_limit = disk_usage_percent > disk_limit_percent
disk_is_full = disk_usage_percent == 100
server_is_offline = server_is_online != True
# Display each result with a clear label.
print("Server online:", server_is_online)
print("Disk over limit:", disk_is_over_limit)
print("Disk full:", disk_is_full)
print("Server offline:", server_is_offline)
What does this code do?
- server_is_online directly stores a Boolean fact.
- disk_usage_percent > disk_limit_percent creates a Boolean by comparing numbers.
- Clear variable names make the output easier to interpret.
- Save booleans.py.
- Return to the standard Linux terminal.
Before you run the script, should the disk-over-limit check be true or false?
- Test the saved checker by running this command:
python3 booleans.py
You should see Server online: True, Disk over limit: True, Disk full: False, and Server offline: False.
That is your first monitoring check working. Python has turned stored facts into visible Boolean results.
Seeing an error or different result?
- Write True with a capital T.
- Use == for comparison and = for assignment.
- Help me debug my Boolean checker.
Connect Booleans to monitoring
Why this matters in the real world
Real monitoring systems collect measurements and compare them with limits. The resulting facts can trigger dashboards, notifications, or automated fixes.
✔️ Awesome, I've got everything!
Your Boolean checker is saved and prints all four expected results.
ⓧ I'd like to double check the full code
# Store the server facts that we want to check.
server_is_online = True
disk_usage_percent = 82
disk_limit_percent = 80
# Compare the facts to create new Boolean results.
disk_is_over_limit = disk_usage_percent > disk_limit_percent
disk_is_full = disk_usage_percent == 100
server_is_offline = server_is_online != True
# Display each result with a clear label.
print("Server online:", server_is_online)
print("Disk over limit:", disk_is_over_limit)
print("Disk full:", disk_is_full)
print("Server offline:", server_is_offline)
You can now represent monitoring questions as true-or-false facts. Next, you’ll organize several server names in one list.
Manage Server Names
Your Boolean checker can evaluate one server fact. A full report also needs a clear way to keep several server names together.
A list stores multiple items in order. One list is easier to update than separate variables for every server.
In this step, get ready to:
- Store several server names in one list.
- Add and remove names with list methods.
- Complete the additional-server challenge.
Create the server list
Square brackets create a list, while commas separate its items. Each server name uses quotation marks because it is text.
- Open server_list.py in Xed by running this command:
xed server_list.py
- Build and update the server list by entering this code in server_list.py:
# Keep every server name in one ordered list.
server_names = ["web-01", "api-01", "db-01"]
# Add a new server and remove one that is retired.
server_names.append("cache-01")
server_names.remove("api-01")
# Display the updated group.
print(server_names)
What does this code do?
- append() adds an item to the end.
- remove() deletes the first matching item.
- The list keeps a predictable order for the future report.
- Save server_list.py.
- Return to the standard Linux terminal.
Before you run the script, which name should remove() delete?
- Test the list by running this command:
python3 server_list.py
You should see ['web-01', 'db-01', 'cache-01'].
List output looks different?
- Check every server name for matching quotation marks.
- Confirm that the requested remove() value exists.
- Help me debug my server list.
Challenge: add another server
A monitoring tool should grow without needing a new variable for every machine. Add worker-01 to the existing list.
✔️ I'll try it first
- Add worker-01 immediately after the existing append() line.
- Save server_list.py.
- Run the script again with the same terminal command.
ⓧ Let me check my work
# Add one more machine for the challenge.
server_names.append("worker-01")
You should now see ['web-01', 'db-01', 'cache-01', 'worker-01'].
Why this matters in the real world
DevOps teams may monitor hundreds of machines. Lists let automation treat those names as one collection.
✔️ Awesome, I've got everything!
Your saved list ends with worker-01 and prints four server names.
ⓧ I'd like to double check the full code
# Keep every server name in one ordered list.
server_names = ["web-01", "api-01", "db-01"]
# Add active servers and remove one that is retired.
server_names.append("cache-01")
server_names.append("worker-01")
server_names.remove("api-01")
# Display the updated group.
print(server_names)
Your server names now move as one group. Next, you’ll connect each name to a disk percentage.
Store Server Details
Your list keeps four server names in order. A useful report also needs to connect each name to the disk percentage that belongs to it.
A dictionary stores labeled key-value pairs. Each server name becomes a key, and its disk percentage becomes the matching value.
In this step, get ready to:
- Store disk percentages under server-name keys.
- Read a value by using its key.
- Update one stored percentage.
Build the disk-usage dictionary
How do key-value pairs work?
A key is the label before a colon, such as "web-01". The value after the colon stores that server’s measurement.
A dictionary lookup places the key inside square brackets. Python returns the matching value.
- Open server_details.py in Xed by running this command:
xed server_details.py
- Store and read the disk percentages by entering this code in server_details.py:
# Connect each server name to its disk usage percentage.
disk_usage_by_server = {
"web-01": 45,
"db-01": 91,
"cache-01": 68,
"worker-01": 76,
}
# Read one value by using its matching key.
web_disk_usage = disk_usage_by_server["web-01"]
print("web-01 disk usage:", web_disk_usage, "%")
What does this code do?
- disk_usage_by_server describes both the stored values and what connects them.
- The "web-01" lookup retrieves 45.
- The trailing comma makes future additions easier to edit.
- Save server_details.py.
- Return to the standard Linux terminal.
- Run the dictionary script with this command:
python3 server_details.py
You should see web-01 disk usage: 45 %. The key reached the correct value.
Dictionary lookup not working?
- Check that every key has matching quotation marks.
- Check that every key-value pair has a colon.
- Help me debug my server dictionary.
Update a stored percentage
Monitoring collects newer measurements for the same server. Assigning a value to an existing key replaces the older reading.
- Add these lines above the existing lookup:
# Replace the old reading with a newer disk measurement.
disk_usage_by_server["cache-01"] = 72
print("cache-01 disk usage:", disk_usage_by_server["cache-01"], "%")
- Save server_details.py.
- Run the saved script again with the same terminal command.
You should see cache-01 disk usage: 72 % before the existing web-server line.
Why this matters in the real world
Monitoring systems connect resource names to changing measurements. Dictionaries model that relationship directly.
✔️ Awesome, I've got everything!
Your dictionary stores four servers and shows the updated cache reading.
ⓧ I'd like to double check the full code
# Connect each server name to its disk usage percentage.
disk_usage_by_server = {
"web-01": 45,
"db-01": 91,
"cache-01": 68,
"worker-01": 76,
}
# Replace the old reading with a newer disk measurement.
disk_usage_by_server["cache-01"] = 72
print("cache-01 disk usage:", disk_usage_by_server["cache-01"], "%")
# Read another value by using its matching key.
web_disk_usage = disk_usage_by_server["web-01"]
print("web-01 disk usage:", web_disk_usage, "%")
Your server names now lead to their disk percentages. Next, you’ll convert each percentage into a health status.
Choose a Server Status
Your dictionary connects every server to a disk percentage. The checker now needs one shared rule that converts each number into a readable health label.
You’ll place the warning and critical thresholds inside a reusable function. One maintained rule can then classify every server consistently.
In this step, get ready to:
- Name the monitoring thresholds as constants.
- Build a reusable get_status() function.
- Test every status at its boundary.
Build the status function
Why use constants?
A threshold separates one status from another. This project uses 70 percent for warning and 90 percent for critical.
Uppercase names show that WARNING_THRESHOLD and CRITICAL_THRESHOLD should stay unchanged while the script runs.
- Open server_status.py in Xed by running this command:
xed server_status.py
- Create the thresholds and status function by entering this code in server_status.py:
# Keep the monitoring limits in one easy-to-find place.
WARNING_THRESHOLD = 70
CRITICAL_THRESHOLD = 90
def get_status(disk_usage_percent):
# Check the most serious condition first.
if disk_usage_percent >= CRITICAL_THRESHOLD:
return "critical"
elif disk_usage_percent >= WARNING_THRESHOLD:
return "warning"
else:
return "healthy"
# Confirm that one sample reaches the warning branch.
print("Status:", get_status(82))
How does the function choose?
- if checks the critical case first.
- elif checks the warning case only when the critical check is false.
- else handles every percentage below 70.
- Save server_status.py.
- Return to the standard Linux terminal.
Before you run the script, which branch should 82 reach?
- Test the function by running this command:
python3 server_status.py
You should see Status: warning. The value is at least 70 but remains below 90.
Function not returning warning?
- End each conditional heading with a colon.
- Use four spaces inside every branch.
- Help me debug get_status().
Test every status
- Replace the final test print with these boundary checks:
# Reuse one function for all three status categories.
print("45%:", get_status(45))
print("70%:", get_status(70))
print("90%:", get_status(90))
- Save server_status.py.
- Run the saved script again with the same terminal command.
You should see 45%: healthy, 70%: warning, and 90%: critical on separate lines.
Why this matters in the real world
Functions keep one copy of an important rule. A team can change a threshold once instead of finding repeated conditionals throughout a script.
✔️ Awesome, I've got everything!
Your function classifies healthy, warning, and critical boundary values.
ⓧ I'd like to double check the full code
# Keep the monitoring limits in one easy-to-find place.
WARNING_THRESHOLD = 70
CRITICAL_THRESHOLD = 90
def get_status(disk_usage_percent):
# Check the most serious condition first.
if disk_usage_percent >= CRITICAL_THRESHOLD:
return "critical"
elif disk_usage_percent >= WARNING_THRESHOLD:
return "warning"
else:
return "healthy"
# Reuse one function for all three status categories.
print("45%:", get_status(45))
print("70%:", get_status(70))
print("90%:", get_status(90))
Your status rule is clear and reusable. Next, you’ll apply it to every server with a loop.
Build the Server Report
Your function can classify any one disk percentage. Copying that function call for every server would still make the report longer each time the team adds a machine.
A loop repeats one block of code for every item in a collection. You’ll use one loop to report every server, display its percentage, and count each status.
In this step, get ready to:
- Combine the status function with the server dictionary.
- Refactor repeated work into a loop.
- Count healthy, warning, and critical servers.
Build the report foundation
- Open server_report.py in Xed by running this command:
xed server_report.py
- Add the shared thresholds and status function by entering this code in server_report.py:
# Keep the monitoring limits shared by every server.
WARNING_THRESHOLD = 70
CRITICAL_THRESHOLD = 90
def get_status(disk_usage_percent):
# Return one label from the supplied disk percentage.
if disk_usage_percent >= CRITICAL_THRESHOLD:
return "critical"
elif disk_usage_percent >= WARNING_THRESHOLD:
return "warning"
else:
return "healthy"
# Confirm the shared function works before building the report.
print("Test status:", get_status(82))
Why start with one shared function?
This file begins with one copy of the thresholds and one copy of get_status(). Every server in the report will use this shared logic.
- Save server_report.py in Xed.
- Return to the standard Linux terminal.
- Run the foundation with this command:
python3 server_report.py
You should see Test status: warning. This small check proves the shared rule works before more code depends on it.
Foundation check failing?
- Compare the thresholds and branch order with the previous step.
- Check that the test call appears outside the function indentation.
- Help me debug the report foundation.
Challenge: refactor with a loop
Why do loops reduce repetition?
A for loop takes each dictionary key in order and runs the indented block once. Adding another dictionary entry then gives the loop another server to process.
This removes repeated status sections, which lowers the chance that one server uses different rules by mistake.
Try replacing the final test print with a dictionary and a loop. The loop needs to read each percentage, call get_status(), and print the server name, percentage, and status.
✔️ I'll try it first
- Create disk_usage_by_server with the four server readings from earlier.
- Loop through each server_name.
- Look up the percentage and pass it to get_status().
- Print all three values on one report line.
ⓧ Let me check my work
# Store the latest disk percentage for each server.
disk_usage_by_server = {
"web-01": 45,
"db-01": 91,
"cache-01": 72,
"worker-01": 76,
}
# Process every server with the same status function.
for server_name in disk_usage_by_server:
disk_usage_percent = disk_usage_by_server[server_name]
status = get_status(disk_usage_percent)
print(server_name, "-", disk_usage_percent, "% -", status)
- Save server_report.py after replacing the test print.
- Return to the standard Linux terminal.
Before you run the report, how many status lines should one loop produce from four dictionary entries?
- Test the loop-based report with this command:
python3 server_report.py
What should you see?
- You should see web-01 - 45 % - healthy.
- You should see db-01 - 91 % - critical.
- You should see warning lines for cache-01 and worker-01.
The repeated decision sections are gone. One loop now processes every stored server and displays each disk percentage.
Challenge: count each status
Status totals help a team see the overall situation without reading every line. Start each counter at zero, then increase the matching counter inside the loop.
- Replace the current loop with this counted version:
# Start one counter for each possible status.
healthy_count = 0
warning_count = 0
critical_count = 0
# Process each server and count the returned status.
for server_name in disk_usage_by_server:
disk_usage_percent = disk_usage_by_server[server_name]
status = get_status(disk_usage_percent)
print(server_name, "-", disk_usage_percent, "% -", status)
if status == "critical":
critical_count += 1
elif status == "warning":
warning_count += 1
else:
healthy_count += 1
# Display the totals after every server is processed.
print("Healthy servers:", healthy_count)
print("Warning servers:", warning_count)
print("Critical servers:", critical_count)
How do the counters work?
- += 1 adds one to the matching counter.
- The counter decision uses the status already returned by get_status().
- The final print calls stay outside the loop so each total appears once.
- Save server_report.py.
- Return to the standard Linux terminal.
Before the final run, which status should have a count of two?
- Run the completed report with this command:
python3 server_report.py
After the four server lines, you should see Healthy servers: 1, Warning servers: 2, and Critical servers: 1 on separate lines.
That’s the complete monitor working. It applies one maintained rule to every server, shows each percentage, and summarizes the fleet.
Counts or report lines incorrect?
- Keep the loop body indented by four spaces.
- Keep the counter decision inside the loop.
- Keep the three summary print calls outside the loop.
- Help me debug the final server report.
Why this matters in the real world
Infrastructure teams use loops to apply the same checks across groups of servers, containers, or cloud resources. Functions keep the rule consistent, while totals help operators decide where to investigate first.
✔️ Awesome, I've got everything!
Your final report shows four percentages and the correct three status totals.
ⓧ I'd like to double check the full code
# Keep the monitoring limits shared by every server.
WARNING_THRESHOLD = 70
CRITICAL_THRESHOLD = 90
def get_status(disk_usage_percent):
# Return one label from the supplied disk percentage.
if disk_usage_percent >= CRITICAL_THRESHOLD:
return "critical"
elif disk_usage_percent >= WARNING_THRESHOLD:
return "warning"
else:
return "healthy"
# Store the latest disk percentage for each server.
disk_usage_by_server = {
"web-01": 45,
"db-01": 91,
"cache-01": 72,
"worker-01": 76,
}
# Start one counter for each possible status.
healthy_count = 0
warning_count = 0
critical_count = 0
# Process each server and count the returned status.
for server_name in disk_usage_by_server:
disk_usage_percent = disk_usage_by_server[server_name]
status = get_status(disk_usage_percent)
print(server_name, "-", disk_usage_percent, "% -", status)
if status == "critical":
critical_count += 1
elif status == "warning":
warning_count += 1
else:
healthy_count += 1
# Display the totals after every server is processed.
print("Healthy servers:", healthy_count)
print("Warning servers:", warning_count)
print("Critical servers:", critical_count)
Secret mission
Save an Interactive Monitoring Report
Accept a server reading from the terminal, handle invalid input, add the current time, and save the result to server_report.txt.
Clean Up Your Resources
Clean Up Your Resources
Everything you built is stored locally in one Desktop folder. There are no ongoing costs or running services, so you can keep the files, pause your work, or delete the project.
Resources you used:
- The local ~/Desktop/python-server-status-checker folder containing your Python lesson scripts, plus the optional interactive_report.py and server_report.txt files.
Keep everything running
No action is needed. Choose this if you want to practise the exercises or continue improving the monitor.
- Leave the ~/Desktop/python-server-status-checker folder on your Desktop.
Pause - I'll come back to this later
Close the local tools to clear your workspace. The scripts stop as soon as each terminal command finishes.
- Save any open files in Xed.
- Close Xed.
- Close the standard Linux terminal.
- Keep the ~/Desktop/python-server-status-checker folder for later.
Delete - I don't want to use this again
Remove all project resources and start fresh. Deletion is permanent, so check the folder path before you run the command.
- Open the standard Linux terminal.
- Confirm that the command below names ~/Desktop/python-server-status-checker.
- Remove the project folder and every file inside it by running this command:
rm -r ~/Desktop/python-server-status-checker
What does this command do?
rm -r removes the named folder and its contents. The project created no cloud resources or background services, so this completes the cleanup.
- Open your Desktop in the file manager.
- Confirm that python-server-status-checker is no longer listed.
Folder still listed?
- Refresh the Desktop view.
- Compare the command path with ~/Desktop/python-server-status-checker.
- Help me remove the project folder safely.
Nice Work!
Nice Work!
You did it! Your Python server monitor now classifies disk usage with one reusable function, processes every server with a loop, and summarizes the results.
You've learned how to:
- Built Boolean monitoring checks that turn server facts and comparisons into visible True or False results.
- Organized server data with a list of names and a dictionary of disk percentages.
- Created a loop-based server report that reuses one function and counts healthy, warning, and critical results.
- Completed the optional Secret Mission by validating terminal input and saving a timestamped report to server_report.txt.
Ready to quiz yourself?