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)
def get_process_cwd(self): if self.pid in (0, 4): raise AccessDenied(self.pid, self._process_name) # return a normalized pathname since the native C function appends # "\\" at the and of the path path = _psutil_mswindows.get_process_cwd(self.pid) return os.path.normpath(path)
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.get('Size:', 0), data.get('Pss:', 0), data.get('Shared_Clean:', 0), data.get('Shared_Dirty:', 0), data.get('Private_Clean:', 0), data.get('Private_Dirty:', 0), data.get('Referenced:', 0), data.get('Anonymous:', 0), data.get('Swap:', 0)) 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 f.close()
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)
def wrapper(self, *args, **kwargs): try: return fun(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 wrapper(self, *args, **kwargs): try: return callable(self, *args, **kwargs) except EnvironmentError: # 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. 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
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
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 send_signal(self, sig): """Send a signal to process pre-emptively checking whether PID has been reused (see signal module constants) . On Windows only SIGTERM is valid and is treated as an alias for kill(). """ 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: self._gone = True 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")