Build a Bash Network Checker
Build a Bash script that checks URL reachability and publish it on GitHub.
Introduction
30 Second Summary
When a website stops responding, the first question is whether anyone can reach it. Repeating that check by hand gets slow as the list grows.
In this project, you will build an executable Bash network checker on macOS that turns an HTTP request into a clear UP or DOWN result. You will save its history with Git before publishing it on GitHub.
What You'll Build
Your finished script turns a supplied URL into a concise Terminal status ready for automation.
By the end of this project, you'll have:
- A reusable network check that reports a supplied URL as UP or DOWN.
- A controlled failure test that proves an unreachable target returns DOWN with exit status 1.
- A published project you can open on GitHub to show the working checker beside its documentation.
- Secret Mission: Extend the checker to test several URLs in one run while returning a failed status when any target is down.
Are there any prerequisites?
You need a Mac with internet access plus a GitHub account. This project assumes installations of Git plus Visual Studio Code.
Before We Start
This first checkpoint anchors what you are building before the terminal work begins. You are creating a Bash network checker so URL reachability can be tested consistently through automation.
Set Up Your macOS Workspace
Your Bash network checker eventually runs from macOS Terminal. Every later step depends on a command-line workspace you can trust.
A missing command or Git identity can stop the workflow before the first network check. This step confirms the tools that carry the project from Terminal into Visual Studio Code.
In this step, get ready to:
- Verify the required command-line tools.
- Enable terminal access to Visual Studio Code.
- Create the configured project workspace.
Verify the command-line tools
Terminal passes your commands to a UNIX shell. Opening Bash briefly proves that the shell is available.
The git --version command checks Git. The curl --version command checks the networking tool your script uses.
- Press Cmd+Space to open Spotlight Search.
- Type Terminal.
- Press Enter to open Terminal.
- Verify the required command-line tools by running these commands:
bash
exit
git --version
curl --version
What Do These Commands Check?
- The bash command starts a Bash session in the current Terminal window.
- The exit command returns you to the shell that opened Terminal.
- The git --version command confirms that Git responds.
- The curl --version command confirms that curl responds. Its output also summarizes the installed build capabilities.
The Terminal prompt returns after exit. Git prints a version line.
curl prints its version information. That first dependency check is complete.
One of the Tools Did Not Respond?
- Follow the macOS installation prompt if the Git check asks for Xcode Command Line Tools.
- Check the spelling of each command if curl does not print version information.
- Ask for targeted help with diagnosing the command-line tool check.
Install the Visual Studio Code launcher
The code command is Visual Studio Code's terminal launcher. Adding it to PATH lets Terminal open a folder in the editor.
The launcher setting is tucked inside the Command Palette. It is easy to miss on a first pass.
- Press Cmd+Space to open Spotlight Search.
- Type Visual Studio Code.
- Press Enter to open Visual Studio Code.
You should see the Visual Studio Code window. The editor is ready for the launcher configuration.
- Press Command-Shift-P to open the Command Palette.
- Type Shell Command: Install 'code' command in PATH into the Command Palette.
The matching command should appear in the Command Palette results.
- Select Shell Command: Install 'code' command in PATH.
Why Does PATH Matter?
PATH is the list of locations your shell searches for commands. Installing the launcher there makes code available from a new Terminal session.
- Switch back to Terminal from earlier.
- Press Cmd+Q to quit Terminal.
- Press Cmd+Space to reopen Spotlight Search.
- Type Terminal.
- Press Enter to start a fresh Terminal session.
Before you run the check, what details do you expect a working launcher to print?
- Verify the Visual Studio Code launcher by running this command:
code --version
What Does This Command Check?
The command asks the launcher for its version information. A response proves the fresh Terminal session can find Visual Studio Code through PATH.
You should see the Visual Studio Code version. The output also includes a GitHub commit ID plus your computer architecture.
The terminal launcher now works. Your project folders can move directly from Terminal into the editor.
The Launcher Does Not Respond?
- Confirm that you restarted Terminal after installing the launcher.
- Repeat the Command Palette installation if the launcher still does not respond.
- Ask for help with fixing the Visual Studio Code launcher.
Configure Git and open the workspace
Git records an author name plus an email address in each commit. The user.name value stores the name. The user.email value stores the email address.
- Inspect your configured Git identity by running these commands:
git config user.name
git config user.email
What Do These Commands Check?
The first command reads the name Git uses for commits. The second command reads the matching email address.
✔️ Both values appear
Your Git identity is already configured. Both values are ready for the commit you create later.
ⓧ One or both values are blank
A blank result means Git needs that identity value. The global configuration applies it to future repositories for your macOS account.
- Replace YOUR NAME with the name you want attached to your commits.
- Replace YOUR EMAIL with the email address you want attached to your commits.
- Store both Git identity values by running the adapted commands below:
git config --global user.name "YOUR NAME"
git config --global user.email "YOUR EMAIL"
What Do These Commands Change?
The --global option stores your identity for the current macOS user. Future Git repositories can use the same author details.
- Confirm both Git identity values by rerunning these commands:
git config user.name
git config user.email
What Should This Confirm?
Both commands should now print a value. This confirms Git can attach your identity to the project's future commits.
Your configured name should print first. Your configured email address should print second.
A Git Identity Value Is Still Blank?
- Check that the configuration command includes --global.
- Confirm that you replaced both uppercase placeholders before running the configuration commands.
- Ask for help with configuring your Git identity.
The project directory gives every later file one predictable home. The ~ symbol represents your macOS home folder.
- Create the ~/month1-devops-checker directory by running these commands:
mkdir ~/month1-devops-checker
cd ~/month1-devops-checker
What Do These Commands Do?
The first command creates the project directory inside your home folder. The second command moves the current Terminal session into that directory.
Your Terminal prompt should now end with month1-devops-checker. This shows that later commands run from the intended directory.
Before you run the final check, which folder do you expect Visual Studio Code to open?
- Open the current project directory in Visual Studio Code by running this command:
code .
What Does This Command Do?
The code . command sends the current directory to Visual Studio Code. The dot represents the directory Terminal is currently using.
Visual Studio Code should move to the foreground. You should see month1-devops-checker open as the workspace.
The Correct Workspace Did Not Open?
- Switch back to Terminal to confirm the prompt ends with month1-devops-checker.
- Rerun cd ~/month1-devops-checker if Terminal is using another directory.
- Ask for help with opening the correct workspace.
Your command-line workspace is ready. Next, you will inspect a live HTTP response before turning it into automation.
Inspect an HTTP Response
Your command-line workspace is ready. You can now test the request your network checker will automate.
A raw HTTP request made with curl gives you an early result. Its response headers are too noisy for a reusable status check.
In this step, get ready to:
- Send an HTTP HEAD request to the curl documentation.
- Identify each part of the target URL.
- Connect the command exit status to a successful request.
Inspect the response headers
An HTTP HEAD request retrieves response headers without downloading the response body. The status line shows how the server answered the request.
- Request the response headers by running this command in the Terminal session from earlier:
curl --head https://curl.se/docs/manpage.html
What Does This Command Do?
- The curl command sends the network request.
- The --head option asks for response headers only.
- The https://curl.se/docs/manpage.html value identifies the official curl manual as the target.
- Locate the HTTP status line at the top of the Terminal output.
- Scan the remaining lines to inspect the response headers.
You'll see an HTTP status line followed by response headers. The exact header names can vary because the server controls which metadata it returns.
No Response Headers?
- Check your Mac's internet connection.
- Compare the URL in your command with https://curl.se/docs/manpage.html.
Ask for focused help with diagnosing the missing headers.
Trace the request journey
The URL tells curl where to connect. Several networking stages turn that text into an HTTP response.
How Does the Request Travel?
- The https value is the scheme. It tells curl to protect the connection with TLS.
- The curl.se value is the hostname. DNS turns that hostname into a network address.
- TCP creates a reliable connection to the server.
- The /docs/manpage.html value is the path. HTTP uses that path to request the curl manual.
- Identify https as the scheme.
- Identify curl.se as the hostname.
- Identify /docs/manpage.html as the path.
- Trace the request through DNS, TCP, TLS, and HTTP in that order.
You can now connect one URL to the network stages behind its response. Each stage must succeed before curl can receive the headers.
Check the exit status
Every shell command leaves an exit status. For this successful request, curl returns 0.
Before you run the final check, do you expect the exit status to show success or failure?
- Run the request sequence below to inspect the exit status:
curl --head https://curl.se/docs/manpage.html
echo $?
What Do These Commands Prove?
- The first line repeats the HTTP HEAD request.
- The second line prints the exit status of the immediately preceding command.
- An exit status of 0 confirms that curl completed the request successfully.
You'll see an HTTP status line followed by response headers. The last line is 0.
You have the first network signal working: the curl request completed with exit status 0. That value gives your future script a machine-readable success signal.
Exit Status Is Not Zero?
- Rerun the two-line sequence without entering another command between the lines.
- Confirm that the response headers finish printing before the exit status appears.
- Check your internet connection before repeating the request.
Ask for targeted help with understanding the unexpected exit status.
You can now read an HTTP response from the command line. Next, you'll turn that noisy response into a Bash checker that prints a compact result.
Build the Network Checker
Your manual curl request proved that the documentation URL responds. The raw HTTP headers are too noisy for a reusable status check.
In this step, you will build that reusable Bash script in the Visual Studio Code workspace from earlier. You will then run it as an executable.
In this step, get ready to:
- Capture a URL through the script's first positional argument.
- Convert the curl exit status into clear UP or DOWN output.
- Produce an UP result from the executable checker.
Capture and validate the target URL
A positional argument gives a script information when you run it. The variable named TARGET_URL stores the first argument from $1.
- Use the file sidebar in the Visual Studio Code workspace from earlier to create check-site.sh inside month1-devops-checker.
- Paste the input handling code into check-site.sh from the first line:
#!/bin/bash
TARGET_URL="$1"
if [ "$TARGET_URL" = "" ]; then
echo "Usage: ./check-site.sh URL"
exit 1
fi
What Does This Code Do?
- The #!/bin/bash line tells macOS to execute the file with Bash.
- The TARGET_URL="$1" assignment stores the first argument supplied to the script.
- The first if block detects an empty argument.
- The usage message shows the required command shape before the script exits with 1.
- Save check-site.sh.
- Confirm that check-site.sh appears inside the month1-devops-checker file sidebar.
File Not Appearing?
- Confirm that you created check-site.sh inside the workspace from earlier.
- Check that the filename ends with .sh.
- Save the file before checking the file sidebar again.
Ask for help with locating the script file.
Add the reachability logic
An exit status lets the if statement test curl directly. A successful request enters the first branch. A failed request enters the else branch.
- Insert one blank line below the first fi.
- Paste the request logic below that blank line:
echo "Checking $TARGET_URL"
if curl --head --fail --silent --show-error --max-time 10 "$TARGET_URL" > /dev/null; then
echo "UP: $TARGET_URL"
exit 0
else
echo "DOWN: $TARGET_URL"
exit 1
fi
How Does the Check Work?
- The --head option requests response headers.
- The --fail option makes unsuccessful HTTP responses return a failure status.
- The --silent option hides the progress meter.
- The --show-error option keeps useful error details visible.
- The --max-time 10 option limits the request to ten seconds.
- The > /dev/null redirection discards the response headers.
- A successful request prints UP before exiting with 0.
- A failed request prints DOWN before exiting with 1.
- Save check-site.sh.
- Confirm that the file begins with #!/bin/bash.
- Confirm that the file ends with the final fi.
Code Does Not Match?
- Check that the request logic sits below the first fi.
- Confirm that every reference to TARGET_URL uses the same uppercase spelling.
- Check that the final conditional contains one else block.
Ask for help with comparing the script structure.
✔️ Awesome, I've got everything!
Good progress. Your saved file now contains the complete input check and reachability decision.
ⓧ I'd like to double check the full code
#!/bin/bash
TARGET_URL="$1"
if [ "$TARGET_URL" = "" ]; then
echo "Usage: ./check-site.sh URL"
exit 1
fi
echo "Checking $TARGET_URL"
if curl --head --fail --silent --show-error --max-time 10 "$TARGET_URL" > /dev/null; then
echo "UP: $TARGET_URL"
exit 0
else
echo "DOWN: $TARGET_URL"
exit 1
fi
Turn the script into an executable
An executable permission allows macOS to run the script by its pathname. The permission mode 755 makes check-site.sh executable.
- Grant executable permissions to check-site.sh by running this command in the Terminal from earlier:
chmod 755 check-site.sh
What Does This Command Do?
The command applies executable permissions to check-site.sh. This lets you run the file by pathname.
Before you run the checker, make your prediction about whether you will see raw headers or concise status lines.
- Test the executable checker against the curl documentation URL by running:
./check-site.sh https://curl.se/docs/manpage.html
What Does This Command Test?
The URL becomes the script's first argument through $1. The script uses the curl result to select its success branch.
You'll see Checking https://curl.se/docs/manpage.html followed by UP: https://curl.se/docs/manpage.html.
That is the core utility working. One URL now becomes a concise reachability result.
Checker Did Not Print UP?
- Confirm that Terminal is still inside ~/month1-devops-checker.
- Rerun chmod 755 check-site.sh if the script cannot be executed.
- Compare your saved file with the full-code tab above.
Ask for help with diagnosing the checker result.
Your checker now turns a reachable URL into a compact success result. Next, you will deliberately trigger its failure path and inspect the returned status.
Test Failure Detection
Your Bash checker already proves that a known HTTP page is reachable. Now you will test whether the same script communicates a failure clearly.
A checker that only demonstrates success is not trustworthy. A reserved invalid domain plus the shell's exit status gives you a repeatable way to prove the failure path.
In this step, get ready to:
- Trigger a controlled name-resolution failure.
- Inspect the script's failed exit status.
- Confirm that the missing-URL guard prints usage guidance.
Trigger the failure path
The .invalid domain is reserved for tests. It gives you a predictable target that cannot resolve through DNS.
Before you run it, predict whether the checker reaches the UP or DOWN branch.
- Trigger the controlled test by running this command:
./check-site.sh https://example.invalid
What Does This Test Do?
The script receives the URL through $1. A failed curl command makes the if condition choose else.
The failure branch prints the target as unavailable. It also returns a failed status to the shell.
You may also see a curl message about name resolution. That message belongs to this controlled test.
You'll see DOWN: https://example.invalid. That controlled result proves the checker does not label every target as reachable.
Did the Checker Print UP?
Confirm that you typed https://example.invalid exactly. A different URL can produce a different branch.
Confirm that Terminal remains in ~/month1-devops-checker.
Ask for help with diagnosing the unexpected checker result.
Inspect the failed exit status
The shell stores the status of the most recent command. Your next command reads that value before anything replaces it.
Before you inspect the status, predict whether the failure branch returns 0 or 1.
- Inspect the checker result by running this command immediately after the invalid-domain test:
echo $?
What Does This Status Check Do?
The $? value holds the exit status from the immediately preceding command. The echo command makes that otherwise hidden value visible.
You'll see 1. This confirms that the checker reports failure to other commands as well as to the person reading the output.
That is the key automation signal. Another process can use this nonzero status to stop or choose a failure path.
Seeing a Value Other Than 1?
Another command may have overwritten $?. Rerun the invalid-domain test.
Check the exit status before running anything else.
Ask for help with tracing the unexpected exit status.
Test the missing argument guard
A reusable script also needs to handle missing input. The first conditional checks whether the positional argument in $1 is empty.
Before you run the script without a URL, predict whether it attempts a request or prints guidance.
- Test the empty-argument guard by running this command:
./check-site.sh
What Does This Test Do?
Running the script without a URL leaves $1 empty. The opening conditional prints the required command format.
The script then exits with a failed status before attempting an incomplete network request.
You'll see Usage: ./check-site.sh URL. The checker now protects itself from missing input.
You have now proved both safeguards. The checker reports an unreachable target clearly. It also rejects an incomplete command with useful guidance.
Did the Script Try to Check an Empty URL?
Make sure the command contains no text after ./check-site.sh.
Confirm that the opening conditional in check-site.sh appears before the Checking $TARGET_URL output.
Ask for help with diagnosing the missing-argument guard.
Your checker now proves success and failure through visible output. Next, you will record this working state with Git. Then you will publish the repository to GitHub.
Publish Your Project
Your Bash network checker now reports reachable targets as UP. It reports unreachable targets as DOWN.
A working script on one Mac is easy to lose. Git records a versioned history.
GitHub gives that history a public home. Visual Studio Code handles the first remote publish from the workspace you already opened.
In this step, get ready to:
- Document the checker's success path plus its failure path.
- Record the working project in a local Git commit.
- Publish the repository publicly through GitHub.
Create the project README
A README.md file explains how someone can use your project without reading the script first. Markdown gives that explanation a clear structure.
- Switch back to the Visual Studio Code workspace from earlier.
- Select the new-file control in the workspace sidebar.
- Enter README.md as the file name.
- Add the project documentation to README.md by copying the content below:
# Month 1 DevOps Network Checker
A small Bash utility that checks whether a URL responds successfully.
## Run it
```bash
chmod 755 check-site.sh
./check-site.sh https://curl.se/docs/manpage.html
```
## Test the failure path
```bash
./check-site.sh https://example.invalid
echo $?
```
A reachable target prints `UP`. An unreachable target prints `DOWN` and returns exit status `1`.
What Does This Documentation Cover?
- The title identifies the utility as your Month 1 DevOps network checker.
- The run section preserves the commands for making the script executable plus checking a reachable URL.
- The failure section demonstrates the reserved failure target.
- The final line explains how the output relates to the exit status.
- Save README.md.
- Confirm README.md appears beside check-site.sh in the workspace sidebar.
- Confirm the editor shows the heading Month 1 DevOps Network Checker.
README Missing or Misformatted?
- Confirm the file name is exactly README.md.
- Check that every opening code fence has a matching closing code fence.
- Ask for help with checking the README structure.
✔️ Awesome, I've got everything!
Your saved README.md now documents both outcomes of the checker.
ⓧ I'd like to double check the full code
# Month 1 DevOps Network Checker
A small Bash utility that checks whether a URL responds successfully.
## Run it
```bash
chmod 755 check-site.sh
./check-site.sh https://curl.se/docs/manpage.html
```
## Test the failure path
```bash
./check-site.sh https://example.invalid
echo $?
```
A reachable target prints `UP`. An unreachable target prints `DOWN` and returns exit status `1`.
How to Use This Reference
Compare this reference with your saved README.md. Every heading plus command should match exactly.
Commit the working project
A Git repository turns the current files into a history you can inspect. The main branch becomes the timeline you publish.
How Does Git Record the Project?
The working tree contains your current files. The staging area selects the files for the next snapshot.
A commit records that snapshot with a message. The history keeps the result available for inspection.
- Use the Git version you checked earlier to select the matching initialization path below.
Git supports initial branch selection
Choose this path if your installed Git version is 2.28.0 or later.
- Initialize the repository on the main branch by running this command:
git init -b main
What Does This Command Do?
The command creates the local Git repository. The branch option names its initial branch main.
Git needs branch correction
Choose this path if your installed Git version is 2.27.1 or earlier.
- Initialize the repository with a main branch by running this command:
git init && git symbolic-ref HEAD refs/heads/main
What Do These Commands Do?
The first command creates the local Git repository. The second command points its initial branch reference at main.
- Inspect the new repository by running this command:
git status
What Does This Command Show?
The command compares the working tree with Git's current snapshot. It also lists files Git has not started tracking.
You should see check-site.sh plus README.md listed as untracked files.
Git Did Not Initialize?
- Confirm Terminal is still inside ~/month1-devops-checker.
- Use the initialization path that matches the Git version you checked earlier.
- Ask for help with initializing the repository on the main branch.
- Stage the complete project by running this command:
git add .
What Does This Command Do?
The command adds the current project contents to the staging area. Those staged files become the input for your first commit.
- Inspect the staged files by running this command:
git status
What Changed in Git?
Git now compares the staged versions with the empty repository history. Both project files are ready for the first commit.
You should see check-site.sh plus README.md listed as changes ready to be committed.
Files Not Staged?
- Confirm both files appear in the Visual Studio Code workspace.
- Confirm Terminal is still inside ~/month1-devops-checker.
- Ask for help with staging both project files.
- Record the staged project by running this command:
git commit -m "Build Bash network checker"
What Does This Command Do?
The command records the staged snapshot in Git history. The message identifies the project milestone represented by that snapshot.
That is the local history secured. Git now has a permanent snapshot containing both project files.
Before you inspect the history, predict whether the new commit message will appear.
- Inspect the compact commit history by running this command:
git log --oneline
What Does This Command Show?
The compact history displays one line for each commit. Each line includes a shortened identifier plus its commit message.
You should see one commit with the message Build Bash network checker.
Commit Missing From the History?
- Confirm the earlier status check listed both files as ready to be committed.
- Check that your configured Git identity remains available in this Terminal session.
- Ask for help with finding the missing Git commit.
Publish the repository to GitHub
A remote repository makes the commit available beyond your Mac. Publishing also gives you a public project page to share.
The publishing flow may ask you to sign in. Your login belongs in the account flow instead of either project file.
- Return to the Visual Studio Code workspace from earlier.
- Press Command-Shift-P to open the Command Palette.
- Run Publish to GitHub.
- Complete the GitHub sign-in flow if prompted.
- Enter month1-devops-checker as the repository name.
- Choose Public as the repository visibility.
- Include check-site.sh plus README.md in the initial publish.
Visual Studio Code creates the GitHub repository. It adds the repository as the project's remote.
It also pushes your commit. Publishing is complete when Visual Studio Code confirms that the repository is available on GitHub.
Before you open the repository, predict which project details the public page will show.
- Open the public repository with the link Visual Studio Code provides.
You should see check-site.sh plus README.md. You should also see the commit message Build Bash network checker.
Your first Month 1 utility now has a public home. Anyone with the repository link can inspect the script plus its documented test paths.
Repository Missing or Private?
- Confirm the publishing flow used the repository name month1-devops-checker.
- Confirm you selected Public visibility.
- Check that Visual Studio Code is signed in to the intended GitHub account.
- Ask for help with diagnosing the GitHub publishing flow.
Secret mission
Check Several URLs in One Run
Extend your checker to process every URL passed to one command. Preserve each result. Return a failed status when any target is down.
Clean Up Your Resources
Clean Up Your Resources
Your Bash checker has a local copy in ~/month1-devops-checker plus a public copy on GitHub. GitHub Free costs $0 USD per month, so keeping both copies creates no ongoing charges.
Resources you used:
- The local ~/month1-devops-checker folder.
- The public month1-devops-checker GitHub repository.
Keep everything running
No action needed. Choose this if you want the network checkers ready for future practice.
- Keep the local ~/month1-devops-checker folder on your Mac.
- Keep the public month1-devops-checker repository available on GitHub.
Both executable scripts remain ready to run. Your published commit history also stays available.
Pause - I'll come back to this later
Your scripts finish after each check, so there is no server or background process to stop. Closing the development windows frees their memory while preserving your work.
- Close the Visual Studio Code window for ~/month1-devops-checker.
- Close the Terminal window from earlier.
- Keep the local ~/month1-devops-checker folder unchanged.
- Keep the public month1-devops-checker repository unchanged.
The checker uses no memory while its scripts are idle. Your local files remain ready for the next session.
Delete - I don't want to use this again
Deleting both copies is permanent. The local scripts plus the public commit history disappear after these actions.
- Return to Terminal from earlier.
- Remove the local project folder by running these commands:
cd ~
rm -rf ~/month1-devops-checker
The cd command moves Terminal out of the project folder. The rm command removes the folder contents without individual prompts.
- Return to Visual Studio Code from earlier.
You should see that the workspace files are no longer available.
- Return to the public month1-devops-checker repository on GitHub.
- Select Settings in the repository navigation.
- Select General in the settings sidebar.
- Scroll to Danger Zone.
- Select Delete this repository.
- Enter month1-devops-checker when GitHub requests the repository name.
- Complete the final confirmation to permanently delete the repository.
Cleanup complete. The repository URL no longer displays your project.
Nice Work!
Nice Work!
You did it! Your published Bash network checker now turns HTTP checks into clear results for people or automation.
You've learned how to:
- Build an executable network checker that accepts a URL through a positional argument. It reports UP or DOWN with a useful exit status.
- Connect curl results to practical networking stages such as DNS, TCP, TLS, and HTTP. You also inspected response headers from a live endpoint.
- Track your project with Git. You published the working scripts and documentation in a public GitHub repository.
- Secret Mission: Extend the checker to process several URLs in one run. The script now returns an aggregate failure result when any target is down.
Ready to quiz yourself?