Files

77 lines
1.9 KiB
Go
Raw Permalink Normal View History

2026-07-18 10:02:43 +03:00
package main
import (
"bufio"
"os"
"strings"
)
// OSInfo holds the detected distribution identity and init system.
type OSInfo struct {
ID string
Version string
Init string // "systemd" or "openrc"
}
// detectOS parses /etc/os-release and maps the distro to its init system.
func detectOS() *OSInfo {
f, err := os.Open("/etc/os-release")
if err != nil {
die("Cannot detect OS: /etc/os-release not found")
}
defer f.Close()
vals := map[string]string{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
if i := strings.Index(line, "="); i >= 0 {
key := strings.TrimSpace(line[:i])
vals[key] = unquoteShell(line[i+1:])
}
}
osInfo := &OSInfo{
ID: valueOr(vals["ID"], "unknown"),
Version: valueOr(vals["VERSION_ID"], "unknown"),
}
switch osInfo.ID {
case "ubuntu", "debian", "linuxmint":
osInfo.Init = "systemd"
case "alpine":
osInfo.Init = "openrc"
default:
die("Unsupported OS: %s (supported: ubuntu, debian, linuxmint, alpine)", osInfo.ID)
}
// A systemd-based distro may still be running here without systemd as
// PID 1 — the container case (e.g. the Linux Mint image used for the
// alternative container build). systemd creates /run/systemd/system only
// when it is actually active as the init system, so its absence is the
// standard way to detect this. Fall back to driving awg-quick directly,
// same as the Alpine/OpenRC path.
if osInfo.Init == "systemd" && !systemdRunning() {
osInfo.Init = "openrc"
}
info("Detected OS: %s %s (init: %s)", osInfo.ID, osInfo.Version, osInfo.Init)
return osInfo
}
// systemdRunning reports whether systemd is active as PID 1.
func systemdRunning() bool {
_, err := os.Stat("/run/systemd/system")
return err == nil
}
func valueOr(v, def string) string {
if v == "" {
return def
}
return v
}