mirror of
https://github.com/henrygd/beszel.git
synced 2026-04-05 12:31:49 +02:00
agent: add separate glibc build with NVML support (#1618)
purego requires dynamic linking, so split the agent builds: - Default: static binary without NVML (works on musl/alpine) - Glibc: dynamic binary with NVML support via purego Changes: - Add glibc build tag to conditionally include NVML code - Add beszel-agent-linux-amd64-glibc build/archive in goreleaser - Update ghupdate to use glibc binary on glibc systems - Switch nvidia dockerfile to golang:bookworm with -tags glibc
This commit is contained in:
@@ -76,6 +76,18 @@ builds:
|
|||||||
- goos: windows
|
- goos: windows
|
||||||
goarch: riscv64
|
goarch: riscv64
|
||||||
|
|
||||||
|
- id: beszel-agent-linux-amd64-glibc
|
||||||
|
binary: beszel-agent
|
||||||
|
main: internal/cmd/agent/agent.go
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
flags:
|
||||||
|
- -tags=glibc
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
|
||||||
archives:
|
archives:
|
||||||
- id: beszel-agent
|
- id: beszel-agent
|
||||||
formats: [tar.gz]
|
formats: [tar.gz]
|
||||||
@@ -89,6 +101,15 @@ archives:
|
|||||||
- goos: windows
|
- goos: windows
|
||||||
formats: [zip]
|
formats: [zip]
|
||||||
|
|
||||||
|
- id: beszel-agent-linux-amd64-glibc
|
||||||
|
formats: [tar.gz]
|
||||||
|
ids:
|
||||||
|
- beszel-agent-linux-amd64-glibc
|
||||||
|
name_template: >-
|
||||||
|
{{ .Binary }}_
|
||||||
|
{{- .Os }}_
|
||||||
|
{{- .Arch }}_glibc
|
||||||
|
|
||||||
- id: beszel
|
- id: beszel
|
||||||
formats: [tar.gz]
|
formats: [tar.gz]
|
||||||
ids:
|
ids:
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"maps"
|
"maps"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
@@ -14,8 +15,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/henrygd/beszel/internal/entities/system"
|
"github.com/henrygd/beszel/internal/entities/system"
|
||||||
|
|
||||||
"log/slog"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build (linux || windows) && amd64
|
//go:build amd64 && (windows || (linux && glibc))
|
||||||
|
|
||||||
package agent
|
package agent
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build linux && amd64
|
//go:build glibc && linux && amd64
|
||||||
|
|
||||||
package agent
|
package agent
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build (!linux && !windows) || !amd64
|
//go:build (!linux && !windows) || !amd64 || (linux && !glibc)
|
||||||
|
|
||||||
package agent
|
package agent
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ func TestSystemdManagerGetServiceStats(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Test with refresh = true
|
// Test with refresh = true
|
||||||
result := manager.getServiceStats(true)
|
result := manager.getServiceStats("any-service", true)
|
||||||
assert.Nil(t, result)
|
assert.Nil(t, result)
|
||||||
|
|
||||||
// Test with refresh = false
|
// Test with refresh = false
|
||||||
result = manager.getServiceStats(false)
|
result = manager.getServiceStats("any-service", false)
|
||||||
assert.Nil(t, result)
|
assert.Nil(t, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM --platform=$BUILDPLATFORM golang:alpine AS builder
|
FROM --platform=$BUILDPLATFORM golang:bookworm AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ COPY . ./
|
|||||||
|
|
||||||
# Build
|
# Build
|
||||||
ARG TARGETOS TARGETARCH
|
ARG TARGETOS TARGETARCH
|
||||||
RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /agent ./internal/cmd/agent
|
RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -tags glibc -ldflags "-w -s" -o /agent ./internal/cmd/agent
|
||||||
|
|
||||||
# --------------------------
|
# --------------------------
|
||||||
# Smartmontools builder stage
|
# Smartmontools builder stage
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -345,5 +346,32 @@ func archiveSuffix(binaryName, goos, goarch string) string {
|
|||||||
if goos == "windows" {
|
if goos == "windows" {
|
||||||
return fmt.Sprintf("%s_%s_%s.zip", binaryName, goos, goarch)
|
return fmt.Sprintf("%s_%s_%s.zip", binaryName, goos, goarch)
|
||||||
}
|
}
|
||||||
|
// Use glibc build for agent on glibc systems (includes NVML support via purego)
|
||||||
|
if binaryName == "beszel-agent" && goos == "linux" && goarch == "amd64" && isGlibc() {
|
||||||
|
return fmt.Sprintf("%s_%s_%s_glibc.tar.gz", binaryName, goos, goarch)
|
||||||
|
}
|
||||||
return fmt.Sprintf("%s_%s_%s.tar.gz", binaryName, goos, goarch)
|
return fmt.Sprintf("%s_%s_%s.tar.gz", binaryName, goos, goarch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isGlibc() bool {
|
||||||
|
for _, path := range []string{
|
||||||
|
"/lib64/ld-linux-x86-64.so.2", // common on many distros
|
||||||
|
"/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2", // Debian/Ubuntu
|
||||||
|
"/lib/ld-linux-x86-64.so.2", // alternate
|
||||||
|
} {
|
||||||
|
if _, err := os.Stat(path); err == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fallback to ldd output when present (musl ldd reports musl, glibc reports GNU libc/glibc).
|
||||||
|
if lddPath, err := exec.LookPath("ldd"); err == nil {
|
||||||
|
out, err := exec.Command(lddPath, "--version").CombinedOutput()
|
||||||
|
if err == nil {
|
||||||
|
s := strings.ToLower(string(out))
|
||||||
|
if strings.Contains(s, "gnu libc") || strings.Contains(s, "glibc") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user