77 lines
1.9 KiB
Go
77 lines
1.9 KiB
Go
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
|
|
}
|