mirror of
https://github.com/EnumeratedDev/stormfetch.git
synced 2026-09-25 12:16:11 +00:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08035010c9
|
||
|
|
983b347d88
|
||
|
|
db96cd7e5e
|
||
|
|
96a2dee0e1
|
||
|
|
85d96fceec
|
@@ -24,3 +24,5 @@ make SYSCONFDIR=/etc
|
|||||||
make install
|
make install
|
||||||
make install-config SYSCONFDIR=/etc
|
make install-config SYSCONFDIR=/etc
|
||||||
```
|
```
|
||||||
|
### Post installation
|
||||||
|
- (Optional) Download `curl` from your package manager to fetch the amdgpu.ids database for AMD GPUs. It may be safely uninstalled after running stormfetch once with curl installed
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
distro_ascii: auto
|
distro_ascii: auto
|
||||||
|
disable_amdgpu_ids_warning: false
|
||||||
modules:
|
modules:
|
||||||
- name: distribution
|
- name: distribution
|
||||||
- name: hostname
|
- name: hostname
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
type StormfetchConfig struct {
|
type StormfetchConfig struct {
|
||||||
Ascii string `yaml:"distro_ascii"`
|
Ascii string `yaml:"distro_ascii"`
|
||||||
|
DisableAmdgpuIdsWarning bool `yaml:"disable_amdgpu_ids_warning"`
|
||||||
Modules []stormfetchModuleConfig `yaml:"modules"`
|
Modules []stormfetchModuleConfig `yaml:"modules"`
|
||||||
AnsiiColors []int `yaml:"ansii_colors"`
|
AnsiiColors []int `yaml:"ansii_colors"`
|
||||||
ForceConfigAnsii bool `yaml:"force_config_ansii"`
|
ForceConfigAnsii bool `yaml:"force_config_ansii"`
|
||||||
|
|||||||
+5
-5
@@ -1,19 +1,19 @@
|
|||||||
module stormfetch
|
module stormfetch
|
||||||
|
|
||||||
go 1.22
|
go 1.24.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728
|
||||||
github.com/jackmordaunt/ghw v1.0.4
|
github.com/jackmordaunt/ghw v1.0.5
|
||||||
github.com/mitchellh/go-ps v1.0.0
|
github.com/mitchellh/go-ps v1.0.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
github.com/jackmordaunt/pcidb v1.0.1 // indirect
|
github.com/jackmordaunt/pcidb v1.0.1 // indirect
|
||||||
github.com/jackmordaunt/wmi v1.2.4 // indirect
|
github.com/jackmordaunt/wmi v1.2.4 // indirect
|
||||||
github.com/kr/pretty v0.1.0 // indirect
|
github.com/kr/pretty v0.1.0 // indirect
|
||||||
golang.org/x/sys v0.3.0 // indirect
|
golang.org/x/sys v0.39.0 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+xzxf1jTJKMKZw3H0swfWk9RpWbBbDK5+0=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+xzxf1jTJKMKZw3H0swfWk9RpWbBbDK5+0=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728 h1:RkGhqHxEVAvPM0/R+8g7XRwQnHatO0KAuVcwHo8q9W8=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728/go.mod h1:SyRD8YfuKk+ZXlDqYiqe1qMSqjNgtHzBTG810KUagMc=
|
||||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
|
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||||
|
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||||
github.com/jackmordaunt/ghw v1.0.4 h1:as+COFuPuXaNQC3WqzoHS/E2JYWZU7gN8ompNTUxNxs=
|
github.com/jackmordaunt/ghw v1.0.4 h1:as+COFuPuXaNQC3WqzoHS/E2JYWZU7gN8ompNTUxNxs=
|
||||||
github.com/jackmordaunt/ghw v1.0.4/go.mod h1:4dReYvJ36CoAzIxlEx8du25Qi/YqKYvEGE9QJoRXiK8=
|
github.com/jackmordaunt/ghw v1.0.4/go.mod h1:4dReYvJ36CoAzIxlEx8du25Qi/YqKYvEGE9QJoRXiK8=
|
||||||
|
github.com/jackmordaunt/ghw v1.0.5 h1:3rTXwu0D9RkungV7/WlhC8HVuDlPaq0aKY8u0I51jLY=
|
||||||
|
github.com/jackmordaunt/ghw v1.0.5/go.mod h1:VpFlLXnJErgoRttR3WOxun4v5EE8/xfB4cK26G5q2U0=
|
||||||
github.com/jackmordaunt/pcidb v1.0.1 h1:uLLZa6kD5P39r2cwMyJJkxmuHfH9Wq19gYQEbYcB0Z4=
|
github.com/jackmordaunt/pcidb v1.0.1 h1:uLLZa6kD5P39r2cwMyJJkxmuHfH9Wq19gYQEbYcB0Z4=
|
||||||
github.com/jackmordaunt/pcidb v1.0.1/go.mod h1:OMmhrZOZVu2hYXhBDZXddypxwKR/dp4DbIgzCkQDxdQ=
|
github.com/jackmordaunt/pcidb v1.0.1/go.mod h1:OMmhrZOZVu2hYXhBDZXddypxwKR/dp4DbIgzCkQDxdQ=
|
||||||
github.com/jackmordaunt/wmi v1.2.4 h1:/XyuMiKby0qXNQp1j0uU0JqTWLM0QGOVok1Hf5Yagtg=
|
github.com/jackmordaunt/wmi v1.2.4 h1:/XyuMiKby0qXNQp1j0uU0JqTWLM0QGOVok1Hf5Yagtg=
|
||||||
@@ -16,8 +22,11 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|||||||
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
|
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
|
||||||
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
|
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
||||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||||
|
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|||||||
+52
-6
@@ -1,8 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-gl/glfw/v3.3/glfw"
|
"github.com/go-gl/glfw/v3.3/glfw"
|
||||||
@@ -18,10 +20,12 @@ type CPU struct {
|
|||||||
type GPU struct {
|
type GPU struct {
|
||||||
PCIAddress string
|
PCIAddress string
|
||||||
Vendor string
|
Vendor string
|
||||||
|
Name string
|
||||||
Product string
|
Product string
|
||||||
Subsystem string
|
Subsystem string
|
||||||
Driver string
|
Driver string
|
||||||
VRAM int64
|
VramTotal string
|
||||||
|
VramUsed string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Monitor struct {
|
type Monitor struct {
|
||||||
@@ -101,18 +105,60 @@ func GetGPUModels(hiddenGPUs []int) []GPU {
|
|||||||
vendor = gpu.DeviceInfo.Vendor.Name
|
vendor = gpu.DeviceInfo.Vendor.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback subsystem name to product name
|
// Set GPU name
|
||||||
subsystem := gpu.DeviceInfo.Subsystem.Name
|
name := ""
|
||||||
if subsystem == "" || subsystem == "unknown" {
|
|
||||||
subsystem = gpu.DeviceInfo.Product.Name
|
// Use GPU name from amdgpu.ids database
|
||||||
|
if vendor == "AMD" {
|
||||||
|
fetchedName, err := fetchAmdGpuName(gpu.DeviceInfo.Product.ID, gpu.DeviceInfo.Revision)
|
||||||
|
if err == nil && !config.DisableAmdgpuIdsWarning {
|
||||||
|
name = fetchedName
|
||||||
|
} else {
|
||||||
|
fmt.Println("Warning: could not fetch GPU name from amdgpu.ids database! Error: " + err.Error())
|
||||||
|
fmt.Println(" You can disable this warning in the configuration file")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if name == "" {
|
||||||
|
if gpu.DeviceInfo.Subsystem.Name == "" || gpu.DeviceInfo.Subsystem.Name == "unknown" {
|
||||||
|
// Set GPU name to product name
|
||||||
|
name = gpu.DeviceInfo.Product.Name
|
||||||
|
} else {
|
||||||
|
// Set GPU name to subsystem name
|
||||||
|
name = gpu.DeviceInfo.Subsystem.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use GPU name in brackets
|
||||||
|
leftBracket := strings.IndexByte(name, '[')
|
||||||
|
rightBracket := strings.IndexByte(name, ']')
|
||||||
|
if leftBracket != -1 && rightBracket != -1 {
|
||||||
|
name = name[leftBracket+1 : rightBracket]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get VRAM
|
||||||
|
vramTotal := "Unknown"
|
||||||
|
bytes, err := os.ReadFile("/sys/class/drm/card" + strconv.Itoa(gpu.Index) + "/device/mem_info_vram_total")
|
||||||
|
if err == nil {
|
||||||
|
vramUint, _ := strconv.ParseUint(strings.TrimSpace(string(bytes)), 10, 64)
|
||||||
|
vramTotal = FormatBytes(vramUint)
|
||||||
|
}
|
||||||
|
vramUsed := "Unknown"
|
||||||
|
bytes, err = os.ReadFile("/sys/class/drm/card" + strconv.Itoa(gpu.Index) + "/device/mem_info_vram_used")
|
||||||
|
if err == nil {
|
||||||
|
vramUint, _ := strconv.ParseUint(strings.TrimSpace(string(bytes)), 10, 64)
|
||||||
|
vramUsed = FormatBytes(vramUint)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = append(ret, GPU{
|
ret = append(ret, GPU{
|
||||||
PCIAddress: gpu.Address,
|
PCIAddress: gpu.Address,
|
||||||
Vendor: vendor,
|
Vendor: vendor,
|
||||||
|
Name: name,
|
||||||
Product: gpu.DeviceInfo.Product.Name,
|
Product: gpu.DeviceInfo.Product.Name,
|
||||||
Subsystem: subsystem,
|
Subsystem: gpu.DeviceInfo.Subsystem.Name,
|
||||||
Driver: gpu.DeviceInfo.Driver,
|
Driver: gpu.DeviceInfo.Driver,
|
||||||
|
VramTotal: vramTotal,
|
||||||
|
VramUsed: vramUsed,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-5
@@ -219,7 +219,7 @@ func initializeModuleMap() {
|
|||||||
RegisterModule(cpusModule)
|
RegisterModule(cpusModule)
|
||||||
|
|
||||||
// GPUs module
|
// GPUs module
|
||||||
gpusModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "gpus", Format: "%3GPU: %4$GPU_VENDOR $GPU_SUBSYSTEM"}, Execute: func(sm StormfetchModule) string {
|
gpusModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "gpus", Format: "%3GPU: %4$GPU_VENDOR $GPU_NAME"}, Execute: func(sm StormfetchModule) string {
|
||||||
hiddenGPUsInterface, _ := sm.GetData("hidden_gpus", make([]any, 0))
|
hiddenGPUsInterface, _ := sm.GetData("hidden_gpus", make([]any, 0))
|
||||||
|
|
||||||
// Convert interface slices to string slices
|
// Convert interface slices to string slices
|
||||||
@@ -232,22 +232,24 @@ func initializeModuleMap() {
|
|||||||
gpus := GetGPUModels(hiddenGPUs)
|
gpus := GetGPUModels(hiddenGPUs)
|
||||||
|
|
||||||
for i, gpu := range gpus {
|
for i, gpu := range gpus {
|
||||||
vram := strconv.FormatInt(gpu.VRAM, 10)
|
|
||||||
|
|
||||||
expanded := os.Expand(sm.Format, func(s string) string {
|
expanded := os.Expand(sm.Format, func(s string) string {
|
||||||
switch s {
|
switch s {
|
||||||
case "GPU_NUM":
|
case "GPU_NUM":
|
||||||
return strconv.Itoa(i + 1)
|
return strconv.Itoa(i + 1)
|
||||||
case "GPU_VENDOR":
|
case "GPU_VENDOR":
|
||||||
return gpu.Vendor
|
return gpu.Vendor
|
||||||
|
case "GPU_NAME":
|
||||||
|
return gpu.Name
|
||||||
case "GPU_PRODUCT":
|
case "GPU_PRODUCT":
|
||||||
return gpu.Product
|
return gpu.Product
|
||||||
case "GPU_SUBSYSTEM":
|
case "GPU_SUBSYSTEM":
|
||||||
return gpu.Subsystem
|
return gpu.Subsystem
|
||||||
case "GPU_DRIVER":
|
case "GPU_DRIVER":
|
||||||
return gpu.Driver
|
return gpu.Driver
|
||||||
case "GPU_VRAM":
|
case "GPU_VRAM_TOTAL":
|
||||||
return vram
|
return gpu.VramTotal
|
||||||
|
case "GPU_VRAM_USED":
|
||||||
|
return gpu.VramUsed
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -58,6 +59,46 @@ func ReadKeyValueFile(filepath string) (map[string]string, error) {
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fetchAmdGpuName(productId, revision string) (string, error) {
|
||||||
|
productId = strings.ToUpper(productId)
|
||||||
|
revision = strings.ToUpper(revision[2:])
|
||||||
|
|
||||||
|
// Get cache directory
|
||||||
|
cachedir, err := os.UserCacheDir()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure amdgpu.ids file exists and download it if it doesn't
|
||||||
|
if _, err := os.Stat(path.Join(cachedir, "amdgpu.ids")); err != nil {
|
||||||
|
cmd := exec.Command("curl", "-o", path.Join(cachedir, "amdgpu.ids"), "https://gitlab.freedesktop.org/mesa/libdrm/-/raw/main/data/amdgpu.ids")
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Could not fetch amdgpu.ids using curl")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read amdgpu.ids file
|
||||||
|
amdgpuIds, err := os.ReadFile(path.Join(cachedir, "amdgpu.ids"))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse read data and find GPU
|
||||||
|
for _, line := range strings.Split(string(amdgpuIds), "\n") {
|
||||||
|
if len(line) < 2 || line[0] == '#' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fields := strings.Split(line, ",\t")
|
||||||
|
if fields[0] == productId && fields[1] == revision {
|
||||||
|
return strings.TrimPrefix(fields[2], "AMD "), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
func runCommand(command string, shell string) string {
|
func runCommand(command string, shell string) string {
|
||||||
cmd := exec.Command(shell, "-c", command)
|
cmd := exec.Command(shell, "-c", command)
|
||||||
workdir, err := os.Getwd()
|
workdir, err := os.Getwd()
|
||||||
|
|||||||
Reference in New Issue
Block a user