OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # $Id: _psposix.py 800 2010-11-12 21:51:25Z g.rodola $ | 3 # $Id: _psposix.py 1142 2011-10-05 18:45:49Z g.rodola $ |
4 # | 4 # |
| 5 # Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. |
| 6 # Use of this source code is governed by a BSD-style license that can be |
| 7 # found in the LICENSE file. |
5 | 8 |
6 """Routines common to all posix systems.""" | 9 """Routines common to all posix systems.""" |
7 | 10 |
8 import os | 11 import os |
9 import errno | 12 import errno |
10 import subprocess | 13 import subprocess |
11 import psutil | 14 import psutil |
12 import socket | 15 import socket |
13 import re | 16 import re |
14 import sys | 17 import sys |
15 import warnings | 18 import warnings |
| 19 import time |
| 20 import glob |
16 | 21 |
17 try: | 22 from psutil.error import AccessDenied, NoSuchProcess, TimeoutExpired |
18 from collections import namedtuple | 23 from psutil._compat import namedtuple |
19 except ImportError: | 24 from psutil._common import ntuple_diskinfo, usage_percent |
20 from psutil.compat import namedtuple # python < 2.6 | |
21 | |
22 from psutil.error import AccessDenied, NoSuchProcess | |
23 | 25 |
24 | 26 |
25 def pid_exists(pid): | 27 def pid_exists(pid): |
26 """Check whether pid exists in the current process table.""" | 28 """Check whether pid exists in the current process table.""" |
27 if pid < 0: | 29 if pid < 0: |
28 return False | 30 return False |
29 try: | 31 try: |
30 os.kill(pid, 0) | 32 os.kill(pid, 0) |
31 except OSError, e: | 33 except OSError, e: |
32 return e.errno == errno.EPERM | 34 return e.errno == errno.EPERM |
33 else: | 35 else: |
34 return True | 36 return True |
35 | 37 |
| 38 def wait_pid(pid, timeout=None): |
| 39 """Wait for process with pid 'pid' to terminate and return its |
| 40 exit status code as an integer. |
| 41 |
| 42 If pid is not a children of os.getpid() (current process) just |
| 43 waits until the process disappears and return None. |
| 44 |
| 45 If pid does not exist at all return None immediately. |
| 46 |
| 47 Raise TimeoutExpired on timeout expired. |
| 48 """ |
| 49 def check_timeout(): |
| 50 if timeout is not None: |
| 51 if time.time() >= stop_at: |
| 52 raise TimeoutExpired |
| 53 time.sleep(0.001) |
| 54 |
| 55 if timeout is not None: |
| 56 waitcall = lambda: os.waitpid(pid, os.WNOHANG) |
| 57 stop_at = time.time() + timeout |
| 58 else: |
| 59 waitcall = lambda: os.waitpid(pid, 0) |
| 60 |
| 61 while 1: |
| 62 try: |
| 63 retpid, status = waitcall() |
| 64 except OSError, err: |
| 65 if err.errno == errno.EINTR: |
| 66 check_timeout() |
| 67 continue |
| 68 elif err.errno == errno.ECHILD: |
| 69 # not a child of os.getpid(): poll until pid has |
| 70 # disappeared and return None instead |
| 71 while 1: |
| 72 if pid_exists(pid): |
| 73 check_timeout() |
| 74 else: |
| 75 return |
| 76 else: |
| 77 raise |
| 78 else: |
| 79 if retpid == 0: |
| 80 check_timeout() |
| 81 continue |
| 82 # process exited due to a signal; return the integer of |
| 83 # that signal |
| 84 if os.WIFSIGNALED(status): |
| 85 return os.WTERMSIG(status) |
| 86 # process exited using exit(2) system call; return the |
| 87 # integer exit(2) system call has been called with |
| 88 elif os.WIFEXITED(status): |
| 89 return os.WEXITSTATUS(status) |
| 90 else: |
| 91 # should never happen |
| 92 raise RuntimeError("unknown process exit status") |
| 93 |
| 94 def get_disk_usage(path): |
| 95 """Return disk usage associated with path.""" |
| 96 st = os.statvfs(path) |
| 97 free = (st.f_bavail * st.f_frsize) |
| 98 total = (st.f_blocks * st.f_frsize) |
| 99 used = (st.f_blocks - st.f_bfree) * st.f_frsize |
| 100 percent = usage_percent(used, total, _round=1) |
| 101 # NB: the percentage is -5% than what shown by df due to |
| 102 # reserved blocks that we are currently not considering: |
| 103 # http://goo.gl/sWGbH |
| 104 return ntuple_diskinfo(total, used, free, percent) |
| 105 |
| 106 def _get_terminal_map(): |
| 107 ret = {} |
| 108 ls = glob.glob('/dev/tty*') + glob.glob('/dev/pts/*') |
| 109 for name in ls: |
| 110 assert name not in ret |
| 111 ret[os.stat(name).st_rdev] = name |
| 112 return ret |
| 113 |
36 | 114 |
37 class LsofParser: | 115 class LsofParser: |
38 """A wrapper for lsof command line utility. | 116 """A wrapper for lsof command line utility. |
39 Executes lsof in subprocess and parses its output. | 117 Executes lsof in subprocess and parses its output. |
40 """ | 118 """ |
41 socket_table = {'TCP' : socket.SOCK_STREAM, | 119 socket_table = {'TCP' : socket.SOCK_STREAM, |
42 'UDP' : socket.SOCK_DGRAM, | 120 'UDP' : socket.SOCK_DGRAM, |
43 'IPv4' : socket.AF_INET, | 121 'IPv4' : socket.AF_INET, |
44 'IPv6' : socket.AF_INET6} | 122 'IPv6' : socket.AF_INET6} |
45 _openfile_ntuple = namedtuple('openfile', 'path fd') | 123 _openfile_ntuple = namedtuple('openfile', 'path fd') |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 elif family == socket.AF_INET6: | 309 elif family == socket.AF_INET6: |
232 ip = "::" | 310 ip = "::" |
233 # OS X can have some procs e.g. SystemUIServer listening on *:* | 311 # OS X can have some procs e.g. SystemUIServer listening on *:* |
234 else: | 312 else: |
235 raise ValueError("invalid IP %s" %addr) | 313 raise ValueError("invalid IP %s" %addr) |
236 if port == "*": | 314 if port == "*": |
237 return 0 | 315 return 0 |
238 return (ip, int(port)) | 316 return (ip, int(port)) |
239 | 317 |
240 | 318 |
OLD | NEW |