// sysinfo package paste import ( "bytes" "io/ioutil" "os/exec" "regexp" "strconv" "strings" "text/template" "github.com/rocky-linux/rpaste/modules/setting" "github.com/rocky-linux/rpaste/modules/utility" ) var ( buf bytes.Buffer osID string sysInfoReturn string ) 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 AppArmorStatus string } // Distro agnostic functions 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 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 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 efiSupport() string { app := "efibootmgr" args := []string{"-v"} cmd, _ := exec.Command(app, args...).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) } // End agnostic functions // Red Hat (EL, Fedora) specific functions that may not work elsewhere // using these on non-rh distros should be used with caution. 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 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) } // End Red Hat functions // SuSE specific functions // End SuSE // Debian/Ubuntu specific functions // End Debian // AppArmor, affects Debian/Ubuntu/SuSE func appArmorStatus() string { app := "aa-status" cmd, _ := exec.Command(app).CombinedOutput() return string(cmd) } // End AppArmor func SysInfoGather() string { osID = utility.GetGenericDistroID() switch osID { case "redhat": sysInfoReturn = redHatSysInfoGather() case "suse": sysInfoReturn = suseSysInfoGather() } return sysInfoReturn } func redHatSysInfoGather() 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.RedHatSysInfoTemplate) t.Execute(&buf, sysInfoData) sysInfoResults := buf.String() return sysInfoResults } func suseSysInfoGather() string { sysInfoData := SystemInfo{ OsRelease: osRelease(), DesktopEnvs: desktopEnvs(), DesktopInstalled: desktopInstalled(), AppArmorStatus: appArmorStatus(), 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(), LastTwentyPackages: lastTwentyPkgs(), EFISupport: efiSupport(), } t := template.New("sysinfo") t, _ = t.Parse(setting.SuseSysInfoTemplate) t.Execute(&buf, sysInfoData) sysInfoResults := buf.String() return sysInfoResults }