DEV Community

Yash Sonawane
Yash Sonawane

Posted on

Stop Writing Bash Scripts for Everything! Build Your Own DevOps CLI Tool With Go

Imagine having one command that checks your servers, monitors Docker containers, tests API endpoints, and reports infrastructure health.

Instead of maintaining 20 different scripts, you build one powerful CLI tool.

Sounds cool?

That's exactly where Go becomes interesting for DevOps engineers.

Bash is amazing for automation. Python is excellent for scripting. But when you want to build portable, compiled command-line applications that are easy to distribute, Go deserves your attention.

Think about tools like:

  • Docker
  • kubectl
  • Terraform
  • Helm
  • Hugo

Go is used to build all of these.

So why not build your own?

Let's create a practical DevOps CLI tool from scratch. ๐Ÿš€


๐Ÿค” 1. Why Should DevOps Engineers Learn Go?

Imagine you're managing multiple servers.

You regularly need to:

  • Check whether servers are reachable.
  • Monitor API availability.
  • Inspect Docker containers.
  • Check application health.
  • Automate repetitive operations.
  • Generate reports.

You could write separate Bash or Python scripts for every task.

But as your automation grows, maintaining those scripts can become difficult.

Go offers some useful advantages:

Feature Why it matters
Compiled binaries Easy application distribution
Static typing Catch many errors during development
Goroutines Run concurrent tasks
Standard library Build HTTP clients and servers
Cross-compilation Build executables for different platforms
Fast startup Useful for command-line applications

The idea isn't to replace Bash or Python.

It's to choose the right tool for the job.

โšก 2. What Exactly Is a CLI Tool?

CLI stands for Command-Line Interface.

You've probably used these commands:

docker ps
kubectl get pods
terraform plan
git status
Enter fullscreen mode Exit fullscreen mode

These are examples of command-line interfaces.

A CLI tool allows users to interact with software through commands and arguments.

Imagine building your own tool called devopsctl.

Its commands could look like this:

devopsctl server check
devopsctl docker status
devopsctl api health
devopsctl system info
Enter fullscreen mode Exit fullscreen mode

Instead of manually remembering multiple scripts, you have one organized command-line application.

Our goal is to build a small version of this idea.


๐Ÿ› ๏ธ 3. Set Up Your Go Environment

First, install Go from:

https://go.dev/dl/

Verify the installation:

go version
Enter fullscreen mode Exit fullscreen mode

Create your project:

mkdir devopsctl
cd devopsctl
Enter fullscreen mode Exit fullscreen mode

Initialize a Go module:

go mod init devopsctl
Enter fullscreen mode Exit fullscreen mode

Create a file:

touch main.go
Enter fullscreen mode Exit fullscreen mode

Your project structure:

devopsctl/
โ”‚
โ”œโ”€โ”€ main.go
โ”œโ”€โ”€ go.mod
โ””โ”€โ”€ README.md
Enter fullscreen mode Exit fullscreen mode

Now let's start building.

๐ŸŒ 4. Build Your First Server Health Checker

One common DevOps task is checking whether a service is reachable.

Let's build a command that checks multiple URLs concurrently.

Create main.go:

package main

import (
    "fmt"
    "net/http"
    "sync"
    "time"
)

func checkServer(url string, wg *sync.WaitGroup) {
    defer wg.Done()

    client := http.Client{
        Timeout: 5 * time.Second,
    }

    start := time.Now()

    response, err := client.Get(url)

    if err != nil {
        fmt.Printf("[DOWN] %s: %v\n", url, err)
        return
    }

    defer response.Body.Close()

    latency := time.Since(start)

    fmt.Printf(
        "[UP] %s | Status: %s | Latency: %v\n",
        url,
        response.Status,
        latency,
    )
}

func main() {
    servers := []string{
        "https://google.com",
        "https://github.com",
        "https://go.dev",
    }

    var wg sync.WaitGroup

    for _, server := range servers {
        wg.Add(1)
        go checkServer(server, &wg)
    }

    wg.Wait()

    fmt.Println("Health checks completed!")
}
Enter fullscreen mode Exit fullscreen mode

Run it:

go run main.go
Enter fullscreen mode Exit fullscreen mode

Example output:

[UP] https://google.com | Status: 200 OK | Latency: 120ms
[UP] https://github.com | Status: 200 OK | Latency: 180ms
[UP] https://go.dev | Status: 200 OK | Latency: 95ms

Health checks completed!
Enter fullscreen mode Exit fullscreen mode

Your first Go-based DevOps utility is ready.

What did we learn?

  • net/http handles HTTP requests.
  • sync.WaitGroup coordinates concurrent tasks.
  • go starts a goroutine.
  • time measures request duration.
  • Error handling helps identify unavailable services.

One important detail: this checks whether an HTTP request succeeds at the transport level. A service returning HTTP 500 is still reachable, but its application response indicates an error. A production health checker should evaluate HTTP status codes and application-specific health endpoints.


๐Ÿณ 5. Add Docker Container Monitoring

Now let's make the project more interesting.

What if your tool could inspect Docker containers?

Docker exposes a command-line interface that you can call from Go.

For a simple learning example:

package main

import (
    "fmt"
    "os/exec"
)

func checkDocker() {
    cmd := exec.Command("docker", "ps")

    output, err := cmd.CombinedOutput()

    if err != nil {
        fmt.Println("Docker command failed:", err)
        return
    }

    fmt.Println(string(output))
}

func main() {
    fmt.Println("Checking Docker containers...")
    checkDocker()
}
Enter fullscreen mode Exit fullscreen mode

Run:

go run main.go
Enter fullscreen mode Exit fullscreen mode

This executes:

docker ps
Enter fullscreen mode Exit fullscreen mode

and displays the result.

For a more advanced production tool, consider using the Docker Engine API or official Go SDK rather than parsing command output.

Also, external command execution should use fixed executable paths or carefully validated arguments. Never pass untrusted user input directly into a shell command.


๐Ÿ“Š 6. Turn It Into a Real CLI Application

So far, we've written individual functions.

But a professional CLI should support commands and arguments.

For example:

devopsctl health
devopsctl docker
devopsctl version
Enter fullscreen mode Exit fullscreen mode

Go provides the flag package in its standard library.

Here's a simple example:

package main

import (
    "flag"
    "fmt"
)

func main() {
    health := flag.Bool(
        "health",
        false,
        "Check application health",
    )

    version := flag.Bool(
        "version",
        false,
        "Show application version",
    )

    flag.Parse()

    if *health {
        fmt.Println("Application is healthy!")
        return
    }

    if *version {
        fmt.Println("devopsctl version 1.0.0")
        return
    }

    flag.Usage()
}
Enter fullscreen mode Exit fullscreen mode

Run:

go run main.go --health
Enter fullscreen mode Exit fullscreen mode

Output:

Application is healthy!
Enter fullscreen mode Exit fullscreen mode

Check the version:

go run main.go --version
Enter fullscreen mode Exit fullscreen mode

For larger applications, explore Cobra, a popular Go library for building command-line applications.

https://github.com/spf13/cobra


๐Ÿš€ 7. Compile Your CLI Into a Single Executable

Here's one of the most satisfying parts of Go.

Build your application:

go build -o devopsctl
Enter fullscreen mode Exit fullscreen mode

Run it:

./devopsctl --health
Enter fullscreen mode Exit fullscreen mode

You can also cross-compile for different operating systems and architectures.

For example, build a Linux AMD64 executable from another supported development environment:

GOOS=linux GOARCH=amd64 go build -o devopsctl-linux
Enter fullscreen mode Exit fullscreen mode

Build for Windows:

GOOS=windows GOARCH=amd64 go build -o devopsctl.exe
Enter fullscreen mode Exit fullscreen mode

Build for macOS on Apple Silicon:

GOOS=darwin GOARCH=arm64 go build -o devopsctl-macos
Enter fullscreen mode Exit fullscreen mode

This makes it convenient to distribute your CLI without requiring users to install a separate Go runtime.

Remember that cross-compilation can depend on native dependencies and build configuration. The examples above are simplest for pure-Go projects.


โ˜ธ๏ธ 8. Take It Further: Build a Kubernetes CLI

Now imagine extending devopsctl with Kubernetes functionality.

You could support commands such as:

devopsctl k8s pods
devopsctl k8s deployments
devopsctl k8s nodes
Enter fullscreen mode Exit fullscreen mode

Go has a powerful Kubernetes ecosystem.

Explore:

  • client-go โ€” Kubernetes API client library.
  • controller-runtime โ€” Libraries for controllers and operators.
  • Kubebuilder โ€” Framework for building Kubernetes APIs and controllers.

Official resources:

https://kubernetes.io/docs/reference/using-api/client-libraries/

https://github.com/kubernetes/client-go

With these tools, you can build applications that interact with Kubernetes clusters programmatically.

For example, a Kubernetes monitoring CLI could:

  1. Connect to a cluster using kubeconfig.
  2. List Pods across namespaces.
  3. Identify Pods that are not Ready.
  4. Display restart counts.
  5. Retrieve selected Pod logs.
  6. Generate a troubleshooting report.

That is a much more advanced project than simply running kubectl get pods.


๐Ÿงช 9. Build This Portfolio Project: DevOpsCTL

Here's the project I'd recommend building and publishing on GitHub.

Project: DevOpsCTL โ€” Your Personal DevOps Command-Line Assistant

Core features

Module Functionality
Server Check endpoint availability
Docker List and inspect containers
Kubernetes List Pods and Deployments
System Display basic system information
API Check HTTP status and latency
Reports Export health-check results as JSON

Suggested architecture

                 DEVOPSCTL
                     |
          +----------+----------+
          |          |          |
          v          v          v
        Server     Docker    Kubernetes
        Module     Module      Module
          |          |          |
          v          v          v
        HTTP      Docker      K8s API
        Client     SDK        Client
          |          |          |
          +----------+----------+
                     |
                     v
               CLI Output
                     |
                     v
              JSON Reports
Enter fullscreen mode Exit fullscreen mode

Suggested repository structure

devopsctl/
โ”‚
โ”œโ”€โ”€ cmd/
โ”‚   โ””โ”€โ”€ root.go
โ”‚
โ”œโ”€โ”€ internal/
โ”‚   โ”œโ”€โ”€ server/
โ”‚   โ”œโ”€โ”€ docker/
โ”‚   โ”œโ”€โ”€ kubernetes/
โ”‚   โ””โ”€โ”€ system/
โ”‚
โ”œโ”€โ”€ main.go
โ”œโ”€โ”€ go.mod
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ README.md
โ””โ”€โ”€ LICENSE
Enter fullscreen mode Exit fullscreen mode

Advanced features to add later

  • Prometheus metrics integration.
  • YAML configuration support.
  • Concurrent health checks with configurable limits.
  • Colorful terminal output.
  • Unit and integration tests.
  • GitHub Actions CI pipeline.
  • Release binaries for Linux, macOS, and Windows.

Don't build everything at once. Start with the health checker, then add one module at a time.


๐Ÿ—“๏ธ 10. Your 7-Day Go Developer Challenge

Want to actually learn Go? Follow this challenge.

Day Task
1 Learn Go syntax, variables, and functions
2 Learn structs, slices, maps, and interfaces
3 Practice goroutines and channels
4 Build a REST API
5 Build a server health checker
6 Integrate Docker or Kubernetes
7 Publish your first Go CLI project on GitHub

At the end of seven days, you won't be a Go expert.

But you'll have something much more valuable: a working project and practical experience.


๐ŸŽฏ Final Thoughts

Go is not just another programming language to add to your resume.

It's a way to move from writing small automation scripts toward building real infrastructure tools.

You can use it to create:

  • DevOps automation utilities.
  • Cloud-native applications.
  • REST APIs.
  • Kubernetes operators.
  • Monitoring systems.
  • Distributed services.
  • Command-line applications.

And the best part?

You don't need to master the entire language before building something useful.

Start small. Build something. Break it. Debug it. Improve it.

Don't just learn tools built by engineers. Start building tools that other engineers can use.

๐Ÿ‘‡ Let's discuss!

If you could build your own DevOps CLI tool, which feature would you implement first?

  1. Docker monitoring
  2. Kubernetes troubleshooting
  3. AWS resource management
  4. Server health monitoring
  5. CI/CD automation

Share your ideas in the comments!


๐Ÿ“š Continue Your Go Learning Journey

Want a structured resource to learn Go?

๐Ÿน Mastering Go โ€” Complete Guide

You can also explore:

Learn Go. Automate intelligently. Build the tools of tomorrow.

Top comments (0)