def send_signal(self, sig): """Send a signal to process (see signal module constants). On Windows only SIGTERM is valid and is treated as an alias for kill(). """ # safety measure in case the current process has been killed in # meantime and the kernel reused its PID if not self.is_running(): name = self._platform_impl._process_name raise NoSuchProcess(self.pid, name) if os.name == 'posix': try: os.kill(self.pid, sig) except OSError: err = sys.exc_info()[1] name = self._platform_impl._process_name if err.errno == errno.ESRCH: raise NoSuchProcess(self.pid, name) if err.errno == errno.EPERM: raise AccessDenied(self.pid, name) raise else: if sig == signal.SIGTERM: self._platform_impl.kill_process() else: raise ValueError("only SIGTERM is supported on Windows")
def get_process_exe(self): if self.pid in (0, 2): raise AccessDenied(self.pid, self._process_name) 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', '') # It seems symlinks can point to a deleted/invalid location # (this usually happens with "pulseaudio" process). # However, if we had permissions to execute readlink() it's # likely that we'll be able to figure out exe from argv[0] # later on. if exe.endswith(" (deleted)") and not os.path.isfile(exe): return "" return exe
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
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
def get_process_exe(self): # no such thing as "exe" on Windows; it will maybe be determined # later from cmdline[0] if not pid_exists(self.pid): raise NoSuchProcess(self.pid, self._process_name) if self.pid in (0, 4): raise AccessDenied(self.pid, self._process_name) return ""
def wrapper(self, *args, **kwargs): try: return method(self, *args, **kwargs) except OSError, err: if err.errno == 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
def wrapper(self, *args, **kwargs): try: return callable(self, *args, **kwargs) except OSError, err: if err.errno in (errno.EPERM, errno.EACCES, ERROR_ACCESS_DENIED): raise AccessDenied(self.pid, self._process_name) if err.errno == errno.ESRCH: raise NoSuchProcess(self.pid, self._process_name) raise
def wrapper(self, *args, **kwargs): try: return callable(self, *args, **kwargs) except (OSError, IOError), err: if err.errno == errno.ENOENT: # no such file or directory raise NoSuchProcess(self.pid, self._process_name) if err.errno in (errno.EPERM, errno.EACCES): raise AccessDenied(self.pid, self._process_name) raise
def get_children(self, recursive=False): """Return the children of this process as a list of Process objects. If recursive is True return all the parent descendants. Example (A == this process): A ─┐ │ ├─ B (child) ─┐ │ └─ X (grandchild) ─┐ │ └─ Y (great grandchild) ├─ C (child) └─ D (child) >>> p.get_children() B, C, D >>> p.get_children(recursive=True) B, X, Y, C, D Note that in the example above if process X disappears process Y won't be returned either as the reference to process A is lost. """ if not self.is_running(): name = self._platform_impl._process_name raise NoSuchProcess(self.pid, name) ret = [] if not recursive: for p in process_iter(): try: if p.ppid == self.pid: ret.append(p) except NoSuchProcess: pass else: # construct a dict where 'values' are all the processes # having 'key' as their parent table = defaultdict(list) for p in process_iter(): try: table[p.ppid].append(p) except NoSuchProcess: pass # At this point we have a mapping table where table[self.pid] # are the current process's children. # Below, we look for all descendants recursively, similarly # to a recursive function call. checkpids = [self.pid] for pid in checkpids: for proc in table[pid]: ret.append(proc) if proc.pid not in checkpids: checkpids.append(proc.pid) return ret
def wrapper(self, *args, **kwargs): try: return callable(self, *args, **kwargs) except OSError: err = sys.exc_info()[1] if err.errno == 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
def kill(self): """Kill the current process.""" # safety measure in case the current process has been killed in # meantime and the kernel reused its PID if not self.is_running(): name = self._platform_impl._process_name raise NoSuchProcess(self.pid, name) if os.name == 'posix': self.send_signal(signal.SIGKILL) else: self._platform_impl.kill_process()
def get_memory_maps(self): try: raw = _psutil_mswindows.get_process_memory_maps(self.pid) except OSError, err: # XXX - can't use wrap_exceptions decorator as we're # returning a generator; probably needs refactoring. if err.errno in (errno.EPERM, errno.EACCES, ERROR_ACCESS_DENIED): raise AccessDenied(self.pid, self._process_name) if err.errno == errno.ESRCH: raise NoSuchProcess(self.pid, self._process_name) raise
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
def wrapper(self, *args, **kwargs): try: return callable(self, *args, **kwargs) except EnvironmentError, err: # ENOENT (no such file or directory) gets raised on open(). # ESRCH (no such process) can get raised on read() if # process is gone in meantime. 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
def resume(self): """Resume process execution.""" # safety measure in case the current process has been killed in # meantime and the kernel reused its PID if not self.is_running(): name = self._platform_impl._process_name raise NoSuchProcess(self.pid, name) # windows if hasattr(self._platform_impl, "resume_process"): self._platform_impl.resume_process() else: # posix self.send_signal(signal.SIGCONT)
def __init__(self, pid): """Create a new Process object, raises NoSuchProcess if the PID does not exist, and ValueError if the parameter is not an integer PID.""" if not isinstance(pid, int): raise ValueError("An integer is required") if not pid_exists(pid): raise NoSuchProcess(pid, None, "no process found with PID %s" % pid) self._pid = pid # platform-specific modules define an PlatformProcess # implementation class self._platform_impl = PlatformProcess(pid) self._last_sys_cpu_times = None self._last_proc_cpu_times = None
def __init__(self, *args, **kwargs): self.__subproc = subprocess.Popen(*args, **kwargs) self._pid = self.__subproc.pid self._gone = False self._platform_impl = _psplatform.Process(self._pid) self._last_sys_cpu_times = None self._last_proc_cpu_times = None try: self.create_time except AccessDenied: pass except NoSuchProcess: raise NoSuchProcess(self._pid, None, "no process found with pid %s" % pid)
def get_children(self): """Return the children of this process as a list of Process objects. """ if not self.is_running(): name = self._platform_impl._process_name raise NoSuchProcess(self.pid, name) retlist = [] for proc in process_iter(): try: if proc.ppid == self.pid: retlist.append(proc) except NoSuchProcess: pass return retlist
def get_memory_maps(self): try: raw = _psutil_mswindows.get_process_memory_maps(self.pid) except OSError: # XXX - can't use wrap_exceptions decorator as we're # returning a generator; probably needs refactoring. err = sys.exc_info()[1] if err.errno in (errno.EPERM, errno.EACCES, ERROR_ACCESS_DENIED): raise AccessDenied(self.pid, self._process_name) if err.errno == errno.ESRCH: raise NoSuchProcess(self.pid, self._process_name) raise else: for addr, perm, path, rss in raw: path = _convert_raw_path(path) addr = hex(addr) yield (addr, perm, path, rss)
def __init__(self, pid): """Create a new Process object for the given pid. Raises NoSuchProcess if pid does not exist. """ self._pid = pid self._gone = False # platform-specific modules define an _psplatform.Process # implementation class self._platform_impl = _psplatform.Process(pid) self._last_sys_cpu_times = None self._last_proc_cpu_times = None # cache creation time for later use in is_running() method try: self.create_time except AccessDenied: pass except NoSuchProcess: raise NoSuchProcess(pid, None, 'no process found with pid %s' % pid)
def get_process_exe(self): if self.pid in (0, 2): raise AccessDenied(self.pid, self._process_name) try: exe = os.readlink("/proc/%s/exe" % self.pid) except (OSError, IOError), err: 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
def get_process_exe(self): # no such thing as "exe" on OS X; it will maybe be determined # later from cmdline[0] if not pid_exists(self.pid): raise NoSuchProcess(self.pid, self._process_name) return ""
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)
def get_process_gid(self): # no such thing as gid on Windows if not pid_exists(self.pid): raise NoSuchProcess(self.pid, self._process_name) return -1