Add SysInfo Functions

Add sysinfo functions, template updates, stuff like that
This commit is contained in:
nazunalika 2021-12-27 11:45:46 -07:00
parent 2157e8a343
commit c901ee769b
Signed by: label
GPG Key ID: 6735C0E1BD65D048
4 changed files with 502 additions and 36 deletions

View File

@ -3,6 +3,7 @@ package paste
import ( import (
"fmt" "fmt"
"io/ioutil"
"os" "os"
"github.com/rocky-linux/rpaste/modules/utility" "github.com/rocky-linux/rpaste/modules/utility"
@ -21,47 +22,36 @@ var (
func runPaste(ctx *cli.Context) error { func runPaste(ctx *cli.Context) error {
// check // check
stdResults := utility.StdInChecker() stdMethod := utility.StdInChecker()
sysInfoMethod := ctx.Bool("sysinfo")
// If there's no more than 1 argument (the executable itself is arg 0), we // Check sysinfo is enabled and run through all the required stuff
// will check for stdin, and if not, print out the usage information. if sysInfoMethod {
//if stdResults { PasteData = SysInfoGather()
// fio, err := os.Stdin.Stat() }
// if (fio.Mode() & os.ModeCharDevice) == 0 {
// bytes, _ := ioutil.ReadAll(os.Stdin)
// PasteData = string(bytes)
// } else if err != nil {
// fmt.Printf("Could not read from stdin: (%s)\n", err)
// os.Exit(1)
// }
//} else {
// cli.ShowAppHelp(ctx)
// os.Exit(0)
//}
// Check args for a file or sysinfo if stdMethod && PasteData == "" {
//if len(PasteData) == 0 { fio, err := os.Stdin.Stat()
// if ctx.Bool("sysinfo") { if (fio.Mode() & os.ModeCharDevice) == 0 {
// //PasteData = GatherSysInfo() bytes, _ := ioutil.ReadAll(os.Stdin)
// PasteData = "Sys Info" PasteData = string(bytes)
// } else { } else if err != nil {
// // Path is expected at the end of the command (matches current rpaste) fmt.Printf("Could not read from stdin: (%s)\n", err)
// argList := os.Args os.Exit(1)
// lastArg := argList[len(argList)-1] }
// fileBytes, err := ioutil.ReadFile(lastArg) } else if !stdMethod && PasteData == "" {
// if err != nil { argList := os.Args
// panic(err) lastArg := argList[len(argList)-1]
// } fileBytes, err := ioutil.ReadFile(lastArg)
// PasteData = string(fileBytes) if err != nil {
// } panic(err)
//} }
PasteData = string(fileBytes)
}
// Check that PasteData is text, and not binary // Check that PasteData is text, and not binary
fmt.Println(len(PasteData)) fmt.Println(PasteData)
for i, arg := range os.Args {
fmt.Println("item", i, "is", arg)
}
return nil return nil
} }

View File

@ -1,2 +1,296 @@
// sysinfo // sysinfo
package paste package paste
import (
"bytes"
"io/ioutil"
"os/exec"
"regexp"
"strconv"
"strings"
"text/template"
"github.com/rocky-linux/rpaste/modules/setting"
)
var (
buf bytes.Buffer
)
type SystemInfo struct {
OsRelease string
DesktopEnvs string
DesktopInstalled string
SELinuxStatus string
SELinuxErrors string
CPUInfo string
Support64bit string
VirtSupport string
LoadAverage string
MemUsage string
TopCPUHogs string
TopMemHogs string
DiskUsage string
BlockDevs string
PciDevs string
USBDevs string
DRMInfo string
XorgModules string
GLSupport string
XorgErrors string
DmesgTail string
LastTenReboots string
DnfRepoList string
DnfRepoFiles string
YumConf string
LastTwentyPackages string
EFISupport string
}
func osRelease() string {
app := "uniq"
args := []string{"/etc/os-release"}
cmd, _ := exec.Command(app, args...).CombinedOutput()
return string(cmd)
}
func desktopEnvs() string {
// The below just returns whatever the match is, rather than each match. The
// original command (and by extension, the original fpaste python script and
// rpaste bash script) would spit out more than just the expected result
app := "ps"
args := []string{
"-eo",
"comm=",
}
cmd, _ := exec.Command(app, args...).CombinedOutput()
re, _ := regexp.Compile(`(gnome-session|startkde|startactive|xfce.?-session|fluxbox|blackbox|hackedbox|ratpoison|enlightenment|icewm-session|od-session|wmaker|wmx|openbox-lxde|openbox-gnome-session|openbox-kde-session|mwm|e16|fvwm|xmonad|sugar-session|mate-session|lxqt-session|cinnamon)`)
values := re.FindString(string(cmd))
return values
}
func desktopInstalled() string {
app := "ls"
args := []string{
"-m",
"/usr/share/xsessions/",
}
cmd, _ := exec.Command(app, args...).CombinedOutput()
re, _ := regexp.Compile(`\.desktop`)
values := re.ReplaceAllString(string(cmd), "")
return values
}
func selinuxStatus() string {
app1 := "getenforce"
app2 := "grep -v '^#' /etc/sysconfig/selinux"
cmd1, _ := exec.Command(app1).CombinedOutput()
cmd2, _ := exec.Command("/bin/sh", "-c", app2).CombinedOutput()
combined := string(cmd1) + string(cmd2)
return combined
}
func selinuxErrors() string {
// I'm not proud of this
app := "journalctl --since yesterday |grep avc: | grep -Eo comm='[^ ]+' | sort |uniq -c |sort -rn"
cmd, _ := exec.Command("/bin/sh", "-c", app).CombinedOutput()
return string(cmd)
}
func cpuInfo() string {
// I'm not proud of this
app := "grep 'model name' /proc/cpuinfo | awk -F: '{print $2}' | uniq -c | sed -re 's/^ +//'"
cmd, _ := exec.Command("/bin/sh", "-c", app).CombinedOutput()
return string(cmd)
}
func support64Bit() string {
text := " lm "
file, _ := ioutil.ReadFile("/proc/cpuinfo")
string := string(file)
return strconv.FormatBool(strings.Contains(string, text))
}
func virtSupport() string {
re, _ := regexp.Compile(`(vmx|svm)`)
file, _ := ioutil.ReadFile("/proc/cpuinfo")
exists := re.Match(file)
return strconv.FormatBool(exists)
}
func loadAverage() string {
app := "uptime"
cmd, _ := exec.Command(app).CombinedOutput()
return string(cmd)
}
func memUsage() string {
app := "free"
args := []string{"-m"}
cmd, _ := exec.Command(app, args...).CombinedOutput()
return string(cmd)
}
func topCPUHogs() string {
// I'm not proud of this
app := "ps axuScnh | sort -rnk3 | head -5"
cmd, _ := exec.Command("/bin/sh", "-c", app).CombinedOutput()
return string(cmd)
}
func topMemHogs() string {
// I'm not proud of this
app := "ps axuScnh | sort -rnk4 | head -5"
cmd, _ := exec.Command("/bin/sh", "-c", app).CombinedOutput()
return string(cmd)
}
func diskUsage() string {
app := "df"
args := []string{"-hT"}
cmd, _ := exec.Command(app, args...).CombinedOutput()
return string(cmd)
}
func blockDevs() string {
app := "/sbin/blkid"
cmd, _ := exec.Command(app).CombinedOutput()
return string(cmd)
}
func pciDevs() string {
app := "/sbin/lspci"
args := []string{"-nn"}
cmd, _ := exec.Command(app, args...).CombinedOutput()
return string(cmd)
}
func usbDevs() string {
app := "/bin/lsusb"
cmd, _ := exec.Command(app).CombinedOutput()
return string(cmd)
}
func drmInfo() string {
// I'm not proud of this
app := "journalctl -k -b | grep -o 'kernel:.*drm.*$' | cut -d ' ' -f 2-"
cmd, _ := exec.Command("/bin/sh", "-c", app).CombinedOutput()
return string(cmd)
}
func xorgModules() string {
// I'm not proud of this
app := "grep LoadModule /var/log/Xorg.0.log ~/.local/share/xorg/Xorg.0.log | cut -d '\"' -f 2 | xargs"
cmd, _ := exec.Command("/bin/sh", "-c", app).CombinedOutput()
return string(cmd)
}
func glSupport() string {
// I'm not proud of this
// turn to golang regexp? we would rather get the error output regardless
app := "glxinfo | grep -E 'OpenGL version|OpenGL renderer'"
cmd, _ := exec.Command("/bin/sh", "-c", app).CombinedOutput()
return string(cmd)
}
func xorgErrors() string {
// I'm not proud of this
app := "grep '^\\[.*(EE)' /var/log/Xorg.0.log ~/.local/share/xorg/Xorg.0.log | cut -d ':' -f 2-"
cmd, _ := exec.Command("/bin/sh", "-c", app).CombinedOutput()
return string(cmd)
}
func dmesgTail() string {
// I'm not proud of this
// Maybe I can implement a tail-like function
app := "dmesg | tail"
cmd, _ := exec.Command("/bin/sh", "-c", app).CombinedOutput()
return string(cmd)
}
func lastTenReboots() string {
app := "last"
args := []string{
"-x",
"-n10",
"reboot",
"runlevel",
}
cmd, _ := exec.Command(app, args...).CombinedOutput()
return string(cmd)
}
func dnfRepoList() string {
app := "dnf"
args := []string{"repolist"}
cmd, _ := exec.Command(app, args...).CombinedOutput()
return string(cmd)
}
func dnfRepoFiles() string {
app := "ls"
args := []string{
"-l",
"/etc/yum.repos.d/",
}
cmd, _ := exec.Command(app, args...).CombinedOutput()
return string(cmd)
}
func yumConf() string {
app := "grep -v '^#' /etc/yum.conf"
cmd, _ := exec.Command("/bin/sh", "-c", app).CombinedOutput()
return string(cmd)
}
func lastTwentyPkgs() string {
app := "rpm -qa --nodigest --nosignature --last | head -20"
cmd, _ := exec.Command("/bin/sh", "-c", app).CombinedOutput()
return string(cmd)
}
func efiSupport() string {
app := "efibootmgr"
args := []string{"-v"}
cmd, _ := exec.Command(app, args...).CombinedOutput()
return string(cmd)
}
func SysInfoGather() string {
sysInfoData := SystemInfo{
OsRelease: osRelease(),
DesktopEnvs: desktopEnvs(),
DesktopInstalled: desktopInstalled(),
SELinuxStatus: selinuxStatus(),
SELinuxErrors: selinuxErrors(),
CPUInfo: cpuInfo(),
Support64bit: support64Bit(),
VirtSupport: virtSupport(),
LoadAverage: loadAverage(),
MemUsage: memUsage(),
TopCPUHogs: topCPUHogs(),
TopMemHogs: topMemHogs(),
DiskUsage: diskUsage(),
BlockDevs: blockDevs(),
PciDevs: pciDevs(),
USBDevs: usbDevs(),
DRMInfo: drmInfo(),
XorgModules: xorgModules(),
GLSupport: glSupport(),
XorgErrors: xorgErrors(),
DmesgTail: dmesgTail(),
LastTenReboots: lastTenReboots(),
DnfRepoList: dnfRepoList(),
DnfRepoFiles: dnfRepoFiles(),
YumConf: yumConf(),
LastTwentyPackages: lastTwentyPkgs(),
EFISupport: efiSupport(),
}
t := template.New("sysinfo")
t, _ = t.Parse(setting.SysInfoTemplate)
t.Execute(&buf, sysInfoData)
sysInfoResults := buf.String()
return sysInfoResults
}

129
modules/setting/template.go Normal file
View File

@ -0,0 +1,129 @@
package setting
var SysInfoTemplate = `################################################################################
# OS Release
#
{{.OsRelease}}
################################################################################
# Desktop Environments
#
{{.DesktopEnvs}}
################################################################################
# Desktop Installed
#
{{.DesktopInstalled}}
################################################################################
# SELinux Status
#
{{.SELinuxStatus}}
################################################################################
# SELinux Errors
#
{{.SELinuxErrors}}
################################################################################
# CPU Info
#
{{.CPUInfo}}
################################################################################
# 64-bit Support
#
{{.Support64bit}}
################################################################################
# Virtualization Support
#
{{.VirtSupport}}
################################################################################
# Load Average
#
{{.LoadAverage}}
################################################################################
# Memory usage
#
{{.MemUsage}}
################################################################################
# Top 5 CPU hogs
#
{{.TopCPUHogs}}
################################################################################
# Top 5 memory hogs
#
{{.TopMemHogs}}
################################################################################
# Disk space usage
#
{{.DiskUsage}}
################################################################################
# Block Devices
#
{{.BlockDevs}}
################################################################################
# PCI devices
#
{{.PciDevs}}
################################################################################
# USB devices
#
{{.USBDevs}}
################################################################################
# DRM Information
#
{{.DRMInfo}}
################################################################################
# Xorg modules
#
{{.XorgModules}}
################################################################################
# GL Support
#
{{.GLSupport}}
################################################################################
# Xorg errors
#
{{.XorgErrors}}
################################################################################
# Kernel Buffer Tail
#
{{.DmesgTail}}
################################################################################
# Last few reboots
#
{{.LastTenReboots}}
################################################################################
# DNF Repos
#
{{.DnfRepoList}}
{{.DnfRepoFiles}}
{{.YumConf}}
################################################################################
# Last 20 packages
#
{{.LastTwentyPackages}}
################################################################################
# EFI Support
#
{{.EFISupport}}
`

53
modules/utility/pipes.go Normal file
View File

@ -0,0 +1,53 @@
package utility
import (
"bytes"
"io"
"log"
"os/exec"
)
func ExecutePipe(outbuffer *bytes.Buffer, stack ...*exec.Cmd) (err error) {
var errbuffer bytes.Buffer
pipestack := make([]*io.PipeWriter, len(stack)-1)
i := 0
for ; i < len(stack)-1; i++ {
stdin_pipe, stdoutpipe := io.Pipe()
stack[i].Stdout = stdoutpipe
stack[i].Stderr = &errbuffer
stack[i+1].Stdin = stdin_pipe
pipestack[i] = stdoutpipe
}
stack[i].Stdout = outbuffer
stack[i].Stderr = &errbuffer
if err := callpipe(stack, pipestack); err != nil {
log.Fatalln(string(errbuffer.Bytes()), err)
}
return err
}
func callpipe(stack []*exec.Cmd, pipes []*io.PipeWriter) (err error) {
if stack[0].Process == nil {
if err = stack[0].Start(); err != nil {
return err
}
}
if len(stack) > 1 {
if err = stack[1].Start(); err != nil {
return err
}
defer func() {
if err == nil {
pipes[0].Close()
err = callpipe(stack[1:], pipes[1:])
}
}()
}
return stack[0].Wait()
}