#!/usr/bin/python
# sysinfo.py
# written by Darren Kirby :: bulliver@badcomputer.org
# Released under the Artistic License
import sys, os
import re, glob
import time
from getopt import gnu_getopt, GetoptError
appname = sys.argv[0]
appversion = "0.3"
out = sys.stdout
start = time.time()
def getOptions():
'''
Process command line options/arguments
If there are none, we show everything
TODO:
Allow html output option...
If you want txt file output, just use shell redirect (ie: 'sysinfo.py > report.txt')
'''
try:
opts, args = gnu_getopt(sys.argv[1:], "cmkhnfupa", ["cpu", "memory", "kernel", "hardware", "network", "filesystem", "user",
"package", "help"])
except GetoptError:
print("Invalid option(s)")
showUsage()
sys.exit(2)
flags = []
for opt, arg in opts:
if opt in ("-a", "--help"):
showUsage()
sys.exit(0)
if opt in ("-c", "--cpu"):
flags.append('c')
if opt in ("-m", "--memory"):
flags.append('m')
if opt in ("-k", "--kernel"):
flags.append('k')
if opt in ("-h", "--hardware"):
flags.append('h')
if opt in ("-n", "--network"):
flags.append('n')
if opt in ("-f", "--filesystem"):
flags.append('f')
if opt in ("-u", "--user"):
flags.append('u')
if opt in ("-p", "package"):
flags.append('p')
if flags == []:
flags = ['c','m','k','h','n','f','u','p']
return flags
def percent(t,f):
s = float(f) / float(t)
s = str(s)
if s == "1.0":
return "100"
else:
return s[2:4]
def endReport(status):
'''
Timestamp, cleanup, and exit
'''
out.write("Report created: %s\n" % (time.asctime()))
end = time.time()
duration = end - start
out.write("Report took %f seconds to create\n" % (duration))
out.close()
sys.exit(status)
def uptime():
'''
Get '/proc/uptime' and convert to d:h:m format
If not, get value of 'uptime' command
'''
oneday = 86400
onehour = 3600
oneminute = 60
try:
uptimes = open("/proc/uptime").readline().split()
uptimes = int(uptimes[0].split(".")[0])
except:
return os.popen("uptime").readline()
days = uptimes / oneday
upmind = uptimes - (days * oneday)
hours = upmind / onehour
upminh = upmind - (hours * onehour)
minutes = upminh / oneminute
if (days == 0) and (hours == 0):
return "%im (%f)" % (minutes, uptimes)
elif (days == 0):
if int(minutes) <= 9:
return "%ihr 0%im (%.2fs)" % (hours, minutes, uptimes)
else:
return "%ihr %im (%.2fs)" % (hours, minutes, uptimes)
else:
return "%id %ihr %im (%.2fs)" % (days, hours, minutes, uptimes)
def getIdeInfo():
'''
IDE information
This should print the size of the HDD, but kernel only provides
the number of sectors. How to find out bytes/sector?
'''
idepath = '/proc/ide/'
devlist = os.listdir(idepath)
devlist.sort()
for dev in devlist:
if 'hd' in dev:
out.write("/dev/%s information:\n" % (dev))
dtype = open(idepath + dev + "/media").readline()[:-1]
out.write("\tType: %s" % (dtype))
out.write("\tModel: %s" % (open(idepath + dev + "/model").readline()[:-1]))
if dtype == "disk":
out.write("\tCache: %s" % (open(idepath + dev + "/cache").readline()[:-1]))
out.write("\tGeometry: %s" % (open(idepath + dev + "/geometry").readlines()[1][:-1]))
out.write("\n")
out.write("\n")
def getScsiInfo():
'''
SCSI disk summary is in /proc/scsi/scsi
This good enough?
'''
out.write("SCSI information:\n")
try:
for line in open("/proc/scsi/scsi").readlines():
out.write("\t%s" % (line))
except:
out.write("\tUnable to get SCSI information\n")
out.write("\n")
def getSataInfo():
'''
I have no SATA devices...
How to report it?
'''
pass
def getMetaInfo():
'''
This info will always be printed
'''
out.write("### System Information ###\n\n")
try:
distFile = glob.glob("/etc/*release")
distro = open(distFile[0]).readline()
except:
distro = "Unknown"
meta = os.uname()
out.write("Hostname:\t %s\n" % (meta[1]))
out.write("OS:\t\t %s\n" % (meta[0]))
out.write("Distribution:\t %s" % (distro))
out.write("Platform:\t %s\n" % (meta[4]))
out.write("\n")
def getCpuInfo():
'''
This is totally broken...
It only works for single CPU systems.
- need someones '/proc/cpuinfo' for an x86, amd64, ppc, other? SMP system
- sparc changed cpuinfo output, shows clock ticks instead of CPU MHz
'''
out.write("### CPU information ###\n\n")
cpu = open("/proc/cpuinfo")
try:
for line in cpu.readlines():
if "model name" in line:
out.write("CPU model:\t%s" % (line.split(":")[1]))
if "cpu MHz" in line:
out.write("CPU speed:\t%s" % (line.split(":")[1]))
if "cache size" in line:
out.write("CPU cache:\t%s" % (line.split(":")[1]))
if "bogomips" in line:
out.write("Bogomips:\t%s" % (line.split(":")[1]))
# else:
# #try:
# for line in cpu.readlines(): # dirty hack for sparc
# if "cpu" in line:
# if not "ncpus" in line:
# out.write("CPU model:\t%s" % (line.split(":")[1]))
# if "ncpus probed" in line:
# out.write("\tCPUs probed: %s" % (line.split(":")[1])) # chomp
# if "ncpus active" in line:
# out.write("\tCPUs active:%s\n" % (line.split(":")[1]))
# if "Bogo" in line:
# print line.split(":")
# out.write("\tCPU %s bogomips:\t%s" % (line.split(":")[1], line.split(":")[0][:4]))
except:
out.write("No CPU info\n")
cpu.close()
out.write("\n")
def getMemInfo():
'''
Reads figures from /proc/meminfo
Do people want +/- buffers/cache?
If so might as well just print 'free -m' output!
I like mine better ... it is cleaner (but less portable)
'''
out.write("### Memory information ###\n\n")
for i in open("/proc/meminfo").readlines():
if "Buffers:" in i:
b = int(i.split()[-2])
if re.match("^Cached",i):
c = int(i.split()[-2])
if "MemTotal" in i:
memt = int(i.split()[-2]) / 1024
if "MemFree" in i:
memf = int(i.split()[-2])
if "SwapTotal" in i:
swpt = int(i.split()[-2]) / 1024
if "SwapFree" in i:
swpf = int(i.split()[-2]) / 1024
memf = (memf + b + c) / 1024
out.write("Total RAM:\t%iM\n" % (memt))
out.write("Free RAM: \t%iM (%s%%)\n" % (memf, percent(memt,memf)))
out.write("Total Swap:\t%iM\n" % (swpt))
out.write("Free Swap:\t%iM (%s%%)\n" % (swpf, percent(swpt,swpf)))
for line in open("/proc/swaps").readlines():
if "/dev/" in line:
swapl = line.split()
out.write("Swap location:\t%s\tType: %s\n" % (swapl[0], swapl[1]))
out.write("\n")
def getKernelInfo():
'''
Depends on proc filesystem
'''
out.write("### Kernel information ###\n\n")
kernv = os.uname()
out.write("Kernel version:\t%s\n" % (kernv[2]))
out.write("Kernel uptime:\t%s\n" % (uptime()))
out.write("Kernel build:\t%s\n" % (kernv[3]))
out.write("Kernel cmdline:\t%s" % (open("/proc/cmdline").readline()))
# Loaded modules...
mod_l = []
for module in open("/proc/modules").readlines():
mod_l.append(module.split()[0])
mod_l.reverse()
out.write("Loaded modules:\n")
if not mod_l:
out.write("\tNone\n")
return
try:
while mod_l != []:
out.write("\t")
for i in range(1,7):
out.write("%s | " % (mod_l.pop()))
out.write("\n")
except IndexError:
pass
out.write("\n")
# Supported FS...
fs_l = []
pfs_l = []
for fs in open("/proc/filesystems").readlines():
if not "nodev" in fs:
fs_l.append(fs.split()[0])
else:
pfs_l.append(fs.split()[1])
fsl_l = fs_l
out.write("Filesystems supported:\n")
try:
while fs_l != []:
out.write("\t")
for i in range(1,7):
out.write("%s | " % (fs_l.pop()))
out.write("\n")
except IndexError:
pass
out.write("\nOther possible supported filesystems (unloaded modules):\n")
opfs_l = os.listdir("/lib/modules/" + kernv[2] + "/kernel/fs")
opfss_l = []
for i in opfs_l:
if not i in fsl_l: # Remove loaded modules
opfss_l.append(i)
try:
while opfss_l != []:
out.write("\t")
for i in range(1,7):
out.write("%s | " % (opfss_l.pop()))
out.write("\n")
except IndexError:
pass
out.write("\nPseudo Filesystems supported:\n")
try:
while pfs_l != []:
out.write("\t")
for i in range(1,7):
out.write("%s | " % (pfs_l.pop()))
out.write("\n")
except IndexError:
pass
out.write("\n\n")
def getHardwareInfo():
'''
First, divide lspci output into categories
Second, try to find out disk information
TODO:
-How to deal with RAID?
-How to deal with USB devices? Monitors? Printers?
-Lots of types of hardware, but we only deal with HDD, optical drives and PCI stuff...
How to deal with other hardware?
'''
out.write("### Hardware information ###\n\n")
hasIde = hasScsi = hasSata = 0
try:
pcidev = os.popen("lspci").readlines()
except:
out.write("Cannot find 'lspci'\n")
return
out.write("Host/Bus bridges:\n")
for line in pcidev:
if "bridge" in line:
out.write("\t%s" % (line))
out.write("IDE controllers:\n")
flag = 0
for line in pcidev:
if "IDE" in line:
flag = 1; hasIde = 1
out.write("\t%s" % (line))
if flag == 0:
out.write("\tNone found\n")
out.write("SCSI controllers:\n")
flag = 0
for line in pcidev:
if "SCSI" in line:
flag = 1; hasScsi = 1
out.write("\t%s" % (line))
if flag == 0:
out.write("\tNone found\n")
out.write("SATA controllers:\n")
flag = 0
for line in pcidev:
if "Mass storage" in line:
flag = 1; hasSata = 1
out.write("\t%s" % (line))
if flag == 0:
out.write("\tNone found\n")
out.write("USB controllers:\n")
flag = 0
for line in pcidev:
if "USB" in line:
flag = 1
out.write("\t%s" % (line))
if flag == 0:
out.write("\tNone found\n")
out.write("Network adapters:\n")
flag = 0
for line in pcidev:
if "Ethernet" in line:
flag = 1
out.write("\t%s" % (line))
if flag == 0:
out.write("\tNone found\n")
out.write("Audio controllers:\n")
flag = 0
for line in pcidev:
if "Multimedia" in line:
flag = 1
out.write("\t%s" % (line))
if flag == 0:
out.write("\tNone found\n")
out.write("FireWire ports:\n")
flag = 0
for line in pcidev:
if "FireWire" in line:
flag = 1
out.write("\t%s" % (line))
if flag == 0:
out.write("\tNone found\n")
out.write("Display adapters:\n")
flag = 0
for line in pcidev:
if "VGA" in line:
flag = 1
out.write("\t%s" % (line))
out.write("\n")
if hasIde == 1:
getIdeInfo()
if hasScsi == 1:
getScsiInfo()
if hasSata == 1:
getSataInfo()
def getNetworkInfo():
'''
Depends on 'ifconfig', 'route', and proc filesystem
'''
out.write("### Network information ###\n\n")
dev = []
dev_l = open("/proc/net/dev").readlines()
for d in dev_l[2:]:
dev.append(d.split(":")[0])
out.write("Network devices:")
for d in dev:
out.write(" %s " % (d.strip(" ")))
out.write("\n")
for d in dev:
out.write("%s information:\n" % (d.strip(" ")))
devinfo = os.popen("ifconfig " + d).readlines()
for line in devinfo:
if "HWaddr" in line:
out.write("\tMAC address:\t%s\n" % (line.split()[4]))
if "inet addr" in line:
x = line.split()
ips = []
for ip in x[1:]:
ips.append(ip.split(":")[1])
if len(ips) == 2:
out.write("\tIP address:\t%s\n" % (ips[0]))
out.write("\tNetmask:\t%s" % (ips[1]))
else:
out.write("\tIP address:\t%s\n" % (ips[0]))
out.write("\tBroadcast:\t%s\n" % (ips[1]))
out.write("\tNetmask:\t%s" % (ips[2]))
out.write("\n")
gw = os.popen("route -n").readlines()
out.write("Default gw:\t%s\n" % (gw[-1].split()[1]))
ns = open("/etc/resolv.conf").readlines()
for line in ns:
if "nameserver" in line:
out.write("Nameserver:\t%s\n" % (line.split()[1]))
out.write("\n")
def getMountInfo():
'''
Depends on 'df'
'''
out.write("### Partition/diskspace information ###\n\n")
out.write("Mounted devices:\n")
mounts = os.popen("mount").readlines()
r =[]; p = []; n = []
for line in mounts:
if "/dev/" in line.split()[0]:
r.append(line)
if ":" in line.split()[0]:
n.append(line)
if not "/dev/" in line.split()[0]:
if not ":" in line.split()[0]:
p.append(line)
r.sort(); p.sort(); n.sort()
for mount in r:
out.write("\t")
out.write(mount)
if n != []:
out.write("Network mounts:\n")
for mount in n:
out.write("\t")
out.write(mount)
out.write("Psuedo mounts:\n")
for mount in p:
out.write("\t")
out.write(mount)
out.write("Disk usage:\n")
for line in os.popen("df -h").readlines():
out.write("\t" + line)
out.write("\n")
def getUserInfo():
'''
This depends on 'id' and 'groups' command
Can you get this info in pure python?
'''
out.write("### User/group information ###\n\n")
out.write("Human users:\n")
users = []; ruser = []; groups = []
for line in open("/etc/passwd").readlines():
if (line.split(":")[0] in line.split(":")[5]) and ("/home/" in line.split(":")[5]) and not ("/false" in line.split(":")[-1]):
ruser.append(line.split(":")[0])
else:
users.append(line.split(":")[0])
users.sort()
for user in ruser:
guid = os.popen("id " + user).readline().split()
uid = guid[0].split("(")[0]; gid = guid[1].split("(")[0]
out.write("\t%s: %s %s Groups: %s" % (user, uid, gid, os.popen("groups " + user).readline()))
out.write("System users:\n")
for user in users:
guid = os.popen("id " + user).readline().split()
uid = guid[0].split("(")[0]; gid = guid[1].split("(")[0]
out.write("\t%s: %s %s Groups: %s" % (user, uid, gid, os.popen("groups " + user).readline()))
out.write("Groups:\n")
for line in open("/etc/group").readlines():
t = (line.split(":")[0], line.split(":")[2])
groups.append(t)
groups.sort()
groups.reverse()
try:
while groups != []:
out.write("\t")
for i in range(1,7):
out.write("%s(%s) | " % (groups.pop()))
out.write("\n")
except IndexError:
pass
out.write("\n")
def getGentooPackageInfo():
'''
First check for epm, if not use equery
epm is _way_ faster (because it uses a DB) in my tests
Also, equery breaks columned output
'''
out.write("\tInstalled Gentoo packages:\n")
if os.path.exists("/usr/bin/epm"):
for line in os.popen("epm -qa | sort | column -x").readlines():
out.write("\t%s" % (line))
endReport(0)
if os.path.exists("/usr/bin/equery"):
for line in os.popen("equery list -i | column -x").readlines():
out.write("\t%s" % (line))
endReport(0)
else:
out.write("Neither epm nor equery found...\n")
out.write("Unable to provide package list\n")
endReport(1)
def getArchPackageInfo():
'''
Arch Linux packages
'''
out.write("\tInstalled Arch packages:\n")
for line in os.popen("pacman -Q | column -x").readlines():
out.write("\t%s" % (line))
endReport(0)
def getRpmPackageInfo():
'''
This should work on any system that uses RPM
'''
out.write("\tInstalled RPM packages:\n")
for line in os.popen("rpm -qa | sort | column -x").readlines():
out.write("\t%s" % (line))
endReport(0)
def getDpkgPackageInfo():
'''
Unsure of dpkg command or output
Help anyone?
'''
out.write("dpkg output not yet implemented\n")
endReport(0)
def getPackageInfo():
out.write("\n### Package information ###\n\n")
try:
distFile = glob.glob("/etc/*release")
distro = open(distFile[0]).readline()
except:
out.write("Can't confirm distribution, unable to provide package info\n")
endReport(0)
if "Gentoo" in distro:
getGentooPackageInfo()
if "Arch" in distro:
getArchPackageInfo()
if "Fedora" in distro:
getRpmPackageInfo()
if "Redhat" in distro:
getRpmPackageInfo()
if "SuSe" in distro:
getRpmPackageInfo()
# What other distros use RPMs?
if "Debian" in distro:
getDpkgPackageInfo()
if "Ubuntu" in distro:
getDpkgPackageInfo()
# slackware?
def showBanner():
print "%s version %s" % (appname, appversion)
print '''Written by Darren Kirby :: d@badcomputer.org :: http://badcomputer.org/unix/code/sysinfo.bot
Released under the Artistic License.
'''
def showUsage():
showBanner()
print "Usage: %s [options]" % (appname)
print ''' Options:
'-a' or '--help' display usage details (this!)
'-c' or '--cpu' display CPU information
'-m' or '--memory' display memory information
'-k' or '--kernel' display kernel information
'-h' or '--hardware' display hardware information
'-n' or '--network' display network information
'-f' or '--filesystem' display filesystem/mount information
'-u' or '--user' display user/group information
'-p' or '--package' display installed package information (will not work on all distros)
'''
def main():
flags = getOptions()
showBanner()
getMetaInfo()
if 'c' in flags:
getCpuInfo()
if 'm' in flags:
getMemInfo()
if 'k' in flags:
getKernelInfo()
if 'h' in flags:
getHardwareInfo()
if 'n' in flags:
getNetworkInfo()
if 'f' in flags:
getMountInfo()
if 'u' in flags:
getUserInfo()
if 'p' in flags:
getPackageInfo()
endReport(0)
if __name__ == '__main__':
main()