/usr/share/pyshared/landscape/lib/process.py is in landscape-common 12.04.3-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | import logging
import os
from datetime import timedelta, datetime
from landscape.lib.timestamp import to_timestamp
from landscape.lib.jiffies import detect_jiffies
# FIXME: It'd be nice to avoid having library code which depends on
# landscape-specific modules.
from landscape.monitor.computeruptime import BootTimes, get_uptime
STATES = {"R (running)": "R",
"D (disk sleep)": "D",
"S (sleeping)": "S",
"T (stopped)": "T",
"T (tracing stop)": "I",
"X (dead)": "X",
"Z (zombie)": "Z"}
class ProcessInformation(object):
"""
@param proc_dir: The directory to use for process information.
@param jiffies: The value to use for jiffies per second.
@param boot_time: An alternate value to use for the last boot time. If
None, the system last boot time will be used.
@param uptime: The uptime value to use (for unit tests only).
"""
def __init__(self, proc_dir="/proc", jiffies=None, boot_time=None,
uptime=None):
if boot_time is None:
boot_time = BootTimes().get_last_boot_time()
if boot_time is not None:
boot_time = datetime.utcfromtimestamp(boot_time)
self._boot_time = boot_time
self._proc_dir = proc_dir
self._jiffies_per_sec = jiffies or detect_jiffies()
self._uptime = uptime
def get_all_process_info(self):
"""Get process information for all processes on the system."""
for filename in os.listdir(self._proc_dir):
try:
process_id = int(filename)
except ValueError:
continue
process_info = self.get_process_info(process_id)
if process_info:
yield process_info
def get_process_info(self, process_id):
"""
Parse the /proc/<pid>/cmdline and /proc/<pid>/status files for
information about the running process with process_id.
The /proc filesystem doesn't behave like ext2, open files can disappear
during the read process.
"""
cmd_line_name = ""
process_dir = os.path.join(self._proc_dir, str(process_id))
process_info = {"pid": process_id}
try:
file = open(os.path.join(process_dir, "cmdline"), "r")
try:
# cmdline is a \0 separated list of strings
# We take the first, and then strip off the path, leaving us with
# the basename.
cmd_line = file.readline()
cmd_line_name = os.path.basename(cmd_line.split("\0")[0])
finally:
file.close()
file = open(os.path.join(process_dir, "status"), "r")
try:
for line in file:
parts = line.split(":", 1)
if parts[0] == "Name":
process_info["name"] = (cmd_line_name.strip() or
parts[1].strip())
elif parts[0] == "State":
state = parts[1].strip()
process_info["state"] = STATES[state]
elif parts[0] == "Uid":
value_parts = parts[1].split()
process_info["uid"] = int(value_parts[0])
elif parts[0] == "Gid":
value_parts = parts[1].split()
process_info["gid"] = int(value_parts[0])
elif parts[0] == "VmSize":
value_parts = parts[1].split()
process_info["vm-size"] = int(value_parts[0])
break
finally:
file.close()
file = open(os.path.join(process_dir, "stat"), "r")
try:
# These variable names are lifted directly from proc(5)
# utime: The number of jiffies that this process has been scheduled in
# user mode.
# stime: The number of jiffies that this process has been scheduled in
# kernel mode.
# cutime: The number of jiffies that this process's waited-for children
# have been scheduled in user mode.
# cstime: The number of jiffies that this process's waited-for children
# have been scheduled in kernel mode.
parts = file.read().split()
start_time = int(parts[21])
utime = int(parts[13])
stime = int(parts[14])
uptime = self._uptime or get_uptime()
pcpu = calculate_pcpu(utime, stime, uptime,
start_time, self._jiffies_per_sec)
process_info["percent-cpu"] = pcpu
delta = timedelta(0, start_time // self._jiffies_per_sec)
if self._boot_time is None:
logging.warning("Skipping process (PID %s) without boot time.")
return None
process_info["start-time"] = to_timestamp(self._boot_time + delta)
finally:
file.close()
except IOError:
# Handle the race that happens when we find a process
# which terminates before we open the stat file.
return None
assert("pid" in process_info and "state" in process_info
and "name" in process_info and "uid" in process_info
and "gid" in process_info and "start-time" in process_info)
return process_info
def calculate_pcpu(utime, stime, uptime, start_time, hertz):
"""
Implement ps' algorithm to calculate the percentage cpu utilisation for a
process.::
unsigned long long total_time; /* jiffies used by this process */
unsigned pcpu = 0; /* scaled %cpu, 99 means 99% */
unsigned long long seconds; /* seconds of process life */
total_time = pp->utime + pp->stime;
if(include_dead_children) total_time += (pp->cutime + pp->cstime);
seconds = seconds_since_boot - pp->start_time / hertz;
if(seconds) pcpu = (total_time * 100ULL / hertz) / seconds;
if (pcpu > 99U) pcpu = 99U;
return snprintf(outbuf, COLWID, "%2u", pcpu);
"""
pcpu = 0
total_time = utime + stime
seconds = uptime - (start_time / hertz)
if seconds:
pcpu = total_time * 100 / hertz / seconds
return round(max(min(pcpu, 99.0), 0), 1)
|