def _get_cputimes_ntuple(): """ Return a (nt, rindex) tuple depending on the CPU times available on this Linux kernel version which may be: user, nice, system, idle, iowait, irq, softirq [steal, [guest, [guest_nice]]] """ f = open("/proc/stat", "r") try: values = f.readline().split()[1:] finally: f.close() fields = ["user", "nice", "system", "idle", "iowait", "irq", "softirq"] rindex = 8 vlen = len(values) if vlen >= 8: # Linux >= 2.6.11 fields.append("steal") rindex += 1 if vlen >= 9: # Linux >= 2.6.24 fields.append("guest") rindex += 1 if vlen >= 10: # Linux >= 3.2.0 fields.append("guest_nice") rindex += 1 return (namedtuple("cputimes", " ".join(fields)), rindex)
def _get_cputimes_ntuple(): """ Return a (nt, rindex) tuple depending on the CPU times available on this Linux kernel version which may be: user, nice, system, idle, iowait, irq, softirq [steal, [guest, [guest_nice]]] """ f = open('/proc/stat', 'r') try: values = f.readline().split()[1:] finally: f.close() fields = ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq'] rindex = 8 vlen = len(values) if vlen >= 8: # Linux >= 2.6.11 fields.append('steal') rindex += 1 if vlen >= 9: # Linux >= 2.6.24 fields.append('guest') rindex += 1 if vlen >= 10: # Linux >= 3.2.0 fields.append('guest_nice') rindex += 1 return (namedtuple('cputimes', ' '.join(fields)), rindex)
def calculate(t1, t2): global _ptime_cpu_perc_nt nums = [] all_delta = sum(t2) - sum(t1) for field in t1._fields: field_delta = getattr(t2, field) - getattr(t1, field) try: field_perc = (100 * field_delta) / all_delta except ZeroDivisionError: field_perc = 0.0 nums.append(round(field_perc, 1)) if _ptime_cpu_perc_nt is None: _ptime_cpu_perc_nt = namedtuple('cpupercent', ' '.join(t1._fields)) return _ptime_cpu_perc_nt(*nums)
class nt_connection(namedtuple('connection', 'fd family type laddr raddr status')): __slots__ = () @property def local_address(self): warnings.warn("'local_address' field is deprecated; use 'laddr'" \ "instead", category=DeprecationWarning, stacklevel=2) return self.laddr @property def remote_address(self): warnings.warn("'remote_address' field is deprecated; use 'raddr'" \ "instead", category=DeprecationWarning, stacklevel=2) return self.raddr
class pconn( namedtuple('pconn', ['fd', 'family', 'type', 'laddr', 'raddr', 'status'])): __slots__ = () @property def local_address(self): warnings.warn("'local_address' field is deprecated; use 'laddr'" "instead", category=DeprecationWarning, stacklevel=2) return self.laddr @property def remote_address(self): warnings.warn("'remote_address' field is deprecated; use 'raddr'" "instead", category=DeprecationWarning, stacklevel=2) return self.raddr
cext.MIB_TCP_STATE_SYN_SENT: _common.CONN_SYN_SENT, cext.MIB_TCP_STATE_SYN_RCVD: _common.CONN_SYN_RECV, cext.MIB_TCP_STATE_FIN_WAIT1: _common.CONN_FIN_WAIT1, cext.MIB_TCP_STATE_FIN_WAIT2: _common.CONN_FIN_WAIT2, cext.MIB_TCP_STATE_TIME_WAIT: _common.CONN_TIME_WAIT, cext.MIB_TCP_STATE_CLOSED: _common.CONN_CLOSE, cext.MIB_TCP_STATE_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, cext.MIB_TCP_STATE_LAST_ACK: _common.CONN_LAST_ACK, cext.MIB_TCP_STATE_LISTEN: _common.CONN_LISTEN, cext.MIB_TCP_STATE_CLOSING: _common.CONN_CLOSING, cext.MIB_TCP_STATE_DELETE_TCB: CONN_DELETE_TCB, cext.PSUTIL_CONN_NONE: _common.CONN_NONE, } scputimes = namedtuple('scputimes', ['user', 'system', 'idle']) svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) pextmem = namedtuple( 'pextmem', ['num_page_faults', 'peak_wset', 'wset', 'peak_paged_pool', 'paged_pool', 'peak_nonpaged_pool', 'nonpaged_pool', 'pagefile', 'peak_pagefile', 'private']) pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss']) pmmap_ext = namedtuple( 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) # set later from __init__.py NoSuchProcess = None AccessDenied = None TimeoutExpired = None
import _psutil_bsd import _psutil_posix from psutil import _psposix from psutil.error import AccessDenied, NoSuchProcess, TimeoutExpired from psutil._compat import namedtuple from psutil._common import * __extra__all__ = [] # --- constants NUM_CPUS = _psutil_bsd.get_num_cpus() BOOT_TIME = _psutil_bsd.get_system_boot_time() _TERMINAL_MAP = _psposix._get_terminal_map() _cputimes_ntuple = namedtuple('cputimes', 'user nice system idle irq') # --- public functions def phymem_usage(): """Physical system memory as a (total, used, free) tuple.""" total = _psutil_bsd.get_total_phymem() free = _psutil_bsd.get_avail_phymem() used = total - free # XXX check out whether we have to do the same math we do on Linux percent = usage_percent(used, total, _round=1) return nt_sysmeminfo(total, used, free, percent) def virtmem_usage(): """Virtual system memory as a (total, used, free) tuple.""" total = _psutil_bsd.get_total_virtmem()
"04" : "FIN_WAIT1", "05" : "FIN_WAIT2", "06" : "TIME_WAIT", "07" : "CLOSE", "08" : "CLOSE_WAIT", "09" : "LAST_ACK", "0A" : "LISTEN", "0B" : "CLOSING" } # --- system memory functions nt_virtmem_info = namedtuple('vmem', ' '.join([ # all platforms 'total', 'available', 'percent', 'used', 'free', # linux specific 'active', 'inactive', 'buffers', 'cached'])) def virtual_memory(): total, free, buffers, shared, _, _ = _psutil_linux.get_sysinfo() cached = active = inactive = None f = open('/proc/meminfo', 'r') try: for line in f: if line.startswith('Cached:'): cached = int(line.split()[1]) * 1024 elif line.startswith('Active:'): active = int(line.split()[1]) * 1024 elif line.startswith('Inactive:'):
cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, cext.TCPS_SYN_RCVD: _common.CONN_SYN_RECV, cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, cext.TCPS_CLOSED: _common.CONN_CLOSE, cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, cext.TCPS_LISTEN: _common.CONN_LISTEN, cext.TCPS_CLOSING: _common.CONN_CLOSING, cext.PSUTIL_CONN_NONE: _common.CONN_NONE, cext.TCPS_IDLE: CONN_IDLE, # sunos specific cext.TCPS_BOUND: CONN_BOUND, # sunos specific } scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait']) svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) pextmem = namedtuple('pextmem', ['rss', 'vms']) pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss', 'anon', 'locked']) pmmap_ext = namedtuple( 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) # set later from __init__.py NoSuchProcess = None AccessDenied = None TimeoutExpired = None # --- functions disk_io_counters = cext.disk_io_counters net_io_counters = cext.net_io_counters
STATUS_RUNNING = constant(0, "running") STATUS_SLEEPING = constant(1, "sleeping") STATUS_DISK_SLEEP = constant(2, "disk sleep") STATUS_STOPPED = constant(3, "stopped") STATUS_TRACING_STOP = constant(4, "tracing stop") STATUS_ZOMBIE = constant(5, "zombie") STATUS_DEAD = constant(6, "dead") STATUS_WAKE_KILL = constant(7, "wake kill") STATUS_WAKING = constant(8, "waking") STATUS_IDLE = constant(9, "idle") # BSD STATUS_LOCKED = constant(10, "locked") # BSD STATUS_WAITING = constant(11, "waiting") # BSD # system ntuple_sys_cputimes = namedtuple('cputimes', 'user nice system idle iowait irq softirq') ntuple_sysmeminfo = namedtuple('usage', 'total used free percent') ntuple_diskinfo = namedtuple('usage', 'total used free percent') ntuple_partition = namedtuple('partition', 'device mountpoint fstype') ntuple_net_iostat = namedtuple('iostat', 'bytes_sent bytes_recv packets_sent packets_recv') ntuple_disk_iostat = namedtuple('iostat', 'read_count write_count read_bytes write_bytes read_time write_time') # processes ntuple_meminfo = namedtuple('meminfo', 'rss vms') ntuple_cputimes = namedtuple('cputimes', 'user system') ntuple_openfile = namedtuple('openfile', 'path fd') ntuple_connection = namedtuple('connection', 'fd family type local_address remote_address status') ntuple_thread = namedtuple('thread', 'id user_time system_time') ntuple_uids = namedtuple('user', 'real effective saved') ntuple_gids = namedtuple('group', 'real effective saved') ntuple_io = namedtuple('io', 'read_count write_count read_bytes write_bytes')
from psutil._compat import namedtuple, PY3 from psutil._common import * __extra__all__ = ["CONN_IDLE", "CONN_BOUND"] PAGE_SIZE = os.sysconf("SC_PAGE_SIZE") NUM_CPUS = os.sysconf("SC_NPROCESSORS_ONLN") BOOT_TIME = _psutil_sunos.get_process_basic_info(0)[3] TOTAL_PHYMEM = os.sysconf("SC_PHYS_PAGES") * PAGE_SIZE CONN_IDLE = "IDLE" CONN_BOUND = "BOUND" _PAGESIZE = os.sysconf("SC_PAGE_SIZE") _cputimes_ntuple = namedtuple("cputimes", "user system idle iowait") disk_io_counters = _psutil_sunos.get_disk_io_counters net_io_counters = _psutil_sunos.get_net_io_counters get_disk_usage = _psposix.get_disk_usage get_system_boot_time = lambda: _psutil_sunos.get_process_basic_info(0)[3] nt_virtmem_info = namedtuple( "vmem", " ".join( [ # all platforms "total", "available", "percent", "used",
_psutil_osx.SSTOP: STATUS_STOPPED, _psutil_osx.SZOMB: STATUS_ZOMBIE, } # --- functions get_system_boot_time = _psutil_osx.get_system_boot_time # ...so that we can test it from test_memory_leask.py get_num_cpus = _psutil_osx.get_num_cpus() nt_virtmem_info = namedtuple('vmem', ' '.join([ # all platforms 'total', 'available', 'percent', 'used', 'free', # OSX specific 'active', 'inactive', 'wired'])) def virtual_memory(): """System virtual memory as a namedtuple.""" total, active, inactive, wired, free = _psutil_osx.get_virtual_mem() avail = inactive + free used = active + inactive + wired percent = usage_percent((total - avail), total, _round=1) return nt_virtmem_info(total, avail, percent, used, free, active, inactive, wired) def swap_memory():
conn_tmap.update({ "tcp6": ([AF_INET6], [SOCK_STREAM]), "udp6": ([AF_INET6], [SOCK_DGRAM]), }) if AF_UNIX is not None: conn_tmap.update({ "unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]), }) del AF_INET, AF_INET6, AF_UNIX, SOCK_STREAM, SOCK_DGRAM, socket # --- namedtuples for psutil.* system-related functions # psutil.swap_memory() sswap = namedtuple('sswap', ['total', 'used', 'free', 'percent', 'sin', 'sout']) # psutil.disk_usage() sdiskusage = namedtuple('sdiskusage', ['total', 'used', 'free', 'percent']) # psutil.disk_io_counters() sdiskio = namedtuple('sdiskio', [ 'read_count', 'write_count', 'read_bytes', 'write_bytes', 'read_time', 'write_time' ]) # psutil.disk_partitions() sdiskpart = namedtuple('sdiskpart', ['device', 'mountpoint', 'fstype', 'opts']) # psutil.net_io_counters() snetio = namedtuple('snetio', [ 'bytes_sent', 'bytes_recv', 'packets_sent', 'packets_recv', 'errin', 'errout', 'dropin', 'dropout' ]) # psutil.users()
cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, cext.TCPS_LISTEN: _common.CONN_LISTEN, cext.TCPS_CLOSING: _common.CONN_CLOSING, cext.PSUTIL_CONN_NONE: _common.CONN_NONE, } PROC_STATUSES = { cext.SIDL: _common.STATUS_IDLE, cext.SRUN: _common.STATUS_RUNNING, cext.SSLEEP: _common.STATUS_SLEEPING, cext.SSTOP: _common.STATUS_STOPPED, cext.SZOMB: _common.STATUS_ZOMBIE, } scputimes = namedtuple('scputimes', ['user', 'nice', 'system', 'idle']) svmem = namedtuple( 'svmem', ['total', 'available', 'percent', 'used', 'free', 'active', 'inactive', 'wired']) pextmem = namedtuple('pextmem', ['rss', 'vms', 'pfaults', 'pageins']) pmmap_grouped = namedtuple( 'pmmap_grouped', 'path rss private swapped dirtied ref_count shadow_depth') pmmap_ext = namedtuple( 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) # set later from __init__.py
f.close() fields = ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq'] vlen = len(values) if vlen >= 8: # Linux >= 2.6.11 fields.append('steal') if vlen >= 9: # Linux >= 2.6.24 fields.append('guest') if vlen >= 10: # Linux >= 3.2.0 fields.append('guest_nice') return fields scputimes = namedtuple('scputimes', _get_cputimes_fields()) svmem = namedtuple('svmem', [ 'total', 'available', 'percent', 'used', 'free', 'active', 'inactive', 'buffers', 'cached' ]) pextmem = namedtuple('pextmem', 'rss vms shared text lib data dirty') pmmap_grouped = namedtuple('pmmap_grouped', [ 'path', 'rss', 'size', 'pss', 'shared_clean', 'shared_dirty', 'private_clean', 'private_dirty', 'referenced', 'anonymous', 'swap' ]) pmmap_ext = namedtuple('pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, cext.TCPS_CLOSED: _common.CONN_CLOSE, cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, cext.TCPS_LISTEN: _common.CONN_LISTEN, cext.TCPS_CLOSING: _common.CONN_CLOSING, cext.PSUTIL_CONN_NONE: _common.CONN_NONE, } PAGESIZE = os.sysconf("SC_PAGE_SIZE") # extend base mem ntuple with BSD-specific memory metrics svmem = namedtuple( 'svmem', ['total', 'available', 'percent', 'used', 'free', 'active', 'inactive', 'buffers', 'cached', 'shared', 'wired']) scputimes = namedtuple( 'scputimes', ['user', 'nice', 'system', 'idle', 'irq']) pextmem = namedtuple('pextmem', ['rss', 'vms', 'text', 'data', 'stack']) pmmap_grouped = namedtuple( 'pmmap_grouped', 'path rss, private, ref_count, shadow_count') pmmap_ext = namedtuple( 'pmmap_ext', 'addr, perms path rss, private, ref_count, shadow_count') # set later from __init__.py NoSuchProcess = None AccessDenied = None TimeoutExpired = None
STATUS_RUNNING = constant(0, "running") STATUS_SLEEPING = constant(1, "sleeping") STATUS_DISK_SLEEP = constant(2, "disk sleep") STATUS_STOPPED = constant(3, "stopped") STATUS_TRACING_STOP = constant(4, "tracing stop") STATUS_ZOMBIE = constant(5, "zombie") STATUS_DEAD = constant(6, "dead") STATUS_WAKE_KILL = constant(7, "wake kill") STATUS_WAKING = constant(8, "waking") STATUS_IDLE = constant(9, "idle") # BSD STATUS_LOCKED = constant(10, "locked") # BSD STATUS_WAITING = constant(11, "waiting") # BSD # system ntuple_sys_cputimes = namedtuple('cputimes', 'user nice system idle iowait irq softirq') # processes ntuple_meminfo = namedtuple('meminfo', 'rss vms') ntuple_cputimes = namedtuple('cputimes', 'user system') ntuple_openfile = namedtuple('openfile', 'path fd') ntuple_connection = namedtuple( 'connection', 'fd family type local_address remote_address status') ntuple_thread = namedtuple('thread', 'id user_time system_time') ntuple_uids = namedtuple('user', 'real effective saved') ntuple_gids = namedtuple('group', 'real effective saved') ntuple_io = namedtuple('io', 'read_count write_count read_bytes write_bytes') ntuple_ionice = namedtuple('ionice', 'ioclass value') # the __all__ namespace common to all _ps*.py platform modules base_module_namespace = [
class Process(object): """Wrapper class around underlying C implementation.""" __slots__ = ["pid", "_process_name"] def __init__(self, pid): self.pid = pid self._process_name = None @wrap_exceptions def get_process_name(self): # note: max len == 15 return _psutil_sunos.get_process_name_and_args(self.pid)[0] @wrap_exceptions def get_process_exe(self): # Will be guess later from cmdline but we want to explicitly # invoke cmdline here in order to get an AccessDenied # exception if the user has not enough privileges. self.get_process_cmdline() return "" @wrap_exceptions def get_process_cmdline(self): return _psutil_sunos.get_process_name_and_args(self.pid)[1].split(' ') @wrap_exceptions def get_process_create_time(self): return _psutil_sunos.get_process_basic_info(self.pid)[3] @wrap_exceptions def get_process_num_threads(self): return _psutil_sunos.get_process_basic_info(self.pid)[5] @wrap_exceptions def get_process_nice(self): # For some reason getpriority(3) return ESRCH (no such process) # for certain low-pid processes, no matter what (even as root). # The process actually exists though, as it has a name, # creation time, etc. # The best thing we can do here appears to be raising AD. # Note: tested on Solaris 11; on Open Solaris 5 everything is # fine. try: return _psutil_posix.getpriority(self.pid) except EnvironmentError: err = sys.exc_info()[1] if err.errno in (errno.ENOENT, errno.ESRCH): if pid_exists(self.pid): raise AccessDenied(self.pid, self._process_name) raise @wrap_exceptions def set_process_nice(self, value): if self.pid in (2, 3): # Special case PIDs: internally setpriority(3) return ESRCH # (no such process), no matter what. # The process actually exists though, as it has a name, # creation time, etc. raise AccessDenied(self.pid, self._process_name) return _psutil_posix.setpriority(self.pid, value) @wrap_exceptions def get_process_ppid(self): return _psutil_sunos.get_process_basic_info(self.pid)[0] @wrap_exceptions def get_process_uids(self): real, effective, saved, _, _, _ = \ _psutil_sunos.get_process_cred(self.pid) return nt_uids(real, effective, saved) @wrap_exceptions def get_process_gids(self): _, _, _, real, effective, saved = \ _psutil_sunos.get_process_cred(self.pid) return nt_uids(real, effective, saved) @wrap_exceptions def get_cpu_times(self): user, system = _psutil_sunos.get_process_cpu_times(self.pid) return nt_cputimes(user, system) @wrap_exceptions def get_process_terminal(self): hit_enoent = False tty = wrap_exceptions(_psutil_sunos.get_process_basic_info(self.pid)[0]) if tty != _psutil_sunos.PRNODEV: for x in (0, 1, 2, 255): try: return os.readlink('/proc/%d/path/%d' % (self.pid, x)) except OSError: err = sys.exc_info()[1] if err.errno == errno.ENOENT: hit_enoent = True continue raise if hit_enoent: # raise NSP if the process disappeared on us os.stat('/proc/%s' % self.pid) @wrap_exceptions def get_process_cwd(self): # /proc/PID/path/cwd may not be resolved by readlink() even if # it exists (ls shows it). If that's the case and the process # is still alive return None (we can return None also on BSD). # Reference: http://goo.gl/55XgO try: return os.readlink("/proc/%s/path/cwd" % self.pid) except OSError: err = sys.exc_info()[1] if err.errno == errno.ENOENT: os.stat("/proc/%s" % self.pid) return None raise @wrap_exceptions def get_memory_info(self): ret = _psutil_sunos.get_process_basic_info(self.pid) rss, vms = ret[1] * 1024, ret[2] * 1024 return nt_meminfo(rss, vms) # it seems Solaris uses rss and vms only get_ext_memory_info = get_memory_info @wrap_exceptions def get_process_status(self): code = _psutil_sunos.get_process_basic_info(self.pid)[6] # XXX is '?' legit? (we're not supposed to return it anyway) return PROC_STATUSES.get(code, '?') @wrap_exceptions def get_process_threads(self): ret = [] tids = os.listdir('/proc/%d/lwp' % self.pid) hit_enoent = False for tid in tids: tid = int(tid) try: utime, stime = _psutil_sunos.query_process_thread(self.pid, tid) except EnvironmentError: # ENOENT == thread gone in meantime err = sys.exc_info()[1] if err.errno == errno.ENOENT: hit_enoent = True continue raise else: nt = nt_thread(tid, utime, stime) ret.append(nt) if hit_enoent: # raise NSP if the process disappeared on us os.stat('/proc/%s' % self.pid) return ret @wrap_exceptions def get_open_files(self): retlist = [] hit_enoent = False pathdir = '/proc/%d/path' % self.pid for fd in os.listdir('/proc/%d/fd' % self.pid): path = os.path.join(pathdir, fd) if os.path.islink(path): try: file = os.readlink(path) except OSError: # ENOENT == file which is gone in the meantime err = sys.exc_info()[1] if err.errno == errno.ENOENT: hit_enoent = True continue raise else: if isfile_strict(file): retlist.append(nt_openfile(file, int(fd))) if hit_enoent: # raise NSP if the process disappeared on us os.stat('/proc/%s' % self.pid) return retlist def _get_unix_sockets(self, pid): """Get UNIX sockets used by process by parsing 'pfiles' output.""" # TODO: rewrite this in C (...but the damn netstat source code # does not include this part! Argh!!) cmd = "pfiles %s" % pid p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate() if PY3: stdout, stderr = [x.decode(sys.stdout.encoding) for x in (stdout, stderr)] if p.returncode != 0: if 'permission denied' in stderr.lower(): raise AccessDenied(self.pid, self._process_name) if 'no such process' in stderr.lower(): raise NoSuchProcess(self.pid, self._process_name) raise RuntimeError("%r command error\n%s" % (cmd, stderr)) lines = stdout.split('\n')[2:] for i, line in enumerate(lines): line = line.lstrip() if line.startswith('sockname: AF_UNIX'): path = line.split(' ', 2)[2] type = lines[i - 2].strip() if type == 'SOCK_STREAM': type = socket.SOCK_STREAM elif type == 'SOCK_DGRAM': type = socket.SOCK_DGRAM else: type = -1 yield (-1, socket.AF_UNIX, type, path, "", CONN_NONE) @wrap_exceptions def get_connections(self, kind='inet'): if kind not in conn_tmap: raise ValueError("invalid %r kind argument; choose between %s" % (kind, ', '.join([repr(x) for x in conn_tmap]))) families, types = conn_tmap[kind] rawlist = _psutil_sunos.get_process_connections( self.pid, families, types) # The underlying C implementation retrieves all OS connections # and filters them by PID. At this point we can't tell whether # an empty list means there were no connections for process or # process is no longer active so we force NSP in case the PID # is no longer there. if not rawlist: os.stat('/proc/%s' % self.pid) # will raise NSP if process is gone ret = [] for item in rawlist: fd, fam, type, laddr, raddr, status = item if fam not in families: continue if type not in types: continue status = TCP_STATUSES[status] nt = nt_connection(fd, fam, type, laddr, raddr, status) ret.append(nt) # UNIX sockets if socket.AF_UNIX in families: ret.extend([nt_connection(*conn) for conn in self._get_unix_sockets(self.pid)]) return ret nt_mmap_grouped = namedtuple('mmap', 'path rss anon locked') nt_mmap_ext = namedtuple('mmap', 'addr perms path rss anon locked') @wrap_exceptions def get_memory_maps(self): def toaddr(start, end): return '%s-%s' % (hex(start)[2:].strip('L'), hex(end)[2:].strip('L')) retlist = [] rawlist = _psutil_sunos.get_process_memory_maps(self.pid) hit_enoent = False for item in rawlist: addr, addrsize, perm, name, rss, anon, locked = item addr = toaddr(addr, addrsize) if not name.startswith('['): try: name = os.readlink('/proc/%s/path/%s' % (self.pid, name)) except OSError: err = sys.exc_info()[1] if err.errno == errno.ENOENT: # sometimes the link may not be resolved by # readlink() even if it exists (ls shows it). # If that's the case we just return the # unresolved link path. # This seems an incosistency with /proc similar # to: http://goo.gl/55XgO name = '/proc/%s/path/%s' % (self.pid, name) hit_enoent = True else: raise retlist.append((addr, perm, name, rss, anon, locked)) if hit_enoent: # raise NSP if the process disappeared on us os.stat('/proc/%s' % self.pid) return retlist @wrap_exceptions def get_num_fds(self): return len(os.listdir("/proc/%s/fd" % self.pid)) @wrap_exceptions def get_num_ctx_switches(self): return nt_ctxsw(*_psutil_sunos.get_process_num_ctx_switches(self.pid)) @wrap_exceptions def process_wait(self, timeout=None): try: return _psposix.wait_pid(self.pid, timeout) except TimeoutExpired: raise TimeoutExpired(self.pid, self._process_name)
class Process(object): """Wrapper class around underlying C implementation.""" __slots__ = ["pid", "_process_name"] def __init__(self, pid): self.pid = pid self._process_name = None @wrap_exceptions def get_process_name(self): """Return process name as a string of limited len (15).""" return _psutil_osx.get_process_name(self.pid) @wrap_exceptions def get_process_exe(self): return _psutil_osx.get_process_exe(self.pid) @wrap_exceptions def get_process_cmdline(self): """Return process cmdline as a list of arguments.""" if not pid_exists(self.pid): raise NoSuchProcess(self.pid, self._process_name) return _psutil_osx.get_process_cmdline(self.pid) @wrap_exceptions def get_process_ppid(self): """Return process parent pid.""" return _psutil_osx.get_process_ppid(self.pid) @wrap_exceptions def get_process_cwd(self): return _psutil_osx.get_process_cwd(self.pid) @wrap_exceptions def get_process_uids(self): real, effective, saved = _psutil_osx.get_process_uids(self.pid) return nt_uids(real, effective, saved) @wrap_exceptions def get_process_gids(self): real, effective, saved = _psutil_osx.get_process_gids(self.pid) return nt_gids(real, effective, saved) @wrap_exceptions def get_process_terminal(self): tty_nr = _psutil_osx.get_process_tty_nr(self.pid) try: return _TERMINAL_MAP[tty_nr] except KeyError: return None @wrap_exceptions def get_memory_info(self): """Return a tuple with the process' RSS and VMS size.""" rss, vms = _psutil_osx.get_memory_info(self.pid) return nt_meminfo(rss, vms) @wrap_exceptions def get_cpu_times(self): user, system = _psutil_osx.get_cpu_times(self.pid) return nt_cputimes(user, system) @wrap_exceptions def get_process_create_time(self): """Return the start time of the process as a number of seconds since the epoch.""" return _psutil_osx.get_process_create_time(self.pid) @wrap_exceptions def get_process_num_threads(self): """Return the number of threads belonging to the process.""" return _psutil_osx.get_process_num_threads(self.pid) @wrap_exceptions def get_open_files(self): """Return files opened by process.""" if self.pid == 0: return [] files = [] rawlist = _psutil_osx.get_process_open_files(self.pid) for path, fd in rawlist: if os.path.isfile(path): ntuple = nt_openfile(path, fd) files.append(ntuple) return files @wrap_exceptions def get_connections(self, kind='inet'): """Return etwork connections opened by a process as a list of namedtuples. """ if kind not in conn_tmap: raise ValueError("invalid %r kind argument; choose between %s" % (kind, ', '.join([repr(x) for x in conn_tmap]))) families, types = conn_tmap[kind] ret = _psutil_osx.get_process_connections(self.pid, families, types) return [nt_connection(*conn) for conn in ret] @wrap_exceptions def get_num_fds(self): if self.pid == 0: return 0 return _psutil_osx.get_process_num_fds(self.pid) @wrap_exceptions def process_wait(self, timeout=None): try: return _psposix.wait_pid(self.pid, timeout) except TimeoutExpired: raise TimeoutExpired(self.pid, self._process_name) @wrap_exceptions def get_process_nice(self): return _psutil_posix.getpriority(self.pid) @wrap_exceptions def set_process_nice(self, value): return _psutil_posix.setpriority(self.pid, value) @wrap_exceptions def get_process_status(self): code = _psutil_osx.get_process_status(self.pid) if code in _status_map: return _status_map[code] return constant(-1, "?") @wrap_exceptions def get_process_threads(self): """Return the number of threads belonging to the process.""" rawlist = _psutil_osx.get_process_threads(self.pid) retlist = [] for thread_id, utime, stime in rawlist: ntuple = nt_thread(thread_id, utime, stime) retlist.append(ntuple) return retlist nt_mmap_grouped = namedtuple('mmap', 'path rss private swapped dirtied ref_count shadow_depth') nt_mmap_ext = namedtuple('mmap', 'addr perms path rss private swapped dirtied ref_count shadow_depth') @wrap_exceptions def get_memory_maps(self): return _psutil_osx.get_process_memory_maps(self.pid)
import _psutil_osx import _psutil_posix from psutil import _psposix from psutil.error import AccessDenied, NoSuchProcess, TimeoutExpired from psutil._compat import namedtuple from psutil._common import * __extra__all__ = [] # --- constants NUM_CPUS = _psutil_osx.get_num_cpus() BOOT_TIME = _psutil_osx.get_system_boot_time() TOTAL_PHYMEM = _psutil_osx.get_virtual_mem()[0] _PAGESIZE = os.sysconf("SC_PAGE_SIZE") _cputimes_ntuple = namedtuple('cputimes', 'user nice system idle') # --- functions nt_virtmem_info = namedtuple('vmem', ' '.join([ # all platforms 'total', 'available', 'percent', 'used', 'free', # OSX specific 'active', 'inactive', 'wired'])) def virtual_memory(): """System virtual memory as a namedtuple.""" total, active, inactive, wired, free = _psutil_osx.get_virtual_mem() avail = inactive + free
cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, cext.TCPS_CLOSED: _common.CONN_CLOSE, cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, cext.TCPS_LISTEN: _common.CONN_LISTEN, cext.TCPS_CLOSING: _common.CONN_CLOSING, cext.PSUTIL_CONN_NONE: _common.CONN_NONE, } PAGESIZE = os.sysconf("SC_PAGE_SIZE") # extend base mem ntuple with BSD-specific memory metrics svmem = namedtuple('svmem', [ 'total', 'available', 'percent', 'used', 'free', 'active', 'inactive', 'buffers', 'cached', 'shared', 'wired' ]) scputimes = namedtuple('scputimes', ['user', 'nice', 'system', 'idle', 'irq']) pextmem = namedtuple('pextmem', ['rss', 'vms', 'text', 'data', 'stack']) pmmap_grouped = namedtuple('pmmap_grouped', 'path rss, private, ref_count, shadow_count') pmmap_ext = namedtuple( 'pmmap_ext', 'addr, perms path rss, private, ref_count, shadow_count') # set later from __init__.py NoSuchProcess = None AccessDenied = None TimeoutExpired = None def virtual_memory():
"09": "LAST_ACK", "0A": "LISTEN", "0B": "CLOSING", } # --- system memory functions nt_virtmem_info = namedtuple( "vmem", " ".join( [ # all platforms "total", "available", "percent", "used", "free", # linux specific "active", "inactive", "buffers", "cached", ] ), ) def virtual_memory(): total, free, buffers, shared, _, _ = _psutil_linux.get_sysinfo() cached = active = inactive = None f = open("/proc/meminfo", "r") try:
class Process(object): """Wrapper class around underlying C implementation.""" __slots__ = ["pid", "_name"] def __init__(self, pid): self.pid = pid self._name = None @wrap_exceptions def name(self): return cext.proc_name(self.pid) @wrap_exceptions def exe(self): return cext.proc_exe(self.pid) @wrap_exceptions def cmdline(self): return cext.proc_cmdline(self.pid) @wrap_exceptions def terminal(self): tty_nr = cext.proc_tty_nr(self.pid) tmap = _psposix._get_terminal_map() try: return tmap[tty_nr] except KeyError: return None @wrap_exceptions def ppid(self): return cext.proc_ppid(self.pid) @wrap_exceptions def uids(self): real, effective, saved = cext.proc_uids(self.pid) return _common.puids(real, effective, saved) @wrap_exceptions def gids(self): real, effective, saved = cext.proc_gids(self.pid) return _common.pgids(real, effective, saved) @wrap_exceptions def cpu_times(self): user, system = cext.proc_cpu_times(self.pid) return _common.pcputimes(user, system) @wrap_exceptions def memory_info(self): rss, vms = cext.proc_memory_info(self.pid)[:2] return _common.pmem(rss, vms) @wrap_exceptions def memory_info_ex(self): return pextmem(*cext.proc_memory_info(self.pid)) @wrap_exceptions def create_time(self): return cext.proc_create_time(self.pid) @wrap_exceptions def num_threads(self): return cext.proc_num_threads(self.pid) @wrap_exceptions def num_ctx_switches(self): return _common.pctxsw(*cext.proc_num_ctx_switches(self.pid)) @wrap_exceptions def threads(self): rawlist = cext.proc_threads(self.pid) retlist = [] for thread_id, utime, stime in rawlist: ntuple = _common.pthread(thread_id, utime, stime) retlist.append(ntuple) return retlist @wrap_exceptions def connections(self, kind='inet'): if kind not in conn_tmap: raise ValueError("invalid %r kind argument; choose between %s" % (kind, ', '.join([repr(x) for x in conn_tmap]))) families, types = conn_tmap[kind] rawlist = cext.proc_connections(self.pid, families, types) ret = [] for item in rawlist: fd, fam, type, laddr, raddr, status = item status = TCP_STATUSES[status] nt = _common.pconn(fd, fam, type, laddr, raddr, status) ret.append(nt) return ret @wrap_exceptions def wait(self, timeout=None): try: return _psposix.wait_pid(self.pid, timeout) except _psposix.TimeoutExpired: # support for private module import if TimeoutExpired is None: raise raise TimeoutExpired(timeout, self.pid, self._name) @wrap_exceptions def nice_get(self): return _psutil_posix.getpriority(self.pid) @wrap_exceptions def nice_set(self, value): return _psutil_posix.setpriority(self.pid, value) @wrap_exceptions def status(self): code = cext.proc_status(self.pid) if code in PROC_STATUSES: return PROC_STATUSES[code] # XXX is this legit? will we even ever get here? return "?" @wrap_exceptions def io_counters(self): rc, wc, rb, wb = cext.proc_io_counters(self.pid) return _common.pio(rc, wc, rb, wb) nt_mmap_grouped = namedtuple('mmap', 'path rss, private, ref_count, shadow_count') nt_mmap_ext = namedtuple( 'mmap', 'addr, perms path rss, private, ref_count, shadow_count') # FreeBSD < 8 does not support functions based on kinfo_getfile() # and kinfo_getvmmap() if hasattr(cext, 'proc_open_files'): @wrap_exceptions def open_files(self): """Return files opened by process as a list of namedtuples.""" rawlist = cext.proc_open_files(self.pid) return [_common.popenfile(path, fd) for path, fd in rawlist] @wrap_exceptions def cwd(self): """Return process current working directory.""" # sometimes we get an empty string, in which case we turn # it into None return cext.proc_cwd(self.pid) or None @wrap_exceptions def memory_maps(self): return cext.proc_memory_maps(self.pid) @wrap_exceptions def num_fds(self): """Return the number of file descriptors opened by this process.""" return cext.proc_num_fds(self.pid) else: def _not_implemented(self): raise NotImplementedError("supported only starting from FreeBSD 8") open_files = _not_implemented proc_cwd = _not_implemented memory_maps = _not_implemented num_fds = _not_implemented
cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, cext.TCPS_LISTEN: _common.CONN_LISTEN, cext.TCPS_CLOSING: _common.CONN_CLOSING, cext.PSUTIL_CONN_NONE: _common.CONN_NONE, } PROC_STATUSES = { cext.SIDL: _common.STATUS_IDLE, cext.SRUN: _common.STATUS_RUNNING, cext.SSLEEP: _common.STATUS_SLEEPING, cext.SSTOP: _common.STATUS_STOPPED, cext.SZOMB: _common.STATUS_ZOMBIE, } scputimes = namedtuple('scputimes', ['user', 'nice', 'system', 'idle']) svmem = namedtuple('svmem', [ 'total', 'available', 'percent', 'used', 'free', 'active', 'inactive', 'wired' ]) pextmem = namedtuple('pextmem', ['rss', 'vms', 'pfaults', 'pageins']) pmmap_grouped = namedtuple( 'pmmap_grouped', 'path rss private swapped dirtied ref_count shadow_depth') pmmap_ext = namedtuple('pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) # set later from __init__.py
mountpoint = letter type = _psutil_mswindows.win32_GetDriveType(letter) if not os.path.exists(mountpoint): # usually a CD-ROM device with no disk inserted mountpoint = "" if not all: if type not in ('cdrom', 'fixed', 'removable'): continue if not mountpoint: continue ntuple = ntuple_partition(letter, mountpoint, type) retlist.append(ntuple) return retlist _cputimes_ntuple = namedtuple('cputimes', 'user system idle') def get_system_cpu_times(): """Return system CPU times as a named tuple.""" user, system, idle = 0, 0, 0 # computes system global times summing each processor value for cpu_time in _psutil_mswindows.get_system_cpu_times(): user += cpu_time[0] system += cpu_time[1] idle += cpu_time[2] return _cputimes_ntuple(user, system, idle) def get_system_per_cpu_times(): """Return system per-CPU times as a list of named tuples.""" ret = [] for cpu_t in _psutil_mswindows.get_system_cpu_times():
_psutil_bsd.PSUTIL_CONN_NONE: CONN_NONE, } PAGESIZE = os.sysconf("SC_PAGE_SIZE") nt_virtmem_info = namedtuple( "vmem", " ".join( [ # all platforms "total", "available", "percent", "used", "free", # FreeBSD specific "active", "inactive", "buffers", "cached", "shared", "wired", ] ), ) def virtual_memory(): """System virtual memory as a namedutple.""" mem = _psutil_bsd.get_virtual_mem() total, free, active, inactive, wired, cached, buffers, shared = mem
class LsofParser: """A wrapper for lsof command line utility. Executes lsof in subprocess and parses its output. """ socket_table = { 'TCP': socket.SOCK_STREAM, 'UDP': socket.SOCK_DGRAM, 'IPv4': socket.AF_INET, 'IPv6': socket.AF_INET6 } _openfile_ntuple = namedtuple('openfile', 'path fd') _connection_ntuple = namedtuple( 'connection', 'fd family type local_address ' 'remote_address status') def __init__(self, pid, name): self.pid = pid self.process_name = name # XXX - this is no longer used def get_process_open_files(self): """Return files opened by process by parsing lsof output.""" # Options: # -i == network files only # -a == ANDing of all options # -p == process with given PID only # -n == do not resolve IP addresses # -P == do not resolve port numbers # -w == suppresses warnings # -F0nPt == (0) separate lines with "\x00" # (n) file name # (t) file type # (f) file descriptr cmd = "lsof -a -p %s -n -P -F0ftn" % self.pid stdout = self.runcmd(cmd) if not stdout: return [] files = [] lines = stdout.split("\n") del lines[0] # first line contains the PID for line in lines: if not line: continue line = line.strip("\x00") fields = {} for field in line.split("\x00"): key, value = field[0], field[1:] fields[key] = value if not 't' in fields: continue _type = fields['t'] fd = fields['f'] name = fields['n'] if 'REG' in _type and fd.isdigit(): if not os.path.isfile(os.path.realpath(name)): continue ntuple = self._openfile_ntuple(name, int(fd)) files.append(ntuple) return files def get_process_connections(self): """Return connections opened by a process by parsing lsof output.""" # Options: # -i == network files only # -a == ANDing of all options # -p == process with given PID only # -n == do not resolve IP addresses # -P == do not resolve port numbers # -w == suppresses warnings # -F0nPt == (0) separate lines with "\x00" # (n) and show internet addresses only # (P) protocol type (TCP, UPD, Unix) # (t) socket family (IPv4, IPv6) # (T) connection status # (f) file descriptors cmd = "lsof -p %s -i -a -F0nPtTf -n -P" % self.pid stdout = self.runcmd(cmd) if not stdout: return [] connections = [] lines = stdout.split() del lines[0] # first line contains the PID for line in lines: line = line.strip("\x00") fields = {} for field in line.split("\x00"): if field.startswith('T'): key, value = field.split('=') else: key, value = field[0], field[1:] fields[key] = value # XXX - might trow execption; needs "continue on unsupported # family or type" (e.g. unix sockets) # we consider TCP and UDP sockets only stype = fields['P'] if stype not in self.socket_table: continue else: _type = self.socket_table[fields['P']] family = self.socket_table[fields['t']] peers = fields['n'] fd = int(fields['f']) if _type == socket.SOCK_STREAM: status = fields['TST'] # OS X shows "CLOSED" instead of "CLOSE" so translate them if status == "CLOSED": status = "CLOSE" else: status = "" if not '->' in peers: local_addr = self._normaddress(peers, family) remote_addr = () # OS X processes e.g. SystemUIServer can return *:* for local # address, so we return 0 and move on if local_addr == 0: continue else: local_addr, remote_addr = peers.split("->") local_addr = self._normaddress(local_addr, family) remote_addr = self._normaddress(remote_addr, family) conn = self._connection_ntuple(fd, family, _type, local_addr, remote_addr, status) connections.append(conn) return connections def runcmd(self, cmd): """Expects an lsof-related command line, execute it in a subprocess and return its output. If something goes bad stderr is parsed and proper exceptions raised as necessary. """ p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate() if PY3: stdout, stderr = [ x.decode(sys.stdout.encoding) for x in (stdout, stderr) ] if stderr: utility = cmd.split(' ')[0] if self._which(utility) is None: msg = "this functionnality requires %s command line utility " \ "to be installed on the system" % utility raise NotImplementedError(msg) elif "permission denied" in stderr.lower(): # "permission denied" can be found also in case of zombie # processes; p = psutil.Process(self.pid) if not p.is_running(): raise NoSuchProcess(self.pid, self.process_name) raise AccessDenied(self.pid, self.process_name) elif "lsof: warning:" in stderr.lower(): # usually appears when lsof is run for the first time and # complains about missing cache file in user home warnings.warn(stderr, RuntimeWarning) else: # this must be considered an application bug raise RuntimeError(stderr) if not stdout: p = psutil.Process(self.pid) if not p.is_running(): raise NoSuchProcess(self.pid, self.process_name) return "" return stdout @staticmethod def _which(program): """Same as UNIX which command. Return None on command not found.""" def is_exe(fpath): return os.path.isfile(fpath) and os.access(fpath, os.X_OK) fpath, fname = os.path.split(program) if fpath: if is_exe(program): return program else: for path in os.environ["PATH"].split(os.pathsep): exe_file = os.path.join(path, program) if is_exe(exe_file): return exe_file return None @staticmethod def _normaddress(addr, family): """Normalize an IP address.""" assert family in (socket.AF_INET, socket.AF_INET6), "unsupported family" if family == socket.AF_INET: ip, port = addr.split(':') else: if "]" in addr: ip, port = re.findall('\[([^]]+)\]:([0-9]+)', addr)[0] else: ip, port = addr.split(':') if ip == '*': if family == socket.AF_INET: ip = "0.0.0.0" elif family == socket.AF_INET6: ip = "::" # OS X can have some procs e.g. SystemUIServer listening on *:* else: raise ValueError("invalid IP %s" % addr) if port == "*": return 0 return (ip, int(port))
class Process(object): """Linux process implementation.""" __slots__ = ["pid", "_process_name"] def __init__(self, pid): if not isinstance(pid, int): raise TypeError('pid must be an integer') self.pid = pid self._process_name = None @wrap_exceptions def get_process_name(self): f = open("/proc/%s/stat" % self.pid) try: name = f.read().split(' ')[1].replace('(', '').replace(')', '') finally: f.close() # XXX - gets changed later and probably needs refactoring return name def get_process_exe(self): try: exe = os.readlink("/proc/%s/exe" % self.pid) except (OSError, IOError): err = sys.exc_info()[1] if err.errno == errno.ENOENT: # no such file error; might be raised also if the # path actually exists for system processes with # low pids (about 0-20) if os.path.lexists("/proc/%s/exe" % self.pid): return "" else: # ok, it is a process which has gone away raise NoSuchProcess(self.pid, self._process_name) if err.errno in (errno.EPERM, errno.EACCES): raise AccessDenied(self.pid, self._process_name) raise # readlink() might return paths containing null bytes causing # problems when used with other fs-related functions (os.*, # open(), ...) exe = exe.replace('\x00', '') # Certain names have ' (deleted)' appended. Usually this is # bogus as the file actually exists. Either way that's not # important as we don't want to discriminate executables which # have been deleted. if exe.endswith(" (deleted)") and not os.path.exists(exe): exe = exe[:-10] return exe @wrap_exceptions def get_process_cmdline(self): f = open("/proc/%s/cmdline" % self.pid) try: # return the args as a list return [x for x in f.read().split('\x00') if x] finally: f.close() @wrap_exceptions def get_process_terminal(self): f = open("/proc/%s/stat" % self.pid) try: tty_nr = int(f.read().split(' ')[6]) finally: f.close() try: return _TERMINAL_MAP[tty_nr] except KeyError: return None @wrap_exceptions def get_process_io_counters(self): f = open("/proc/%s/io" % self.pid) try: for line in f: if line.startswith("rchar"): read_count = int(line.split()[1]) elif line.startswith("wchar"): write_count = int(line.split()[1]) elif line.startswith("read_bytes"): read_bytes = int(line.split()[1]) elif line.startswith("write_bytes"): write_bytes = int(line.split()[1]) return nt_io(read_count, write_count, read_bytes, write_bytes) finally: f.close() if not os.path.exists('/proc/%s/io' % os.getpid()): def get_process_io_counters(self): raise NotImplementedError('/proc/PID/io is not available') @wrap_exceptions def get_cpu_times(self): f = open("/proc/%s/stat" % self.pid) try: st = f.read().strip() finally: f.close() # ignore the first two values ("pid (exe)") st = st[st.find(')') + 2:] values = st.split(' ') utime = float(values[11]) / _CLOCK_TICKS stime = float(values[12]) / _CLOCK_TICKS return nt_cputimes(utime, stime) @wrap_exceptions def process_wait(self, timeout=None): try: return _psposix.wait_pid(self.pid, timeout) except TimeoutExpired: raise TimeoutExpired(self.pid, self._process_name) @wrap_exceptions def get_process_create_time(self): f = open("/proc/%s/stat" % self.pid) try: st = f.read().strip() finally: f.close() # ignore the first two values ("pid (exe)") st = st[st.rfind(')') + 2:] values = st.split(' ') # According to documentation, starttime is in field 21 and the # unit is jiffies (clock ticks). # We first divide it for clock ticks and then add uptime returning # seconds since the epoch, in UTC. starttime = (float(values[19]) / _CLOCK_TICKS) + BOOT_TIME return starttime @wrap_exceptions def get_memory_info(self): f = open("/proc/%s/statm" % self.pid) try: vms, rss = f.readline().split()[:2] return nt_meminfo(int(rss) * _PAGESIZE, int(vms) * _PAGESIZE) finally: f.close() _nt_ext_mem = namedtuple('meminfo', 'rss vms shared text lib data dirty') @wrap_exceptions def get_ext_memory_info(self): # ============================================================ # | FIELD | DESCRIPTION | AKA | TOP | # ============================================================ # | rss | resident set size | | RES | # | vms | total program size | size | VIRT | # | shared | shared pages (from shared mappings) | | SHR | # | text | text ('code') | trs | CODE | # | lib | library (unused in Linux 2.6) | lrs | | # | data | data + stack | drs | DATA | # | dirty | dirty pages (unused in Linux 2.6) | dt | | # ============================================================ f = open("/proc/%s/statm" % self.pid) try: vms, rss, shared, text, lib, data, dirty = \ [int(x) * _PAGESIZE for x in f.readline().split()[:7]] finally: f.close() return self._nt_ext_mem(rss, vms, shared, text, lib, data, dirty) _mmap_base_fields = ['path', 'rss', 'size', 'pss', 'shared_clean', 'shared_dirty', 'private_clean', 'private_dirty', 'referenced', 'anonymous', 'swap',] nt_mmap_grouped = namedtuple('mmap', ' '.join(_mmap_base_fields)) nt_mmap_ext = namedtuple('mmap', 'addr perms ' + ' '.join(_mmap_base_fields)) def get_memory_maps(self): """Return process's mapped memory regions as a list of nameduples. Fields are explained in 'man proc'; here is an updated (Apr 2012) version: http://goo.gl/fmebo """ f = None try: f = open("/proc/%s/smaps" % self.pid) first_line = f.readline() current_block = [first_line] def get_blocks(): data = {} for line in f: fields = line.split(None, 5) if len(fields) >= 5: yield (current_block.pop(), data) current_block.append(line) else: data[fields[0]] = int(fields[1]) * 1024 yield (current_block.pop(), data) if first_line: # smaps file can be empty for header, data in get_blocks(): hfields = header.split(None, 5) try: addr, perms, offset, dev, inode, path = hfields except ValueError: addr, perms, offset, dev, inode, path = hfields + [''] if not path: path = '[anon]' else: path = path.strip() yield (addr, perms, path, data['Rss:'], data['Size:'], data.get('Pss:', 0), data['Shared_Clean:'], data['Shared_Clean:'], data['Private_Clean:'], data['Private_Dirty:'], data['Referenced:'], data.get('Anonymous:', 0), data['Swap:']) f.close() except EnvironmentError: # XXX - Can't use wrap_exceptions decorator as we're # returning a generator; this probably needs some # refactoring in order to avoid this code duplication. if f is not None: f.close() err = sys.exc_info()[1] if err.errno in (errno.ENOENT, errno.ESRCH): raise NoSuchProcess(self.pid, self._process_name) if err.errno in (errno.EPERM, errno.EACCES): raise AccessDenied(self.pid, self._process_name) raise except: if f is not None: f.close() raise if not os.path.exists('/proc/%s/smaps' % os.getpid()): def get_shared_libs(self, ext): msg = "this Linux version does not support /proc/PID/smaps " \ "(kernel < 2.6.14 or CONFIG_MMU kernel configuration " \ "option is not enabled)" raise NotImplementedError(msg) @wrap_exceptions def get_process_cwd(self): # readlink() might return paths containing null bytes causing # problems when used with other fs-related functions (os.*, # open(), ...) path = os.readlink("/proc/%s/cwd" % self.pid) return path.replace('\x00', '') @wrap_exceptions def get_num_ctx_switches(self): vol = unvol = None f = open("/proc/%s/status" % self.pid) try: for line in f: if line.startswith("voluntary_ctxt_switches"): vol = int(line.split()[1]) elif line.startswith("nonvoluntary_ctxt_switches"): unvol = int(line.split()[1]) if vol is not None and unvol is not None: return nt_ctxsw(vol, unvol) raise RuntimeError("line not found") finally: f.close() @wrap_exceptions def get_process_num_threads(self): f = open("/proc/%s/status" % self.pid) try: for line in f: if line.startswith("Threads:"): return int(line.split()[1]) raise RuntimeError("line not found") finally: f.close() @wrap_exceptions def get_process_threads(self): thread_ids = os.listdir("/proc/%s/task" % self.pid) thread_ids.sort() retlist = [] hit_enoent = False for thread_id in thread_ids: try: f = open("/proc/%s/task/%s/stat" % (self.pid, thread_id)) except EnvironmentError: err = sys.exc_info()[1] if err.errno == errno.ENOENT: # no such file or directory; it means thread # disappeared on us hit_enoent = True continue raise try: st = f.read().strip() finally: f.close() # ignore the first two values ("pid (exe)") st = st[st.find(')') + 2:] values = st.split(' ') utime = float(values[11]) / _CLOCK_TICKS stime = float(values[12]) / _CLOCK_TICKS ntuple = nt_thread(int(thread_id), utime, stime) retlist.append(ntuple) if hit_enoent: # raise NSP if the process disappeared on us os.stat('/proc/%s' % self.pid) return retlist @wrap_exceptions def get_process_nice(self): #f = open('/proc/%s/stat' % self.pid, 'r') #try: # data = f.read() # return int(data.split()[18]) #finally: # f.close() # Use C implementation return _psutil_posix.getpriority(self.pid) @wrap_exceptions def set_process_nice(self, value): return _psutil_posix.setpriority(self.pid, value) @wrap_exceptions def get_process_cpu_affinity(self): from_bitmask = lambda x: [i for i in xrange(64) if (1 << i) & x] bitmask = _psutil_linux.get_process_cpu_affinity(self.pid) return from_bitmask(bitmask) @wrap_exceptions def set_process_cpu_affinity(self, value): def to_bitmask(l): if not l: raise ValueError("invalid argument %r" % l) out = 0 for b in l: if not isinstance(b, (int, long)) or b < 0: raise ValueError("invalid argument %r" % b) out |= 2**b return out bitmask = to_bitmask(value) try: _psutil_linux.set_process_cpu_affinity(self.pid, bitmask) except OSError: err = sys.exc_info()[1] if err.errno == errno.EINVAL: allcpus = list(range(len(get_system_per_cpu_times()))) for cpu in value: if cpu not in allcpus: raise ValueError("invalid CPU %i" % cpu) raise # only starting from kernel 2.6.13 if hasattr(_psutil_linux, "ioprio_get"): @wrap_exceptions def get_process_ionice(self): ioclass, value = _psutil_linux.ioprio_get(self.pid) return nt_ionice(ioclass, value) @wrap_exceptions def set_process_ionice(self, ioclass, value): if ioclass in (IOPRIO_CLASS_NONE, None): if value: raise ValueError("can't specify value with IOPRIO_CLASS_NONE") ioclass = IOPRIO_CLASS_NONE value = 0 if ioclass in (IOPRIO_CLASS_RT, IOPRIO_CLASS_BE): if value is None: value = 4 elif ioclass == IOPRIO_CLASS_IDLE: if value: raise ValueError("can't specify value with IOPRIO_CLASS_IDLE") value = 0 else: value = 0 if not 0 <= value <= 8: raise ValueError("value argument range expected is between 0 and 8") return _psutil_linux.ioprio_set(self.pid, ioclass, value) @wrap_exceptions def get_process_status(self): f = open("/proc/%s/status" % self.pid) try: for line in f: if line.startswith("State:"): letter = line.split()[1] if letter in _status_map: return _status_map[letter] return constant(-1, '?') finally: f.close() @wrap_exceptions def get_open_files(self): retlist = [] files = os.listdir("/proc/%s/fd" % self.pid) hit_enoent = False for fd in files: file = "/proc/%s/fd/%s" % (self.pid, fd) if os.path.islink(file): try: file = os.readlink(file) except OSError: # ENOENT == file which is gone in the meantime err = sys.exc_info()[1] if err.errno == errno.ENOENT: hit_enoent = True continue raise else: # If file is not an absolute path there's no way # to tell whether it's a regular file or not, # so we skip it. A regular file is always supposed # to be absolutized though. if file.startswith('/') and isfile_strict(file): ntuple = nt_openfile(file, int(fd)) retlist.append(ntuple) if hit_enoent: # raise NSP if the process disappeared on us os.stat('/proc/%s' % self.pid) return retlist @wrap_exceptions def get_connections(self, kind='inet'): """Return connections opened by process as a list of namedtuples. The kind parameter filters for connections that fit the following criteria: Kind Value Number of connections using inet IPv4 and IPv6 inet4 IPv4 inet6 IPv6 tcp TCP tcp4 TCP over IPv4 tcp6 TCP over IPv6 udp UDP udp4 UDP over IPv4 udp6 UDP over IPv6 all the sum of all the possible families and protocols """ # Note: in case of UNIX sockets we're only able to determine the # local bound path while the remote endpoint is not retrievable: # http://goo.gl/R3GHM inodes = {} # os.listdir() is gonna raise a lot of access denied # exceptions in case of unprivileged user; that's fine: # lsof does the same so it's unlikely that we can to better. for fd in os.listdir("/proc/%s/fd" % self.pid): try: inode = os.readlink("/proc/%s/fd/%s" % (self.pid, fd)) except OSError: continue if inode.startswith('socket:['): # the process is using a socket inode = inode[8:][:-1] inodes[inode] = fd if not inodes: # no connections for this process return [] def process(file, family, type_): retlist = [] try: f = open(file, 'r') except IOError: # IPv6 not supported on this platform err = sys.exc_info()[1] if err.errno == errno.ENOENT and file.endswith('6'): return [] else: raise try: f.readline() # skip the first line for line in f: # IPv4 / IPv6 if family in (socket.AF_INET, socket.AF_INET6): _, laddr, raddr, status, _, _, _, _, _, inode = \ line.split()[:10] if inode in inodes: laddr = self._decode_address(laddr, family) raddr = self._decode_address(raddr, family) if type_ == socket.SOCK_STREAM: status = _TCP_STATES_TABLE[status] else: status = "" fd = int(inodes[inode]) conn = nt_connection(fd, family, type_, laddr, raddr, status) retlist.append(conn) elif family == socket.AF_UNIX: tokens = line.split() _, _, _, _, type_, _, inode = tokens[0:7] if inode in inodes: if len(tokens) == 8: path = tokens[-1] else: path = "" fd = int(inodes[inode]) type_ = int(type_) conn = nt_connection(fd, family, type_, path, None, "") retlist.append(conn) else: raise ValueError(family) return retlist finally: f.close() tcp4 = ("tcp" , socket.AF_INET , socket.SOCK_STREAM) tcp6 = ("tcp6", socket.AF_INET6, socket.SOCK_STREAM) udp4 = ("udp" , socket.AF_INET , socket.SOCK_DGRAM) udp6 = ("udp6", socket.AF_INET6, socket.SOCK_DGRAM) unix = ("unix", socket.AF_UNIX, None) tmap = { "all" : (tcp4, tcp6, udp4, udp6, unix), "tcp" : (tcp4, tcp6), "tcp4" : (tcp4,), "tcp6" : (tcp6,), "udp" : (udp4, udp6), "udp4" : (udp4,), "udp6" : (udp6,), "unix" : (unix,), "inet" : (tcp4, tcp6, udp4, udp6), "inet4": (tcp4, udp4), "inet6": (tcp6, udp6), } if kind not in tmap: raise ValueError("invalid %r kind argument; choose between %s" % (kind, ', '.join([repr(x) for x in tmap]))) ret = [] for f, family, type_ in tmap[kind]: ret += process("/proc/net/%s" % f, family, type_) # raise NSP if the process disappeared on us os.stat('/proc/%s' % self.pid) return ret # --- lsof implementation # # def get_connections(self): # lsof = _psposix.LsofParser(self.pid, self._process_name) # return lsof.get_process_connections() @wrap_exceptions def get_num_fds(self): return len(os.listdir("/proc/%s/fd" % self.pid)) @wrap_exceptions def get_process_ppid(self): f = open("/proc/%s/status" % self.pid) try: for line in f: if line.startswith("PPid:"): # PPid: nnnn return int(line.split()[1]) raise RuntimeError("line not found") finally: f.close() @wrap_exceptions def get_process_uids(self): f = open("/proc/%s/status" % self.pid) try: for line in f: if line.startswith('Uid:'): _, real, effective, saved, fs = line.split() return nt_uids(int(real), int(effective), int(saved)) raise RuntimeError("line not found") finally: f.close() @wrap_exceptions def get_process_gids(self): f = open("/proc/%s/status" % self.pid) try: for line in f: if line.startswith('Gid:'): _, real, effective, saved, fs = line.split() return nt_gids(int(real), int(effective), int(saved)) raise RuntimeError("line not found") finally: f.close() @staticmethod def _decode_address(addr, family): """Accept an "ip:port" address as displayed in /proc/net/* and convert it into a human readable form, like: "0500000A:0016" -> ("10.0.0.5", 22) "0000000000000000FFFF00000100007F:9E49" -> ("::ffff:127.0.0.1", 40521) The IP address portion is a little or big endian four-byte hexadecimal number; that is, the least significant byte is listed first, so we need to reverse the order of the bytes to convert it to an IP address. The port is represented as a two-byte hexadecimal number. Reference: http://linuxdevcenter.com/pub/a/linux/2000/11/16/LinuxAdmin.html """ ip, port = addr.split(':') port = int(port, 16) if PY3: ip = ip.encode('ascii') # this usually refers to a local socket in listen mode with # no end-points connected if not port: return () if family == socket.AF_INET: # see: http://code.google.com/p/psutil/issues/detail?id=201 if sys.byteorder == 'little': ip = socket.inet_ntop(family, base64.b16decode(ip)[::-1]) else: ip = socket.inet_ntop(family, base64.b16decode(ip)) else: # IPv6 # old version - let's keep it, just in case... #ip = ip.decode('hex') #return socket.inet_ntop(socket.AF_INET6, # ''.join(ip[i:i+4][::-1] for i in xrange(0, 16, 4))) ip = base64.b16decode(ip) # see: http://code.google.com/p/psutil/issues/detail?id=201 if sys.byteorder == 'little': ip = socket.inet_ntop(socket.AF_INET6, struct.pack('>4I', *struct.unpack('<4I', ip))) else: ip = socket.inet_ntop(socket.AF_INET6, struct.pack('<4I', *struct.unpack('<4I', ip))) return (ip, port)
STATUS_RUNNING = constant(0, "running") STATUS_SLEEPING = constant(1, "sleeping") STATUS_DISK_SLEEP = constant(2, "disk sleep") STATUS_STOPPED = constant(3, "stopped") STATUS_TRACING_STOP = constant(4, "tracing stop") STATUS_ZOMBIE = constant(5, "zombie") STATUS_DEAD = constant(6, "dead") STATUS_WAKE_KILL = constant(7, "wake kill") STATUS_WAKING = constant(8, "waking") STATUS_IDLE = constant(9, "idle") # BSD STATUS_LOCKED = constant(10, "locked") # BSD STATUS_WAITING = constant(11, "waiting") # BSD # system ntuple_sys_cputimes = namedtuple('cputimes', 'user nice system idle iowait irq softirq') # processes ntuple_meminfo = namedtuple('meminfo', 'rss vms') ntuple_cputimes = namedtuple('cputimes', 'user system') ntuple_openfile = namedtuple('openfile', 'path fd') ntuple_connection = namedtuple('connection', 'fd family type local_address remote_address status') ntuple_thread = namedtuple('thread', 'id user_time system_time') ntuple_uids = namedtuple('user', 'real effective saved') ntuple_gids = namedtuple('group', 'real effective saved') ntuple_io = namedtuple('io', 'read_count write_count read_bytes write_bytes') ntuple_ionice = namedtuple('ionice', 'ioclass value') # the __all__ namespace common to all _ps*.py platform modules base_module_namespace = [ # constants
"inet4": ([AF_INET], [SOCK_STREAM, SOCK_DGRAM]), "inet6": ([AF_INET6], [SOCK_STREAM, SOCK_DGRAM]), } if AF_INET6 is not None: conn_tmap.update({ "tcp6": ([AF_INET6], [SOCK_STREAM]), "udp6": ([AF_INET6], [SOCK_DGRAM]), }) del AF_INET, AF_INET6, SOCK_STREAM, SOCK_DGRAM, socket # --- namedtuples # system ntuple_sys_cputimes = namedtuple('cputimes', 'user nice system idle iowait irq softirq') ntuple_sysmeminfo = namedtuple('usage', 'total used free percent') ntuple_diskinfo = namedtuple('usage', 'total used free percent') ntuple_partition = namedtuple('partition', 'device mountpoint fstype') ntuple_net_iostat = namedtuple( 'iostat', 'bytes_sent bytes_recv packets_sent packets_recv') ntuple_disk_iostat = namedtuple( 'iostat', 'read_count write_count read_bytes write_bytes read_time write_time') ntuple_user = namedtuple('user', 'name terminal host started user_process') # processes ntuple_meminfo = namedtuple('meminfo', 'rss vms') ntuple_cputimes = namedtuple('cputimes', 'user system') ntuple_openfile = namedtuple('openfile', 'path fd') ntuple_connection = namedtuple(
from psutil._compat import namedtuple, PY3 from psutil._common import * __extra__all__ = ["CONN_IDLE", "CONN_BOUND"] PAGE_SIZE = os.sysconf('SC_PAGE_SIZE') NUM_CPUS = os.sysconf("SC_NPROCESSORS_ONLN") BOOT_TIME = _psutil_sunos.get_process_basic_info(0)[3] TOTAL_PHYMEM = os.sysconf('SC_PHYS_PAGES') * PAGE_SIZE CONN_IDLE = constant(11, "IDLE") CONN_BOUND = constant(12, "BOUND") _PAGESIZE = os.sysconf("SC_PAGE_SIZE") _cputimes_ntuple = namedtuple('cputimes', 'user system idle iowait') disk_io_counters = _psutil_sunos.get_disk_io_counters net_io_counters = _psutil_sunos.get_net_io_counters get_disk_usage = _psposix.get_disk_usage get_system_boot_time = lambda: _psutil_sunos.get_process_basic_info(0)[3] nt_virtmem_info = namedtuple('vmem', ' '.join([ # all platforms 'total', 'available', 'percent', 'used', 'free'])) def virtual_memory(): # we could have done this with kstat, but imho this is good enough total = os.sysconf('SC_PHYS_PAGES') * PAGE_SIZE # note: there's no difference on Solaris free = avail = os.sysconf('SC_AVPHYS_PAGES') * PAGE_SIZE
cext.MIB_TCP_STATE_ESTAB: _common.CONN_ESTABLISHED, cext.MIB_TCP_STATE_SYN_SENT: _common.CONN_SYN_SENT, cext.MIB_TCP_STATE_SYN_RCVD: _common.CONN_SYN_RECV, cext.MIB_TCP_STATE_FIN_WAIT1: _common.CONN_FIN_WAIT1, cext.MIB_TCP_STATE_FIN_WAIT2: _common.CONN_FIN_WAIT2, cext.MIB_TCP_STATE_TIME_WAIT: _common.CONN_TIME_WAIT, cext.MIB_TCP_STATE_CLOSED: _common.CONN_CLOSE, cext.MIB_TCP_STATE_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, cext.MIB_TCP_STATE_LAST_ACK: _common.CONN_LAST_ACK, cext.MIB_TCP_STATE_LISTEN: _common.CONN_LISTEN, cext.MIB_TCP_STATE_CLOSING: _common.CONN_CLOSING, cext.MIB_TCP_STATE_DELETE_TCB: CONN_DELETE_TCB, cext.PSUTIL_CONN_NONE: _common.CONN_NONE, } scputimes = namedtuple('scputimes', ['user', 'system', 'idle']) svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) pextmem = namedtuple('pextmem', [ 'num_page_faults', 'peak_wset', 'wset', 'peak_paged_pool', 'paged_pool', 'peak_nonpaged_pool', 'nonpaged_pool', 'pagefile', 'peak_pagefile', 'private' ]) pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss']) pmmap_ext = namedtuple('pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) # set later from __init__.py NoSuchProcess = None AccessDenied = None TimeoutExpired = None
cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, cext.TCPS_SYN_RCVD: _common.CONN_SYN_RECV, cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, cext.TCPS_CLOSED: _common.CONN_CLOSE, cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, cext.TCPS_LISTEN: _common.CONN_LISTEN, cext.TCPS_CLOSING: _common.CONN_CLOSING, cext.PSUTIL_CONN_NONE: _common.CONN_NONE, cext.TCPS_IDLE: CONN_IDLE, # sunos specific cext.TCPS_BOUND: CONN_BOUND, # sunos specific } scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait']) svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) pextmem = namedtuple('pextmem', ['rss', 'vms']) pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss', 'anon', 'locked']) pmmap_ext = namedtuple( 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) # --- functions disk_io_counters = cext.disk_io_counters net_io_counters = cext.net_io_counters disk_usage = _psposix.disk_usage def virtual_memory():
_psutil_sunos.TCPS_CLOSE_WAIT: CONN_CLOSE_WAIT, _psutil_sunos.TCPS_LAST_ACK: CONN_LAST_ACK, _psutil_sunos.TCPS_LISTEN: CONN_LISTEN, _psutil_sunos.TCPS_CLOSING: CONN_CLOSING, _psutil_sunos.PSUTIL_CONN_NONE: CONN_NONE, _psutil_sunos.TCPS_IDLE: CONN_IDLE, # sunos specific _psutil_sunos.TCPS_BOUND: CONN_BOUND, # sunos specific } disk_io_counters = _psutil_sunos.get_disk_io_counters net_io_counters = _psutil_sunos.get_net_io_counters get_disk_usage = _psposix.get_disk_usage get_system_boot_time = _psutil_sunos.get_boot_time nt_virtmem_info = namedtuple('vmem', ' '.join([ 'total', 'available', 'percent', 'used', 'free'])) # all platforms def virtual_memory(): # we could have done this with kstat, but imho this is good enough total = os.sysconf('SC_PHYS_PAGES') * PAGE_SIZE # note: there's no difference on Solaris free = avail = os.sysconf('SC_AVPHYS_PAGES') * PAGE_SIZE used = total - free percent = usage_percent(used, total, _round=1) return nt_virtmem_info(total, avail, percent, used, free) def swap_memory(): sin, sout = _psutil_sunos.get_swap_mem() # XXX # we are supposed to get total/free by doing so:
class Process(object): """Wrapper class around underlying C implementation.""" __slots__ = ["pid", "_process_name"] def __init__(self, pid): self.pid = pid self._process_name = None @wrap_exceptions def get_process_name(self): """Return process name as a string of limited len (15).""" return _psutil_bsd.get_process_name(self.pid) @wrap_exceptions def get_process_exe(self): """Return process executable pathname.""" return _psutil_bsd.get_process_exe(self.pid) @wrap_exceptions def get_process_cmdline(self): """Return process cmdline as a list of arguments.""" return _psutil_bsd.get_process_cmdline(self.pid) @wrap_exceptions def get_process_terminal(self): tty_nr = _psutil_bsd.get_process_tty_nr(self.pid) try: return _TERMINAL_MAP[tty_nr] except KeyError: return None @wrap_exceptions def get_process_ppid(self): """Return process parent pid.""" return _psutil_bsd.get_process_ppid(self.pid) # XXX - available on FreeBSD >= 8 only if hasattr(_psutil_bsd, "get_process_cwd"): @wrap_exceptions def get_process_cwd(self): """Return process current working directory.""" # sometimes we get an empty string, in which case we turn # it into None return _psutil_bsd.get_process_cwd(self.pid) or None @wrap_exceptions def get_process_uids(self): """Return real, effective and saved user ids.""" real, effective, saved = _psutil_bsd.get_process_uids(self.pid) return nt_uids(real, effective, saved) @wrap_exceptions def get_process_gids(self): """Return real, effective and saved group ids.""" real, effective, saved = _psutil_bsd.get_process_gids(self.pid) return nt_gids(real, effective, saved) @wrap_exceptions def get_cpu_times(self): """return a tuple containing process user/kernel time.""" user, system = _psutil_bsd.get_process_cpu_times(self.pid) return nt_cputimes(user, system) @wrap_exceptions def get_memory_info(self): """Return a tuple with the process' RSS and VMS size.""" rss, vms = _psutil_bsd.get_process_memory_info(self.pid)[:2] return nt_meminfo(rss, vms) _nt_ext_mem = namedtuple('meminfo', 'rss vms text data stack') @wrap_exceptions def get_ext_memory_info(self): return self._nt_ext_mem(*_psutil_bsd.get_process_memory_info(self.pid)) @wrap_exceptions def get_process_create_time(self): """Return the start time of the process as a number of seconds since the epoch.""" return _psutil_bsd.get_process_create_time(self.pid) @wrap_exceptions def get_process_num_threads(self): """Return the number of threads belonging to the process.""" return _psutil_bsd.get_process_num_threads(self.pid) @wrap_exceptions def get_num_ctx_switches(self): return nt_ctxsw(*_psutil_bsd.get_process_num_ctx_switches(self.pid)) @wrap_exceptions def get_num_fds(self): """Return the number of file descriptors opened by this process.""" return _psutil_bsd.get_process_num_fds(self.pid) @wrap_exceptions def get_process_threads(self): """Return the number of threads belonging to the process.""" rawlist = _psutil_bsd.get_process_threads(self.pid) retlist = [] for thread_id, utime, stime in rawlist: ntuple = nt_thread(thread_id, utime, stime) retlist.append(ntuple) return retlist @wrap_exceptions def get_open_files(self): """Return files opened by process as a list of namedtuples.""" # XXX - C implementation available on FreeBSD >= 8 only # else fallback on lsof parser if hasattr(_psutil_bsd, "get_process_open_files"): rawlist = _psutil_bsd.get_process_open_files(self.pid) return [nt_openfile(path, fd) for path, fd in rawlist] else: lsof = _psposix.LsofParser(self.pid, self._process_name) return lsof.get_process_open_files() @wrap_exceptions def get_connections(self, kind='inet'): """Return etwork connections opened by a process as a list of namedtuples. """ if kind not in conn_tmap: raise ValueError("invalid %r kind argument; choose between %s" % (kind, ', '.join([repr(x) for x in conn_tmap]))) families, types = conn_tmap[kind] ret = _psutil_bsd.get_process_connections(self.pid, families, types) return [nt_connection(*conn) for conn in ret] @wrap_exceptions def process_wait(self, timeout=None): try: return _psposix.wait_pid(self.pid, timeout) except TimeoutExpired: raise TimeoutExpired(self.pid, self._process_name) @wrap_exceptions def get_process_nice(self): return _psutil_posix.getpriority(self.pid) @wrap_exceptions def set_process_nice(self, value): return _psutil_posix.setpriority(self.pid, value) @wrap_exceptions def get_process_status(self): code = _psutil_bsd.get_process_status(self.pid) if code in _status_map: return _status_map[code] return constant(-1, "?") @wrap_exceptions def get_process_io_counters(self): rc, wc, rb, wb = _psutil_bsd.get_process_io_counters(self.pid) return nt_io(rc, wc, rb, wb) nt_mmap_grouped = namedtuple('mmap', 'path rss, private, ref_count, shadow_count') nt_mmap_ext = namedtuple( 'mmap', 'addr, perms path rss, private, ref_count, shadow_count') @wrap_exceptions def get_memory_maps(self): return _psutil_bsd.get_process_memory_maps(self.pid) # FreeBSD < 8 does not support kinfo_getfile() and kinfo_getvmmap() if not hasattr(_psutil_bsd, 'get_process_open_files'): def _not_implemented(self): raise NotImplementedError("supported only starting from FreeBSD 8") get_open_files = _not_implemented get_process_cwd = _not_implemented get_memory_maps = _not_implemented get_num_fds = _not_implemented
"tcp6": ([AF_INET6], [SOCK_STREAM]), "udp6": ([AF_INET6], [SOCK_DGRAM]), }) if AF_UNIX is not None: conn_tmap.update({ "unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]), }) del AF_INET, AF_INET6, AF_UNIX, SOCK_STREAM, SOCK_DGRAM, socket # --- namedtuples for psutil.* system-related functions # psutil.swap_memory() sswap = namedtuple('sswap', ['total', 'used', 'free', 'percent', 'sin', 'sout']) # psutil.disk_usage() sdiskusage = namedtuple('sdiskusage', ['total', 'used', 'free', 'percent']) # psutil.disk_io_counters() sdiskio = namedtuple('sdiskio', ['read_count', 'write_count', 'read_bytes', 'write_bytes', 'read_time', 'write_time']) # psutil.disk_partitions() sdiskpart = namedtuple('sdiskpart', ['device', 'mountpoint', 'fstype', 'opts']) # psutil.net_io_counters() snetio = namedtuple('snetio', ['bytes_sent', 'bytes_recv', 'packets_sent', 'packets_recv', 'errin', 'errout', 'dropin', 'dropout']) # psutil.users() suser = namedtuple('suser', ['name', 'terminal', 'host', 'started'])
mountpoint = letter type = _psutil_mswindows.win32_GetDriveType(letter) if not os.path.exists(mountpoint): # usually a CD-ROM device with no disk inserted mountpoint = "" if not all: if type not in ("cdrom", "fixed", "removable"): continue if not mountpoint: continue ntuple = ntuple_partition(letter, mountpoint, type) retlist.append(ntuple) return retlist _cputimes_ntuple = namedtuple("cputimes", "user system idle") def get_system_cpu_times(): """Return system CPU times as a named tuple.""" user, system, idle = 0, 0, 0 # computes system global times summing each processor value for cpu_time in _psutil_mswindows.get_system_cpu_times(): user += cpu_time[0] system += cpu_time[1] idle += cpu_time[2] return _cputimes_ntuple(user, system, idle) def get_system_per_cpu_times(): """Return system per-CPU times as a list of named tuples."""
mountpoint = letter type = _psutil_mswindows.win32_GetDriveType(letter) if not os.path.exists(mountpoint): # usually a CD-ROM device with no disk inserted mountpoint = "" if not all: if type not in ('cdrom', 'fixed', 'removable'): continue if not mountpoint: continue ntuple = ntuple_partition(letter, mountpoint, type) retlist.append(ntuple) return retlist _cputimes_ntuple = namedtuple('cputimes', 'user system idle') def get_system_cpu_times(): """Return system CPU times as a named tuple.""" user, system, idle = 0, 0, 0 # computes system global times summing each processor value for cpu_time in _psutil_mswindows.get_system_cpu_times(): user += cpu_time[0] system += cpu_time[1] idle += cpu_time[2] return _cputimes_ntuple(user, system, idle) def get_system_per_cpu_times(): """Return system per-CPU times as a list of named tuples."""
f.close() fields = ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq'] vlen = len(values) if vlen >= 8: # Linux >= 2.6.11 fields.append('steal') if vlen >= 9: # Linux >= 2.6.24 fields.append('guest') if vlen >= 10: # Linux >= 3.2.0 fields.append('guest_nice') return fields scputimes = namedtuple('scputimes', _get_cputimes_fields()) svmem = namedtuple( 'svmem', ['total', 'available', 'percent', 'used', 'free', 'active', 'inactive', 'buffers', 'cached']) pextmem = namedtuple('pextmem', 'rss vms shared text lib data dirty') pmmap_grouped = namedtuple( 'pmmap_grouped', ['path', 'rss', 'size', 'pss', 'shared_clean', 'shared_dirty', 'private_clean', 'private_dirty', 'referenced', 'anonymous', 'swap']) pmmap_ext = namedtuple( 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
import _psutil_posix from psutil import _psposix from psutil.error import AccessDenied, NoSuchProcess, TimeoutExpired from psutil._compat import namedtuple from psutil._common import * __extra__all__ = [] # --- constants NUM_CPUS = _psutil_bsd.get_num_cpus() BOOT_TIME = _psutil_bsd.get_system_boot_time() TOTAL_PHYMEM = _psutil_bsd.get_virtual_mem()[0] _TERMINAL_MAP = _psposix._get_terminal_map() _PAGESIZE = os.sysconf("SC_PAGE_SIZE") _cputimes_ntuple = namedtuple('cputimes', 'user nice system idle irq') # --- public functions nt_virtmem_info = namedtuple( 'vmem', ' '.join([ # all platforms 'total', 'available', 'percent', 'used', 'free', # FreeBSD specific 'active', 'inactive',
class Process(object): """Wrapper class around underlying C implementation.""" __slots__ = ["pid", "_process_name"] def __init__(self, pid): self.pid = pid self._process_name = None @wrap_exceptions def get_process_name(self): """Return process name as a string of limited len (15).""" return _psutil_osx.get_process_name(self.pid) @wrap_exceptions def get_process_exe(self): return _psutil_osx.get_process_exe(self.pid) @wrap_exceptions def get_process_cmdline(self): """Return process cmdline as a list of arguments.""" if not pid_exists(self.pid): raise NoSuchProcess(self.pid, self._process_name) return _psutil_osx.get_process_cmdline(self.pid) @wrap_exceptions def get_process_ppid(self): """Return process parent pid.""" return _psutil_osx.get_process_ppid(self.pid) @wrap_exceptions def get_process_cwd(self): return _psutil_osx.get_process_cwd(self.pid) @wrap_exceptions def get_process_uids(self): real, effective, saved = _psutil_osx.get_process_uids(self.pid) return nt_uids(real, effective, saved) @wrap_exceptions def get_process_gids(self): real, effective, saved = _psutil_osx.get_process_gids(self.pid) return nt_gids(real, effective, saved) @wrap_exceptions def get_process_terminal(self): tty_nr = _psutil_osx.get_process_tty_nr(self.pid) tmap = _psposix._get_terminal_map() try: return tmap[tty_nr] except KeyError: return None @wrap_exceptions def get_memory_info(self): """Return a tuple with the process' RSS and VMS size.""" rss, vms = _psutil_osx.get_process_memory_info(self.pid)[:2] return nt_meminfo(rss, vms) _nt_ext_mem = namedtuple('meminfo', 'rss vms pfaults pageins') @wrap_exceptions def get_ext_memory_info(self): """Return a tuple with the process' RSS and VMS size.""" rss, vms, pfaults, pageins = _psutil_osx.get_process_memory_info( self.pid) return self._nt_ext_mem(rss, vms, pfaults * _PAGESIZE, pageins * _PAGESIZE) @wrap_exceptions def get_cpu_times(self): user, system = _psutil_osx.get_process_cpu_times(self.pid) return nt_cputimes(user, system) @wrap_exceptions def get_process_create_time(self): """Return the start time of the process as a number of seconds since the epoch.""" return _psutil_osx.get_process_create_time(self.pid) @wrap_exceptions def get_num_ctx_switches(self): return nt_ctxsw(*_psutil_osx.get_process_num_ctx_switches(self.pid)) @wrap_exceptions def get_process_num_threads(self): """Return the number of threads belonging to the process.""" return _psutil_osx.get_process_num_threads(self.pid) @wrap_exceptions def get_open_files(self): """Return files opened by process.""" if self.pid == 0: return [] files = [] rawlist = _psutil_osx.get_process_open_files(self.pid) for path, fd in rawlist: if isfile_strict(path): ntuple = nt_openfile(path, fd) files.append(ntuple) return files @wrap_exceptions def get_connections(self, kind='inet'): """Return etwork connections opened by a process as a list of namedtuples. """ if kind not in conn_tmap: raise ValueError("invalid %r kind argument; choose between %s" % (kind, ', '.join([repr(x) for x in conn_tmap]))) families, types = conn_tmap[kind] rawlist = _psutil_osx.get_process_connections(self.pid, families, types) ret = [] for item in rawlist: fd, fam, type, laddr, raddr, status = item status = _TCP_STATES_TABLE[status] nt = nt_connection(fd, fam, type, laddr, raddr, status) ret.append(nt) return ret @wrap_exceptions def get_num_fds(self): if self.pid == 0: return 0 return _psutil_osx.get_process_num_fds(self.pid) @wrap_exceptions def process_wait(self, timeout=None): try: return _psposix.wait_pid(self.pid, timeout) except TimeoutExpired: raise TimeoutExpired(self.pid, self._process_name) @wrap_exceptions def get_process_nice(self): return _psutil_posix.getpriority(self.pid) @wrap_exceptions def set_process_nice(self, value): return _psutil_posix.setpriority(self.pid, value) @wrap_exceptions def get_process_status(self): code = _psutil_osx.get_process_status(self.pid) # XXX is '?' legit? (we're not supposed to return it anyway) return _status_map.get(code, '?') @wrap_exceptions def get_process_threads(self): """Return the number of threads belonging to the process.""" rawlist = _psutil_osx.get_process_threads(self.pid) retlist = [] for thread_id, utime, stime in rawlist: ntuple = nt_thread(thread_id, utime, stime) retlist.append(ntuple) return retlist nt_mmap_grouped = namedtuple( 'mmap', 'path rss private swapped dirtied ref_count shadow_depth') nt_mmap_ext = namedtuple( 'mmap', 'addr perms path rss private swapped dirtied ref_count shadow_depth') @wrap_exceptions def get_memory_maps(self): return _psutil_osx.get_process_memory_maps(self.pid)
"tcp6" : ([AF_INET6], [SOCK_STREAM]), "udp6" : ([AF_INET6], [SOCK_DGRAM]), }) if AF_UNIX is not None: conn_tmap.update({ "unix" : ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]), }) del AF_INET, AF_INET6, AF_UNIX, SOCK_STREAM, SOCK_DGRAM, socket # --- namedtuples # system nt_sys_cputimes = namedtuple('cputimes', 'user nice system idle iowait irq softirq') nt_sysmeminfo = namedtuple('usage', 'total used free percent') # XXX - would 'available' be better than 'free' as for virtual_memory() nt? nt_swapmeminfo = namedtuple('swap', 'total used free percent sin sout') nt_diskinfo = namedtuple('usage', 'total used free percent') nt_partition = namedtuple('partition', 'device mountpoint fstype opts') nt_net_iostat = namedtuple('iostat', 'bytes_sent bytes_recv packets_sent packets_recv errin errout dropin dropout') nt_disk_iostat = namedtuple('iostat', 'read_count write_count read_bytes write_bytes read_time write_time') nt_user = namedtuple('user', 'name terminal host started') # processes nt_meminfo = namedtuple('meminfo', 'rss vms') nt_cputimes = namedtuple('cputimes', 'user system') nt_openfile = namedtuple('openfile', 'path fd') nt_connection = namedtuple('connection', 'fd family type local_address remote_address status')
"04" : CONN_FIN_WAIT1, "05" : CONN_FIN_WAIT2, "06" : CONN_TIME_WAIT, "07" : CONN_CLOSE, "08" : CONN_CLOSE_WAIT, "09" : CONN_LAST_ACK, "0A" : CONN_LISTEN, "0B" : CONN_CLOSING } # --- system memory functions nt_virtmem_info = namedtuple('vmem', ' '.join([ # all platforms 'total', 'available', 'percent', 'used', 'free', # linux specific 'active', 'inactive', 'buffers', 'cached'])) def virtual_memory(): total, free, buffers, shared, _, _ = _psutil_linux.get_sysinfo() cached = active = inactive = None f = open('/proc/meminfo', 'r') try: for line in f: if line.startswith('Cached:'): cached = int(line.split()[1]) * 1024 elif line.startswith('Active:'): active = int(line.split()[1]) * 1024 elif line.startswith('Inactive:'):
conn_tmap.update({ "tcp6": ([AF_INET6], [SOCK_STREAM]), "udp6": ([AF_INET6], [SOCK_DGRAM]), }) if AF_UNIX is not None: conn_tmap.update({ "unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]), }) del AF_INET, AF_INET6, AF_UNIX, SOCK_STREAM, SOCK_DGRAM, socket # --- namedtuples # system nt_sysmeminfo = namedtuple('usage', 'total used free percent') # XXX - would 'available' be better than 'free' as for virtual_memory() nt? nt_swapmeminfo = namedtuple('swap', 'total used free percent sin sout') nt_diskinfo = namedtuple('usage', 'total used free percent') nt_partition = namedtuple('partition', 'device mountpoint fstype opts') nt_net_iostat = namedtuple( 'iostat', 'bytes_sent bytes_recv packets_sent packets_recv errin errout dropin dropout' ) nt_disk_iostat = namedtuple( 'iostat', 'read_count write_count read_bytes write_bytes read_time write_time') nt_user = namedtuple('user', 'name terminal host started') # processes nt_meminfo = namedtuple('meminfo', 'rss vms')
def total_virtmem(): "Return the amount of total virtual memory available on the system, in bytes." return _psutil_bsd.get_total_virtmem() def avail_virtmem(): "Return the amount of virtual memory currently in use on the system, in bytes." return _psutil_bsd.get_avail_virtmem() def used_virtmem(): """Return the amount of used memory currently in use on the system, in bytes.""" return _psutil_bsd.get_total_virtmem() - _psutil_bsd.get_avail_virtmem() _cputimes_ntuple = namedtuple("cputimes", "user nice system idle irq") def get_system_cpu_times(): """Return system CPU times as a named tuple""" user, nice, system, idle, irq = _psutil_bsd.get_system_cpu_times() return _cputimes_ntuple(user, nice, system, idle, irq) def get_pid_list(): """Returns a list of PIDs currently running on the system.""" return _psutil_bsd.get_pid_list() def pid_exists(pid): """Check For the existence of a unix pid."""