From 09a6b8374fb19583d196c245664f1d6494f46037 Mon Sep 17 00:00:00 2001 From: Antonio De Lucreziis Date: Sun, 24 Dec 2023 22:59:42 +0100 Subject: [PATCH] initial commit --- .github/workflows/release.yaml | 30 ++++++++++++++++ .gitignore | 11 ++++++ README.md | 64 ++++++++++++++++++++++++++++++++++ go.mod | 3 ++ main.go | 64 ++++++++++++++++++++++++++++++++++ 5 files changed, 172 insertions(+) create mode 100644 .github/workflows/release.yaml create mode 100644 .gitignore create mode 100644 README.md create mode 100644 go.mod create mode 100644 main.go diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..2cab81b --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,30 @@ +name: Build and Release + +on: + push: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.21 + + - name: Build + run: | + CGO_ENABLED=0 GOARCH=arm64 go build -a -ldflags '-s -w' -o ./out/stats-server + + - name: Create Release + id: create_release + uses: softprops/action-gh-release@v1 + with: + files: ./out/stats-server + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bad565b --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# Local files +.env +*.local* + +# Binaries +bin/ +.out/ +out/ + +# Editors +.vscode/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..a5ee525 --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +# Go Stats Server + +This Go project implements a simple TCP server that responds to custom commands over the network. The server performs various system-related tasks and provides +information such as CPU usage, memory status, network statistics, storage details, and system uptime. + +## Usage + +1. **Build the Server:** + + ```bash + CGO_ENABLED=0 GOARCH= go build -a -ldflags '-s -w' -o ./out/stats-server main.go + ``` + +2. **Run the Server:** + + ```bash + ./out/stats-server + ``` + +3. **Connect to the Server:** Use a TCP client to connect to the server on port 12345. You can send commands like "cpu," "memory," "network," "storage," + "uptime," and "exit." + + Example using `nc`: + + ```bash + echo "cpu" | nc localhost 12345 + ``` + + or using golang + + ```go + import "net" + + func main() { + conn, err := net.Dial("tcp", "localhost:12345") + if err != nil { + // handle error + } + defer conn.Close() + + conn.Write([]byte("cpu")) + } + ``` + +## GitHub Actions Workflow + +The included GitHub Actions workflow automates the build and release process. On each push to the main branch, the workflow builds the Go program, creates a +GitHub release, and uploads the compiled binary as an artifact. + +## Downloading the Artifact + +TODO + + diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..05e494c --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/aziis98/go-cluster-node-stats + +go 1.21.5 diff --git a/main.go b/main.go new file mode 100644 index 0000000..443a48e --- /dev/null +++ b/main.go @@ -0,0 +1,64 @@ +package main + +import ( + "bufio" + "fmt" + "net" + "os" + "os/exec" +) + +// ExecuteCommand runs a system command and returns its output +func ExecuteCommand(command string) string { + cmd := exec.Command("bash", "-c", command) + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Sprintf("Error: %s", err) + } + return string(output) +} + +func handleConnection(conn net.Conn) { + defer conn.Close() + + scanner := bufio.NewScanner(conn) + for scanner.Scan() { + command := scanner.Text() + + switch command { + case "cpu": + fmt.Fprintln(conn, ExecuteCommand("top -bn1 | grep \"Cpu(s)\" | sed \"s/.*, *\\([0-9.]*\\)%* id.*/\\1/\" | sed \"s/^/100 - /\" | bc")) + case "memory": + fmt.Fprintln(conn, ExecuteCommand("free -m | awk '/Mem/{print $3\" \"$2}'")) + case "network": + fmt.Fprintln(conn, ExecuteCommand("cat /sys/class/net/[e]*/statistics/{r,t}x_bytes")) + case "storage": + fmt.Fprintln(conn, ExecuteCommand("df -Ph | grep mmcblk0p5 | awk '{print $2\" \"$3}' | sed 's/G//g'")) + case "uptime": + fmt.Fprintln(conn, ExecuteCommand("cut -f1 -d. /proc/uptime")) + case "exit": + return + default: + fmt.Fprintln(conn, "Invalid command") + } + } +} + +func main() { + ln, err := net.Listen("tcp", ":12345") + if err != nil { + fmt.Println("Error:", err) + os.Exit(1) + } + defer ln.Close() + + for { + conn, err := ln.Accept() + if err != nil { + fmt.Println("Error:", err) + continue + } + + go handleConnection(conn) + } +}