Skip to content

Commit

Permalink
#720: sysinfo() linux impl
Browse files Browse the repository at this point in the history
  • Loading branch information
giampaolo committed Dec 18, 2015
1 parent 8986939 commit 866991a
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 0 deletions.
7 changes: 7 additions & 0 deletions psutil/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1894,6 +1894,13 @@ def users():
return _psplatform.users()


def sysinfo():
"""Return various system-wide information as a namedtuple whose
fields change depending on the platform.
"""
return _psplatform.sysinfo()


def test(): # pragma: no cover
"""List info of all currently running processes emulating ps aux
output.
Expand Down
35 changes: 35 additions & 0 deletions psutil/_pslinux.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,41 @@ def boot_time():
"line 'btime' not found in %s/stat" % get_procfs_path())


ssysinfo = namedtuple(
'ssysinfo', ['procs_running', 'procs_blocked', 'ctx_switches',
'files', 'max_files', 'max_threads', 'max_pid'])


def sysinfo():
"""Generic system info."""
procfs = get_procfs_path()
with open_binary('%s/sys/fs/file-nr' % procfs) as f:
data = f.read()
files, _, max_files = data.split()
files = int(files)
max_files = int(max_files)
with open_binary('%s/sys/kernel/threads-max' % procfs) as f:
max_threads = int(f.read())
with open_binary('%s/sys/kernel/pid_max' % procfs) as f:
max_pid = int(f.read())
with open_binary('%s/stat' % procfs) as f:
ctx_switches = None
procs_running = None
procs_blocked = None
for line in f:
if line.startswith(b'ctxt'):
ctx_switches = int(line.split()[1])
elif line.startswith(b'procs_running'):
procs_running = int(line.split()[1])
elif line.startswith(b'procs_blocked'):
procs_blocked = int(line.split()[1])
if ctx_switches is not None and procs_running is not None and \
procs_blocked is not None:
break
return ssysinfo(procs_running, procs_blocked, ctx_switches, files,
max_files, max_threads, max_pid)


# --- processes

def pids():
Expand Down
7 changes: 7 additions & 0 deletions psutil/_psutil_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,11 @@ psutil_net_if_stats(PyObject* self, PyObject* args) {
}


static PyObject*
psutil_sysctl_info(PyObject* self, PyObject* args) {
return Py_BuildValue("s", "ciao");
}

/*
* Define the psutil C module methods and initialize the module.
*/
Expand Down Expand Up @@ -577,6 +582,8 @@ PsutilMethods[] = {
"Return currently connected users as a list of tuples"},
{"net_if_stats", psutil_net_if_stats, METH_VARARGS,
"Return NIC stats (isup, duplex, speed, mtu)"},
{"sysctl_info", psutil_sysctl_info, METH_VARARGS,
"Return various system info."},

// --- linux specific

Expand Down
16 changes: 16 additions & 0 deletions test/_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ def ord(x):
return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1]


def sysctl(arg):
out = sh("sysctl %s" % arg)
res = out.split('=')[1]
try:
return int(res)
except ValueError:
return res


@unittest.skipUnless(LINUX, "not a Linux system")
class LinuxSpecificTestCase(unittest.TestCase):

Expand Down Expand Up @@ -511,6 +520,13 @@ def test_path_deleted(self):
self.assertEqual(psutil.Process().exe(), "/home/foo")
self.assertEqual(psutil.Process().cwd(), "/home/foo")

def test_sysinfo_max_pid(self):
self.assertEqual(psutil.sysinfo().max_pid, sysctl("kernel.pid_max"))

def test_sysinfo_max_threads(self):
self.assertEqual(psutil.sysinfo().max_threads,
sysctl("kernel.threads-max"))


def main():
test_suite = unittest.TestSuite()
Expand Down
17 changes: 17 additions & 0 deletions test/test_psutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,23 @@ def test_boot_time(self):
self.assertGreater(bt, 0)
self.assertLess(bt, time.time())

def test_sysinfo(self):
res = psutil.sysinfo()
if hasattr(res, 'procs_running'):
self.assertGreaterEqual(res.procs_running, 0)
if hasattr(res, 'procs_blocked'):
self.assertGreaterEqual(res.procs_blocked, 0)
if hasattr(res, 'ctx_switches'):
self.assertGreater(res.ctx_switches, 0)
if hasattr(res, 'files'):
self.assertGreater(res.files, 0)
if hasattr(res, 'max_files'):
self.assertGreater(res.max_files, 0)
if hasattr(res, 'max_threads'):
self.assertGreater(res.max_threads, 0)
if hasattr(res, 'max_pid'):
self.assertGreater(res.max_pid, 0)

@unittest.skipUnless(POSIX, 'posix only')
def test_PAGESIZE(self):
# pagesize is used internally to perform different calculations
Expand Down

0 comments on commit 866991a

Please sign in to comment.