Last active
November 6, 2024 17:53
-
-
Save hitalos/b67024ea505a33fd429b51f25ab74fa2 to your computer and use it in GitHub Desktop.
Get system info from linux files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module sysfetch | |
go 1.23.2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"bytes" | |
"fmt" | |
"os" | |
"strconv" | |
"strings" | |
"time" | |
) | |
type Item struct { | |
title string | |
info func() string | |
} | |
var ( | |
shell string | |
items = []Item{ | |
{"User", func() (user string) { user, shell = userInfo(); return }}, | |
{"OS", osInfo}, | |
{"Shell", func() string { return shell }}, | |
{"Kernel", kernel}, | |
{"Host", host}, | |
{"CPU", cpu}, | |
{"Uptime", uptime}, | |
{"Memory", memory}, | |
} | |
) | |
func maxLength(items []Item) int { | |
max := 0 | |
for _, item := range items { | |
if len(item.title) > max { | |
max = len(item.title) | |
} | |
} | |
return max | |
} | |
func printInfo(title string, info string) { | |
os.Stdout.WriteString(title + ": " + strings.Repeat(" ", maxLength(items)-len(title)) + info + "\n") | |
} | |
func userInfo() (string, string) { | |
hostnameContent, _ := os.ReadFile("/etc/hostname") | |
statusContent, _ := os.ReadFile(fmt.Sprintf("/proc/%d/status", os.Getpid())) | |
passwdContent, _ := os.ReadFile("/etc/passwd") | |
var uid, user, shell string | |
for _, line := range strings.Split(string(statusContent), "\n") { | |
if strings.HasPrefix(line, "Uid:") { | |
uid = strings.Split(strings.Split(line, ":")[1], "\t")[1] | |
break | |
} | |
} | |
for _, line := range strings.Split(string(passwdContent), "\n") { | |
parts := strings.Split(line, ":") | |
if parts[2] == uid { | |
user = parts[0] + "@" + strings.TrimSpace(string(hostnameContent)) | |
shell = parts[6] | |
break | |
} | |
} | |
return user, shell | |
} | |
func osInfo() string { | |
osRelease, _ := os.ReadFile("/etc/os-release") | |
for _, line := range strings.Split(string(osRelease), "\n") { | |
if strings.Contains(line, "PRETTY_NAME") { | |
return string(osRelease)[len(`PRETTY_NAME="`) : len(line)-1] | |
} | |
} | |
return "" | |
} | |
func kernel() string { | |
kernelVersion, _ := os.ReadFile("/proc/sys/kernel/osrelease") | |
kernelArch, _ := os.ReadFile("/proc/sys/kernel/arch") | |
return fmt.Sprintf("%s %s", bytes.TrimSpace(kernelVersion), bytes.TrimSpace(kernelArch)) | |
} | |
func host() string { | |
hostVendor, _ := os.ReadFile("/sys/devices/virtual/dmi/id/board_vendor") | |
hostBoard, _ := os.ReadFile("/sys/devices/virtual/dmi/id/board_name") | |
return fmt.Sprintf("%s (%s)", bytes.TrimSpace(hostVendor), bytes.TrimSpace(hostBoard)) | |
} | |
func cpu() string { | |
f, _ := os.Open("/proc/cpuinfo") | |
defer f.Close() | |
scan := bufio.NewScanner(f) | |
var line, cpuModel, cpuCores string | |
for scan.Scan() { | |
line = scan.Text() | |
if strings.Contains(line, "model name") { | |
cpuModel = strings.TrimSpace(strings.Split(line, ":")[1]) | |
continue | |
} | |
if strings.Contains(line, "cpu cores") { | |
cpuCores = strings.TrimSpace(strings.Split(line, ":")[1]) | |
break | |
} | |
} | |
return cpuModel + " (x" + cpuCores + ")" | |
} | |
func uptime() string { | |
uptimeContent, _ := os.ReadFile("/proc/uptime") | |
uptimeSeconds := uptimeContent[:bytes.Index(uptimeContent, []byte("."))] | |
uptimeDuration, _ := time.ParseDuration(string(uptimeSeconds) + "s") | |
daysCount := uptimeDuration / (24 * time.Hour) | |
hoursCount := int(uptimeDuration.Hours()) % 24 | |
minutesCount := int(uptimeDuration.Minutes()) % 60 | |
days := "" | |
switch daysCount { | |
case 1: | |
days = "1 dia, " | |
default: | |
days = fmt.Sprintf("%d dias, ", daysCount) | |
} | |
hours := "" | |
switch hoursCount { | |
case 1: | |
hours = "1 hora e " | |
default: | |
hours = fmt.Sprintf("%d horas e ", hoursCount) | |
} | |
minutes := "" | |
switch minutesCount { | |
case 1: | |
minutes = "1 minuto" | |
default: | |
minutes = fmt.Sprintf("%d minutos", minutesCount) | |
} | |
return days + hours + minutes | |
} | |
func formatBytes(val int) string { | |
bytes := float64(val) | |
unit := "B" | |
if bytes >= 1024 { | |
bytes /= 1024 | |
unit = "KB" | |
} | |
if bytes >= 1024 { | |
bytes /= 1024 | |
unit = "MB" | |
} | |
if bytes >= 1024 { | |
bytes /= 1024 | |
unit = "GB" | |
} | |
return fmt.Sprintf("%.3f %s", bytes, unit) | |
} | |
func memory() string { | |
f, _ := os.Open("/proc/meminfo") | |
defer f.Close() | |
scan := bufio.NewScanner(f) | |
var line, memory, free string | |
for scan.Scan() { | |
line = scan.Text() | |
if strings.Contains(line, "MemTotal") { | |
memory = strings.TrimSpace(strings.Split(line, ":")[1]) | |
continue | |
} | |
if strings.Contains(line, "MemAvailable") { | |
free = strings.TrimSpace(strings.Split(line, ":")[1]) | |
break | |
} | |
} | |
memoryTotal, _ := strconv.Atoi(memory[:strings.Index(memory, " ")]) | |
memoryFree, _ := strconv.Atoi(free[:strings.Index(free, " ")]) | |
percUsed := (float64(memoryTotal - memoryFree)) / float64(memoryTotal) * 100 | |
return fmt.Sprintf("%s / %s (%.2f%%)", formatBytes(1024*memoryFree), formatBytes(1024*memoryTotal), percUsed) | |
} | |
func main() { | |
for _, item := range items { | |
printInfo(item.title, item.info()) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { readFile } = require('fs/promises') | |
const items = ['User', 'OS', 'Shell', 'Kernel', 'Host', 'CPU', 'Uptime', 'Memory'] | |
const max_length = items.reduce((a, b) => a.length > b.length ? a : b).length | |
const print_info = (title, info) => { | |
const spaces = ' '.repeat(max_length - title.length) | |
process.stdout.write(`${title}: ${spaces}${info}\n`) | |
} | |
const format_bytes = (val) => { | |
let bytes = val | |
let unit = bytes >= 1024 ? ((bytes /= 1024), 'KB') : 'B' | |
unit = bytes >= 1024 ? ((bytes /= 1024), 'MB') : unit | |
unit = bytes >= 1024 ? ((bytes /= 1024), 'GB') : unit | |
return `${bytes.toFixed(3)} ${unit}` | |
} | |
const format_time = (time) => { | |
const seconds = parseInt(time.trim()) | |
const out = { | |
days: Math.floor(seconds / 86400), | |
hours: Math.floor((seconds % 86400) / 3600), | |
minutes: Math.floor(((seconds % 86400) % 3600) / 60), | |
} | |
switch (out.days) { | |
case 0: out.days = ''; break | |
case 1: out.days = '1 dia, '; break | |
default: out.days = `${out.days} dias, ` | |
} | |
switch (out.hours) { | |
case 0: out.hours = ''; break | |
case 1: out.hours = '1 hora e '; break | |
default: out.hours = `${out.hours} horas e ` | |
} | |
switch (out.minutes) { | |
case 1: out.minutes = '1 minuto'; break | |
default: out.minutes = `${out.minutes} minutos` | |
} | |
return `${out.days}${out.hours}${out.minutes}` | |
} | |
const userinfo = (hostnameContent, statusContent, passwdContent) => { | |
const uid = /Uid:\s+(\d+)\s/.exec(statusContent)[1] | |
const passwdLine = passwdContent.split('\n').filter((line) => line.split(':')[2] === uid)[0].split(':') | |
return { user: `${passwdLine[0]}@${hostnameContent.trim()}`, shell: passwdLine[6] } | |
} | |
const cpu = (content) => { | |
const lines = content.split('\n') | |
const model = lines.filter((l) => l.includes('model name'))[0].split(': ')[1].trim() | |
const cores = lines.filter((l) => l.includes('cpu cores'))[0].split(': ')[1].trim() | |
return `${model} (x${cores})` | |
} | |
const memory = (content) => { | |
const lines = content.split('\n') | |
const total = parseInt(lines.filter((l) => l.includes('MemTotal'))[0].split(': ')[1].trim()) * 1024 | |
const free = parseInt(lines.filter((l) => l.includes('MemAvailable'))[0].split(': ')[1].trim()) * 1024 | |
const percUsed = ((total-free)/total)*100 | |
return `${format_bytes(free)} / ${format_bytes(total)} (${percUsed.toFixed(2)}%)` | |
} | |
Promise.all([ | |
readFile('/etc/hostname', 'utf-8'), | |
readFile(`/proc/${process.pid}/status`, 'utf-8'), | |
readFile('/etc/passwd', 'utf-8'), | |
readFile('/etc/os-release', 'utf-8'), | |
readFile('/proc/sys/kernel/osrelease', 'utf-8'), | |
readFile('/proc/sys/kernel/arch', 'utf-8'), | |
readFile('/sys/devices/virtual/dmi/id/board_vendor', 'utf-8'), | |
readFile('/sys/devices/virtual/dmi/id/board_name', 'utf-8'), | |
readFile('/proc/cpuinfo', 'utf-8'), | |
readFile('/proc/uptime', 'utf-8'), | |
readFile('/proc/meminfo', 'utf-8'), | |
]).then((results) => { | |
const info = userinfo(results[0], results[1], results[2]) | |
return { | |
User: info.user, | |
OS: /PRETTY_NAME="(.+)"/.exec(results[3])[1], | |
Shell: info.shell, | |
Kernel: `${results[4].trim()} ${results[5].trim()}`, | |
Host: `${results[6].trim()} (${results[7].trim()})`, | |
CPU: cpu(results[8]), | |
Uptime: format_time(results[9]), | |
Memory: memory(results[10]), | |
} | |
}).then((result) => items.forEach((item) => print_info(item, result[item]))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment