Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(512)

Side by Side Diff: third_party/psutil/psutil/_pslinux.py

Issue 8159001: Update third_party/psutil and fix the licence issue with it. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: remove the suppression and unnecessary files. Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/psutil/psutil/_psbsd.py ('k') | third_party/psutil/psutil/_psmswindows.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # $Id: _pslinux.py 800 2010-11-12 21:51:25Z g.rodola $ 3 # $Id: _pslinux.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 __all__ = ["NUM_CPUS", "TOTAL_PHYMEM", 9 """Linux platform implementation."""
7 "PlatformProcess",
8 "avail_phymem", "used_phymem", "total_virtmem", "avail_virtmem",
9 "used_virtmem", "get_system_cpu_times", "pid_exists", "get_pid_list",
10 "phymem_buffers", "cached_phymem"
11 ]
12
13 10
14 import os 11 import os
15 import errno 12 import errno
16 import socket 13 import socket
17 import struct 14 import struct
18 import sys 15 import sys
19 import base64 16 import base64
17 import re
20 18
21 try: 19 import _psutil_posix
22 from collections import namedtuple 20 import _psutil_linux
23 except ImportError: 21 from psutil import _psposix
24 from psutil.compat import namedtuple # python < 2.6 22 from psutil.error import AccessDenied, NoSuchProcess, TimeoutExpired
23 from psutil._common import *
25 24
26 from psutil import _psposix 25 __extra__all__ = [
27 from psutil.error import AccessDenied, NoSuchProcess 26 "IOPRIO_CLASS_NONE", "IOPRIO_CLASS_RT", "IOPRIO_CLASS_BE",
27 "IOPRIO_CLASS_IDLE",
28 "phymem_buffers", "cached_phymem"]
28 29
29 30
30 def _get_uptime(): 31 def _get_boot_time():
31 """Return system boot time (epoch in seconds)""" 32 """Return system boot time (epoch in seconds)"""
32 f = open('/proc/stat', 'r') 33 f = open('/proc/stat', 'r')
33 for line in f: 34 try:
34 if line.startswith('btime'): 35 for line in f:
35 f.close() 36 if line.startswith('btime'):
36 return float(line.strip().split()[1]) 37 return float(line.strip().split()[1])
38 raise RuntimeError("line not found")
39 finally:
40 f.close()
37 41
38 def _get_num_cpus(): 42 def _get_num_cpus():
39 """Return the number of CPUs on the system""" 43 """Return the number of CPUs on the system"""
40 num = 0 44 num = 0
41 f = open('/proc/cpuinfo', 'r') 45 f = open('/proc/cpuinfo', 'r')
42 for line in f: 46 try:
43 if line.startswith('processor'): 47 lines = f.readlines()
48 finally:
49 f.close()
50 for line in lines:
51 if line.lower().startswith('processor'):
44 num += 1 52 num += 1
45 f.close() 53
54 # unknown format (e.g. amrel/sparc architectures), see:
55 # http://code.google.com/p/psutil/issues/detail?id=200
56 if num == 0:
57 f = open('/proc/stat', 'r')
58 try:
59 lines = f.readlines()
60 finally:
61 f.close()
62 search = re.compile('cpu\d')
63 for line in lines:
64 line = line.split(' ')[0]
65 if search.match(line):
66 num += 1
67
68 if num == 0:
69 raise RuntimeError("can't determine number of CPUs")
46 return num 70 return num
47 71
48 def _get_total_phymem():
49 """Return the total amount of physical memory, in bytes"""
50 f = open('/proc/meminfo', 'r')
51 for line in f:
52 if line.startswith('MemTotal:'):
53 f.close()
54 return int(line.split()[1]) * 1024
55
56 72
57 # Number of clock ticks per second 73 # Number of clock ticks per second
58 _CLOCK_TICKS = os.sysconf(os.sysconf_names["SC_CLK_TCK"]) 74 _CLOCK_TICKS = os.sysconf(os.sysconf_names["SC_CLK_TCK"])
59 _UPTIME = _get_uptime() 75 _TERMINAL_MAP = _psposix._get_terminal_map()
76 BOOT_TIME = _get_boot_time()
60 NUM_CPUS = _get_num_cpus() 77 NUM_CPUS = _get_num_cpus()
61 TOTAL_PHYMEM = _get_total_phymem() 78 # ioprio_* constants http://linux.die.net/man/2/ioprio_get
62 79 IOPRIO_CLASS_NONE = 0
63 del _get_uptime, _get_num_cpus, _get_total_phymem 80 IOPRIO_CLASS_RT = 1
81 IOPRIO_CLASS_BE = 2
82 IOPRIO_CLASS_IDLE = 3
64 83
65 # http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h 84 # http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h
66 _TCP_STATES_TABLE = {"01" : "ESTABLISHED", 85 _TCP_STATES_TABLE = {"01" : "ESTABLISHED",
67 "02" : "SYN_SENT", 86 "02" : "SYN_SENT",
68 "03" : "SYN_RECV", 87 "03" : "SYN_RECV",
69 "04" : "FIN_WAIT1", 88 "04" : "FIN_WAIT1",
70 "05" : "FIN_WAIT2", 89 "05" : "FIN_WAIT2",
71 "06" : "TIME_WAIT", 90 "06" : "TIME_WAIT",
72 "07" : "CLOSE", 91 "07" : "CLOSE",
73 "08" : "CLOSE_WAIT", 92 "08" : "CLOSE_WAIT",
74 "09" : "LAST_ACK", 93 "09" : "LAST_ACK",
75 "0A" : "LISTEN", 94 "0A" : "LISTEN",
76 "0B" : "CLOSING" 95 "0B" : "CLOSING"
77 } 96 }
78 97
79 def avail_phymem(): 98 # --- system memory functions
80 """Return the amount of physical memory available, in bytes."""
81 f = open('/proc/meminfo', 'r')
82 free = None
83 _flag = False
84 for line in f:
85 if line.startswith('MemFree:'):
86 free = int(line.split()[1]) * 1024
87 break
88 f.close()
89 return free
90
91 def used_phymem():
92 """"Return the amount of physical memory used, in bytes."""
93 return (TOTAL_PHYMEM - avail_phymem())
94
95 def total_virtmem():
96 """"Return the total amount of virtual memory, in bytes."""
97 f = open('/proc/meminfo', 'r')
98 for line in f:
99 if line.startswith('SwapTotal:'):
100 f.close()
101 return int(line.split()[1]) * 1024
102
103 def avail_virtmem():
104 """Return the amount of virtual memory currently in use on the
105 system, in bytes.
106 """
107 f = open('/proc/meminfo', 'r')
108 for line in f:
109 if line.startswith('SwapFree:'):
110 f.close()
111 return int(line.split()[1]) * 1024
112
113 def used_virtmem():
114 """Return the amount of used memory currently in use on the system,
115 in bytes.
116 """
117 return total_virtmem() - avail_virtmem()
118 99
119 def cached_phymem(): 100 def cached_phymem():
120 """Return the amount of cached memory on the system, in bytes. 101 """Return the amount of cached memory on the system, in bytes.
121 This reflects the "cached" column of free command line utility. 102 This reflects the "cached" column of free command line utility.
122 """ 103 """
123 f = open('/proc/meminfo', 'r') 104 f = open('/proc/meminfo', 'r')
124 for line in f: 105 try:
125 if line.startswith('Cached:'): 106 for line in f:
126 f.close() 107 if line.startswith('Cached:'):
127 return int(line.split()[1]) * 1024 108 return int(line.split()[1]) * 1024
109 raise RuntimeError("line not found")
110 finally:
111 f.close()
128 112
129 def phymem_buffers(): 113 def phymem_buffers():
130 """Return the amount of physical memory buffers used by the 114 """Return the amount of physical memory buffers used by the
131 kernel in bytes. 115 kernel in bytes.
132 This reflects the "buffers" column of free command line utility. 116 This reflects the "buffers" column of free command line utility.
133 """ 117 """
134 f = open('/proc/meminfo', 'r') 118 f = open('/proc/meminfo', 'r')
135 for line in f: 119 try:
136 if line.startswith('Buffers:'): 120 for line in f:
137 f.close() 121 if line.startswith('Buffers:'):
138 return int(line.split()[1]) * 1024 122 return int(line.split()[1]) * 1024
123 raise RuntimeError("line not found")
124 finally:
125 f.close()
126
127 def phymem_usage():
128 # total, used and free values are matched against free cmdline utility
129 # the percentage matches top/htop and gnome-system-monitor
130 f = open('/proc/meminfo', 'r')
131 try:
132 total = free = buffers = cached = None
133 for line in f:
134 if line.startswith('MemTotal:'):
135 total = int(line.split()[1]) * 1024
136 elif line.startswith('MemFree:'):
137 free = int(line.split()[1]) * 1024
138 elif line.startswith('Buffers:'):
139 buffers = int(line.split()[1]) * 1024
140 elif line.startswith('Cached:'):
141 cached = int(line.split()[1]) * 1024
142 break
143 used = total - free
144 percent = usage_percent(total - (free + buffers + cached), total,
145 _round=1)
146 return ntuple_sysmeminfo(total, used, free, percent)
147 finally:
148 f.close()
149
150
151 def virtmem_usage():
152 f = open('/proc/meminfo', 'r')
153 try:
154 total = free = None
155 for line in f:
156 if line.startswith('SwapTotal:'):
157 total = int(line.split()[1]) * 1024
158 elif line.startswith('SwapFree:'):
159 free = int(line.split()[1]) * 1024
160 if total is not None and free is not None:
161 break
162 assert total is not None and free is not None
163 used = total - free
164 percent = usage_percent(used, total, _round=1)
165 return ntuple_sysmeminfo(total, used, free, percent)
166 finally:
167 f.close()
168
169
170 # --- system CPU functions
139 171
140 def get_system_cpu_times(): 172 def get_system_cpu_times():
141 """Return a dict representing the following CPU times: 173 """Return a named tuple representing the following CPU times:
142 user, nice, system, idle, iowait, irq, softirq. 174 user, nice, system, idle, iowait, irq, softirq.
143 """ 175 """
144 f = open('/proc/stat', 'r') 176 f = open('/proc/stat', 'r')
145 values = f.readline().split() 177 try:
146 f.close() 178 values = f.readline().split()
179 finally:
180 f.close()
147 181
148 values = values[1:8] 182 values = values[1:8]
149 values = tuple([float(x) / _CLOCK_TICKS for x in values]) 183 values = tuple([float(x) / _CLOCK_TICKS for x in values])
150 184 return ntuple_sys_cputimes(*values[:7])
151 return dict(user=values[0], nice=values[1], system=values[2], idle=values[3] , 185
152 iowait=values[4], irq=values[5], softirq=values[6]) 186 def get_system_per_cpu_times():
187 """Return a list of namedtuple representing the CPU times
188 for every CPU available on the system.
189 """
190 cpus = []
191 f = open('/proc/stat', 'r')
192 # get rid of the first line who refers to system wide CPU stats
193 try:
194 f.readline()
195 for line in f.readlines():
196 if line.startswith('cpu'):
197 values = line.split()[1:8]
198 values = tuple([float(x) / _CLOCK_TICKS for x in values])
199 entry = ntuple_sys_cputimes(*values[:7])
200 cpus.append(entry)
201 return cpus
202 finally:
203 f.close()
204
205
206 # --- system disk functions
207
208 def disk_partitions(all=False):
209 """Return mounted disk partitions as a list of nameduples"""
210 phydevs = []
211 f = open("/proc/filesystems", "r")
212 try:
213 for line in f:
214 if not line.startswith("nodev"):
215 phydevs.append(line.strip())
216 finally:
217 f.close()
218
219 retlist = []
220 partitions = _psutil_linux.get_disk_partitions()
221 for partition in partitions:
222 device, mountpoint, fstype = partition
223 if device == 'none':
224 device = ''
225 if not all:
226 if device == '' or fstype not in phydevs:
227 continue
228 ntuple = ntuple_partition(device, mountpoint, fstype)
229 retlist.append(ntuple)
230 return retlist
231
232 get_disk_usage = _psposix.get_disk_usage
233
234 # --- process functions
153 235
154 def get_pid_list(): 236 def get_pid_list():
155 """Returns a list of PIDs currently running on the system.""" 237 """Returns a list of PIDs currently running on the system."""
156 pids = [int(x) for x in os.listdir('/proc') if x.isdigit()] 238 pids = [int(x) for x in os.listdir('/proc') if x.isdigit()]
157 # special case for 0 (kernel process) PID
158 pids.insert(0, 0)
159 return pids 239 return pids
160 240
161 def pid_exists(pid): 241 def pid_exists(pid):
162 """Check For the existence of a unix pid.""" 242 """Check For the existence of a unix pid."""
163 return _psposix.pid_exists(pid) 243 return _psposix.pid_exists(pid)
164 244
245 def network_io_counters():
246 """Return network I/O statistics for every network interface
247 installed on the system as a dict of raw tuples.
248 """
249 f = open("/proc/net/dev", "r")
250 try:
251 lines = f.readlines()
252 finally:
253 f.close()
254
255 retdict = {}
256 for line in lines[2:]:
257 fields = line.split()
258 name = fields[0][:-1]
259 bytes_recv = int(fields[1])
260 packets_recv = int(fields[2])
261 bytes_sent = int(fields[9])
262 packets_sent = int(fields[10])
263 retdict[name] = (bytes_sent, bytes_recv, packets_sent, packets_recv)
264 return retdict
265
266 def disk_io_counters():
267 """Return disk I/O statistics for every disk installed on the
268 system as a dict of raw tuples.
269 """
270 # man iostat states that sectors are equivalent with blocks and
271 # have a size of 512 bytes since 2.4 kernels. This value is
272 # needed to calculate the amount of disk I/O in bytes.
273 SECTOR_SIZE = 512
274
275 # determine partitions we want to look for
276 partitions = []
277 f = open("/proc/partitions", "r")
278 try:
279 lines = f.readlines()[2:]
280 finally:
281 f.close()
282 for line in lines:
283 _, _, _, name = line.split()
284 if name[-1].isdigit():
285 partitions.append(name)
286 #
287 retdict = {}
288 f = open("/proc/diskstats", "r")
289 try:
290 lines = f.readlines()
291 finally:
292 f.close()
293 for line in lines:
294 _, _, name, reads, _, rbytes, rtime, writes, _, wbytes, wtime = \
295 line.split()[:11]
296 if name in partitions:
297 rbytes = int(rbytes) * SECTOR_SIZE
298 wbytes = int(wbytes) * SECTOR_SIZE
299 reads = int(reads)
300 writes = int(writes)
301 # TODO: times are expressed in milliseconds while OSX/BSD has
302 # these expressed in nanoseconds; figure this out.
303 rtime = int(rtime)
304 wtime = int(wtime)
305 retdict[name] = (reads, writes, rbytes, wbytes, rtime, wtime)
306 return retdict
307
308
309 # taken from /fs/proc/array.c
310 _status_map = {"R" : STATUS_RUNNING,
311 "S" : STATUS_SLEEPING,
312 "D" : STATUS_DISK_SLEEP,
313 "T" : STATUS_STOPPED,
314 "t" : STATUS_TRACING_STOP,
315 "Z" : STATUS_ZOMBIE,
316 "X" : STATUS_DEAD,
317 "x" : STATUS_DEAD,
318 "K" : STATUS_WAKE_KILL,
319 "W" : STATUS_WAKING}
165 320
166 # --- decorators 321 # --- decorators
167 322
168 def wrap_exceptions(callable): 323 def wrap_exceptions(callable):
169 """Call callable into a try/except clause and translate ENOENT, 324 """Call callable into a try/except clause and translate ENOENT,
170 EACCES and EPERM in NoSuchProcess or AccessDenied exceptions. 325 EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
171 """ 326 """
172 def wrapper(self, *args, **kwargs): 327 def wrapper(self, *args, **kwargs):
173 try: 328 try:
174 return callable(self, *args, **kwargs) 329 return callable(self, *args, **kwargs)
175 except (OSError, IOError), err: 330 except (OSError, IOError), err:
176 if err.errno == errno.ENOENT: # no such file or directory 331 # ENOENT (no such file or directory) gets raised on open().
332 # ESRCH (no such process) can get raised on read() if
333 # process is gone in meantime.
334 if err.errno in (errno.ENOENT, errno.ESRCH):
177 raise NoSuchProcess(self.pid, self._process_name) 335 raise NoSuchProcess(self.pid, self._process_name)
178 if err.errno in (errno.EPERM, errno.EACCES): 336 if err.errno in (errno.EPERM, errno.EACCES):
179 raise AccessDenied(self.pid, self._process_name) 337 raise AccessDenied(self.pid, self._process_name)
180 raise 338 raise
181 return wrapper 339 return wrapper
182 340
183 341
184 class LinuxProcess(object): 342 class Process(object):
185 """Linux process implementation.""" 343 """Linux process implementation."""
186 344
187 _meminfo_ntuple = namedtuple('meminfo', 'rss vms')
188 _cputimes_ntuple = namedtuple('cputimes', 'user system')
189 _openfile_ntuple = namedtuple('openfile', 'path fd')
190 _connection_ntuple = namedtuple('connection', 'fd family type local_address '
191 'remote_address status')
192 __slots__ = ["pid", "_process_name"] 345 __slots__ = ["pid", "_process_name"]
193 346
194 def __init__(self, pid): 347 def __init__(self, pid):
195 self.pid = pid 348 self.pid = pid
196 self._process_name = None 349 self._process_name = None
197 350
198 @wrap_exceptions 351 @wrap_exceptions
199 def get_process_name(self): 352 def get_process_name(self):
200 if self.pid == 0:
201 return 'sched' # special case for kernel process
202 f = open("/proc/%s/stat" % self.pid) 353 f = open("/proc/%s/stat" % self.pid)
203 try: 354 try:
204 name = f.read().split(' ')[1].replace('(', '').replace(')', '') 355 name = f.read().split(' ')[1].replace('(', '').replace(')', '')
205 finally: 356 finally:
206 f.close() 357 f.close()
207 # XXX - gets changed later and probably needs refactoring 358 # XXX - gets changed later and probably needs refactoring
208 return name 359 return name
209 360
210 def get_process_exe(self): 361 def get_process_exe(self):
211 if self.pid in (0, 2): 362 if self.pid in (0, 2):
212 return "" # special case for kernel processes 363 raise AccessDenied(self.pid, self._process_name)
213 try: 364 try:
214 exe = os.readlink("/proc/%s/exe" % self.pid) 365 exe = os.readlink("/proc/%s/exe" % self.pid)
215 except (OSError, IOError), err: 366 except (OSError, IOError), err:
216 if err.errno == errno.ENOENT: 367 if err.errno == errno.ENOENT:
217 # no such file error; might be raised also if the 368 # no such file error; might be raised also if the
218 # path actually exists for system processes with 369 # path actually exists for system processes with
219 # low pids (about 0-20) 370 # low pids (about 0-20)
220 if os.path.lexists("/proc/%s/exe" % self.pid): 371 if os.path.lexists("/proc/%s/exe" % self.pid):
221 return "" 372 return ""
222 else: 373 else:
223 # ok, it is a process which has gone away 374 # ok, it is a process which has gone away
224 raise NoSuchProcess(self.pid, self._process_name) 375 raise NoSuchProcess(self.pid, self._process_name)
225 if err.errno in (errno.EPERM, errno.EACCES): 376 if err.errno in (errno.EPERM, errno.EACCES):
226 raise AccessDenied(self.pid, self._process_name) 377 raise AccessDenied(self.pid, self._process_name)
227 raise 378 raise
228 379
380 # readlink() might return paths containing null bytes causing
381 # problems when used with other fs-related functions (os.*,
382 # open(), ...)
383 exe = exe.replace('\x00', '')
229 # It seems symlinks can point to a deleted/invalid location 384 # It seems symlinks can point to a deleted/invalid location
230 # (this usually happens with "pulseaudio" process). 385 # (this usually happens with "pulseaudio" process).
231 # However, if we had permissions to execute readlink() it's 386 # However, if we had permissions to execute readlink() it's
232 # likely that we'll be able to figure out exe from argv[0] 387 # likely that we'll be able to figure out exe from argv[0]
233 # later on. 388 # later on.
234 if exe.endswith(" (deleted)") and not os.path.isfile(exe): 389 if exe.endswith(" (deleted)") and not os.path.isfile(exe):
235 return "" 390 return ""
236 return exe 391 return exe
237 392
238 @wrap_exceptions 393 @wrap_exceptions
239 def get_process_cmdline(self): 394 def get_process_cmdline(self):
240 if self.pid == 0:
241 return [] # special case for kernel process
242 f = open("/proc/%s/cmdline" % self.pid) 395 f = open("/proc/%s/cmdline" % self.pid)
243 try: 396 try:
244 # return the args as a list 397 # return the args as a list
245 return [x for x in f.read().split('\x00') if x] 398 return [x for x in f.read().split('\x00') if x]
246 finally: 399 finally:
247 f.close() 400 f.close()
248 401
249 @wrap_exceptions 402 @wrap_exceptions
403 def get_process_terminal(self):
404 f = open("/proc/%s/stat" % self.pid)
405 try:
406 tty_nr = int(f.read().split(' ')[6])
407 finally:
408 f.close()
409 try:
410 return _TERMINAL_MAP[tty_nr]
411 except KeyError:
412 return None
413
414 @wrap_exceptions
415 def get_process_io_counters(self):
416 f = open("/proc/%s/io" % self.pid)
417 try:
418 for line in f:
419 if line.startswith("rchar"):
420 read_count = int(line.split()[1])
421 elif line.startswith("wchar"):
422 write_count = int(line.split()[1])
423 elif line.startswith("read_bytes"):
424 read_bytes = int(line.split()[1])
425 elif line.startswith("write_bytes"):
426 write_bytes = int(line.split()[1])
427 return ntuple_io(read_count, write_count, read_bytes, write_bytes)
428 finally:
429 f.close()
430
431 @wrap_exceptions
250 def get_cpu_times(self): 432 def get_cpu_times(self):
251 # special case for 0 (kernel process) PID
252 if self.pid == 0:
253 return self._cputimes_ntuple(0.0, 0.0)
254 f = open("/proc/%s/stat" % self.pid) 433 f = open("/proc/%s/stat" % self.pid)
255 st = f.read().strip() 434 try:
256 f.close() 435 st = f.read().strip()
436 finally:
437 f.close()
257 # ignore the first two values ("pid (exe)") 438 # ignore the first two values ("pid (exe)")
258 st = st[st.find(')') + 2:] 439 st = st[st.find(')') + 2:]
259 values = st.split(' ') 440 values = st.split(' ')
260 utime = float(values[11]) / _CLOCK_TICKS 441 utime = float(values[11]) / _CLOCK_TICKS
261 stime = float(values[12]) / _CLOCK_TICKS 442 stime = float(values[12]) / _CLOCK_TICKS
262 return self._cputimes_ntuple(utime, stime) 443 return ntuple_cputimes(utime, stime)
444
445 @wrap_exceptions
446 def process_wait(self, timeout=None):
447 try:
448 return _psposix.wait_pid(self.pid, timeout)
449 except TimeoutExpired:
450 raise TimeoutExpired(self.pid, self._process_name)
263 451
264 @wrap_exceptions 452 @wrap_exceptions
265 def get_process_create_time(self): 453 def get_process_create_time(self):
266 # special case for 0 (kernel processes) PID; return system uptime
267 if self.pid == 0:
268 return _UPTIME
269 f = open("/proc/%s/stat" % self.pid) 454 f = open("/proc/%s/stat" % self.pid)
270 st = f.read().strip() 455 try:
271 f.close() 456 st = f.read().strip()
457 finally:
458 f.close()
272 # ignore the first two values ("pid (exe)") 459 # ignore the first two values ("pid (exe)")
273 st = st[st.find(')') + 2:] 460 st = st[st.find(')') + 2:]
274 values = st.split(' ') 461 values = st.split(' ')
275 # According to documentation, starttime is in field 21 and the 462 # According to documentation, starttime is in field 21 and the
276 # unit is jiffies (clock ticks). 463 # unit is jiffies (clock ticks).
277 # We first divide it for clock ticks and then add uptime returning 464 # We first divide it for clock ticks and then add uptime returning
278 # seconds since the epoch, in UTC. 465 # seconds since the epoch, in UTC.
279 starttime = (float(values[19]) / _CLOCK_TICKS) + _UPTIME 466 starttime = (float(values[19]) / _CLOCK_TICKS) + BOOT_TIME
280 return starttime 467 return starttime
281 468
282 @wrap_exceptions 469 @wrap_exceptions
283 def get_memory_info(self): 470 def get_memory_info(self):
284 # special case for 0 (kernel processes) PID
285 if self.pid == 0:
286 return self._meminfo_ntuple(0, 0)
287 f = open("/proc/%s/status" % self.pid) 471 f = open("/proc/%s/status" % self.pid)
288 virtual_size = 0 472 try:
289 resident_size = 0 473 virtual_size = 0
290 _flag = False 474 resident_size = 0
291 for line in f: 475 _flag = False
292 if (not _flag) and line.startswith("VmSize:"): 476 for line in f:
293 virtual_size = int(line.split()[1]) * 1024 477 if (not _flag) and line.startswith("VmSize:"):
294 _flag = True 478 virtual_size = int(line.split()[1]) * 1024
295 elif line.startswith("VmRSS"): 479 _flag = True
296 resident_size = int(line.split()[1]) * 1024 480 elif line.startswith("VmRSS"):
297 break 481 resident_size = int(line.split()[1]) * 1024
298 f.close() 482 break
299 return self._meminfo_ntuple(resident_size, virtual_size) 483 return ntuple_meminfo(resident_size, virtual_size)
484 finally:
485 f.close()
300 486
301 @wrap_exceptions 487 @wrap_exceptions
302 def get_process_cwd(self): 488 def get_process_cwd(self):
303 if self.pid == 0: 489 # readlink() might return paths containing null bytes causing
304 return '' 490 # problems when used with other fs-related functions (os.*,
305 return os.readlink("/proc/%s/cwd" % self.pid) 491 # open(), ...)
492 path = os.readlink("/proc/%s/cwd" % self.pid)
493 return path.replace('\x00', '')
306 494
307 @wrap_exceptions 495 @wrap_exceptions
308 def get_process_num_threads(self): 496 def get_process_num_threads(self):
309 if self.pid == 0:
310 return 0
311 f = open("/proc/%s/status" % self.pid) 497 f = open("/proc/%s/status" % self.pid)
312 for line in f: 498 try:
313 if line.startswith("Threads:"): 499 for line in f:
500 if line.startswith("Threads:"):
501 return int(line.split()[1])
502 raise RuntimeError("line not found")
503 finally:
504 f.close()
505
506 @wrap_exceptions
507 def get_process_threads(self):
508 thread_ids = os.listdir("/proc/%s/task" % self.pid)
509 thread_ids.sort()
510 retlist = []
511 for thread_id in thread_ids:
512 try:
513 f = open("/proc/%s/task/%s/stat" % (self.pid, thread_id))
514 except (OSError, IOError), err:
515 if err.errno == errno.ENOENT:
516 # no such file or directory; it means thread
517 # disappeared on us
518 continue
519 raise
520 try:
521 st = f.read().strip()
522 finally:
314 f.close() 523 f.close()
315 return int(line.split()[1]) 524 # ignore the first two values ("pid (exe)")
525 st = st[st.find(')') + 2:]
526 values = st.split(' ')
527 utime = float(values[11]) / _CLOCK_TICKS
528 stime = float(values[12]) / _CLOCK_TICKS
529 ntuple = ntuple_thread(int(thread_id), utime, stime)
530 retlist.append(ntuple)
531 return retlist
532
533 @wrap_exceptions
534 def get_process_nice(self):
535 #f = open('/proc/%s/stat' % self.pid, 'r')
536 #try:
537 # data = f.read()
538 # return int(data.split()[18])
539 #finally:
540 # f.close()
541
542 # Use C implementation
543 return _psutil_posix.getpriority(self.pid)
544
545 @wrap_exceptions
546 def set_process_nice(self, value):
547 return _psutil_posix.setpriority(self.pid, value)
548
549 # only starting from kernel 2.6.13
550 if hasattr(_psutil_linux, "ioprio_get"):
551
552 @wrap_exceptions
553 def get_process_ionice(self):
554 ioclass, value = _psutil_linux.ioprio_get(self.pid)
555 return ntuple_ionice(ioclass, value)
556
557 @wrap_exceptions
558 def set_process_ionice(self, ioclass, value):
559 if ioclass in (IOPRIO_CLASS_NONE, None):
560 if value:
561 raise ValueError("can't specify value with IOPRIO_CLASS_NONE ")
562 ioclass = IOPRIO_CLASS_NONE
563 value = 0
564 if ioclass in (IOPRIO_CLASS_RT, IOPRIO_CLASS_BE):
565 if value is None:
566 value = 4
567 elif ioclass == IOPRIO_CLASS_IDLE:
568 if value:
569 raise ValueError("can't specify value with IOPRIO_CLASS_IDLE ")
570 value = 0
571 else:
572 value = 0
573 if not 0 <= value <= 8:
574 raise ValueError("value argument range expected is between 0 and 8")
575 return _psutil_linux.ioprio_set(self.pid, ioclass, value)
576
577 @wrap_exceptions
578 def get_process_status(self):
579 f = open("/proc/%s/status" % self.pid)
580 try:
581 for line in f:
582 if line.startswith("State:"):
583 letter = line.split()[1]
584 if letter in _status_map:
585 return _status_map[letter]
586 return constant(-1, '?')
587 finally:
588 f.close()
316 589
317 @wrap_exceptions 590 @wrap_exceptions
318 def get_open_files(self): 591 def get_open_files(self):
319 retlist = [] 592 retlist = []
320 files = os.listdir("/proc/%s/fd" % self.pid) 593 files = os.listdir("/proc/%s/fd" % self.pid)
321 for fd in files: 594 for fd in files:
322 file = "/proc/%s/fd/%s" % (self.pid, fd) 595 file = "/proc/%s/fd/%s" % (self.pid, fd)
323 if os.path.islink(file): 596 if os.path.islink(file):
324 file = os.readlink(file) 597 file = os.readlink(file)
325 if file.startswith("socket:["): 598 if file.startswith("socket:["):
326 continue 599 continue
327 if file.startswith("pipe:["): 600 if file.startswith("pipe:["):
328 continue 601 continue
329 if file == "[]": 602 if file == "[]":
330 continue 603 continue
331 if os.path.isfile(file) and not file in retlist: 604 if os.path.isfile(file) and not file in retlist:
332 ntuple = self._openfile_ntuple(file, int(fd)) 605 ntuple = ntuple_openfile(file, int(fd))
333 retlist.append(ntuple) 606 retlist.append(ntuple)
334 return retlist 607 return retlist
335 608
336 # --- lsof implementation
337 #
338 # def get_open_files(self):
339 # lsof = _psposix.LsofParser(self.pid, self._process_name)
340 # return lsof.get_process_open_files()
341
342 @wrap_exceptions 609 @wrap_exceptions
343 def get_connections(self): 610 def get_connections(self):
344 if self.pid == 0:
345 return []
346 inodes = {} 611 inodes = {}
347 # os.listdir() is gonna raise a lot of access denied 612 # os.listdir() is gonna raise a lot of access denied
348 # exceptions in case of unprivileged user; that's fine: 613 # exceptions in case of unprivileged user; that's fine:
349 # lsof does the same so it's unlikely that we can to better. 614 # lsof does the same so it's unlikely that we can to better.
350 for fd in os.listdir("/proc/%s/fd" % self.pid): 615 for fd in os.listdir("/proc/%s/fd" % self.pid):
351 try: 616 try:
352 inode = os.readlink("/proc/%s/fd/%s" % (self.pid, fd)) 617 inode = os.readlink("/proc/%s/fd/%s" % (self.pid, fd))
353 except OSError: 618 except OSError:
354 continue 619 continue
355 if inode.startswith('socket:['): 620 if inode.startswith('socket:['):
356 # the process is using a socket 621 # the process is using a socket
357 inode = inode[8:][:-1] 622 inode = inode[8:][:-1]
358 inodes[inode] = fd 623 inodes[inode] = fd
359 624
360 if not inodes: 625 if not inodes:
361 # no connections for this process 626 # no connections for this process
362 return [] 627 return []
363 628
364 def process(file, family, _type): 629 def process(file, family, _type):
365 retlist = [] 630 retlist = []
366 f = open(file) 631 f = open(file)
367 f.readline() # skip the first line 632 try:
368 for line in f: 633 f.readline() # skip the first line
369 _, laddr, raddr, status, _, _, _, _, _, inode = line.split()[:10 ] 634 for line in f:
370 if inode in inodes: 635 _, laddr, raddr, status, _, _, _, _, _, inode = \
371 laddr = self._decode_address(laddr, family) 636 line.split()[:10]
372 raddr = self._decode_address(raddr, family) 637 if inode in inodes:
373 if _type == socket.SOCK_STREAM: 638 laddr = self._decode_address(laddr, family)
374 status = _TCP_STATES_TABLE[status] 639 raddr = self._decode_address(raddr, family)
375 else: 640 if _type == socket.SOCK_STREAM:
376 status = "" 641 status = _TCP_STATES_TABLE[status]
377 fd = int(inodes[inode]) 642 else:
378 conn = self._connection_ntuple(fd, family, _type, laddr, 643 status = ""
379 raddr, status) 644 fd = int(inodes[inode])
380 retlist.append(conn) 645 conn = ntuple_connection(fd, family, _type, laddr,
381 f.close() 646 raddr, status)
382 return retlist 647 retlist.append(conn)
648 return retlist
649 finally:
650 f.close()
383 651
384 tcp4 = process("/proc/net/tcp", socket.AF_INET, socket.SOCK_STREAM) 652 tcp4 = process("/proc/net/tcp", socket.AF_INET, socket.SOCK_STREAM)
385 tcp6 = process("/proc/net/tcp6", socket.AF_INET6, socket.SOCK_STREAM)
386 udp4 = process("/proc/net/udp", socket.AF_INET, socket.SOCK_DGRAM) 653 udp4 = process("/proc/net/udp", socket.AF_INET, socket.SOCK_DGRAM)
387 udp6 = process("/proc/net/udp6", socket.AF_INET6, socket.SOCK_DGRAM) 654 try:
655 tcp6 = process("/proc/net/tcp6", socket.AF_INET6, socket.SOCK_STREAM )
656 udp6 = process("/proc/net/udp6", socket.AF_INET6, socket.SOCK_DGRAM)
657 except IOError, err:
658 if err.errno == errno.ENOENT:
659 # IPv6 is not supported on this platform
660 tcp6 = udp6 = []
661 else:
662 raise
388 return tcp4 + tcp6 + udp4 + udp6 663 return tcp4 + tcp6 + udp4 + udp6
389 664
390 # --- lsof implementation 665 # --- lsof implementation
391 # 666 #
392 # def get_connections(self): 667 # def get_connections(self):
393 # lsof = _psposix.LsofParser(self.pid, self._process_name) 668 # lsof = _psposix.LsofParser(self.pid, self._process_name)
394 # return lsof.get_process_connections() 669 # return lsof.get_process_connections()
395 670
396 @wrap_exceptions 671 @wrap_exceptions
397 def get_process_ppid(self): 672 def get_process_ppid(self):
398 if self.pid == 0:
399 return 0
400 f = open("/proc/%s/status" % self.pid) 673 f = open("/proc/%s/status" % self.pid)
401 for line in f: 674 try:
402 if line.startswith("PPid:"): 675 for line in f:
403 # PPid: nnnn 676 if line.startswith("PPid:"):
404 f.close() 677 # PPid: nnnn
405 return int(line.split()[1]) 678 return int(line.split()[1])
679 raise RuntimeError("line not found")
680 finally:
681 f.close()
406 682
407 @wrap_exceptions 683 @wrap_exceptions
408 def get_process_uid(self): 684 def get_process_uids(self):
409 if self.pid == 0:
410 return 0
411 f = open("/proc/%s/status" % self.pid) 685 f = open("/proc/%s/status" % self.pid)
412 for line in f: 686 try:
413 if line.startswith('Uid:'): 687 for line in f:
414 # Uid line provides 4 values which stand for real, 688 if line.startswith('Uid:'):
415 # effective, saved set, and file system UIDs. 689 _, real, effective, saved, fs = line.split()
416 # We want to provide real UID only. 690 return ntuple_uids(int(real), int(effective), int(saved))
417 f.close() 691 raise RuntimeError("line not found")
418 return int(line.split()[1]) 692 finally:
693 f.close()
419 694
420 @wrap_exceptions 695 @wrap_exceptions
421 def get_process_gid(self): 696 def get_process_gids(self):
422 if self.pid == 0:
423 return 0
424 f = open("/proc/%s/status" % self.pid) 697 f = open("/proc/%s/status" % self.pid)
425 for line in f: 698 try:
426 if line.startswith('Gid:'): 699 for line in f:
427 # Uid line provides 4 values which stand for real, 700 if line.startswith('Gid:'):
428 # effective, saved set, and file system GIDs. 701 _, real, effective, saved, fs = line.split()
429 # We want to provide real GID only. 702 return ntuple_gids(int(real), int(effective), int(saved))
430 f.close() 703 raise RuntimeError("line not found")
431 return int(line.split()[1]) 704 finally:
705 f.close()
432 706
433 @staticmethod 707 @staticmethod
434 def _decode_address(addr, family): 708 def _decode_address(addr, family):
435 """Accept an "ip:port" address as displayed in /proc/net/* 709 """Accept an "ip:port" address as displayed in /proc/net/*
436 and convert it into a human readable form, like: 710 and convert it into a human readable form, like:
437 711
438 "0500000A:0016" -> ("10.0.0.5", 22) 712 "0500000A:0016" -> ("10.0.0.5", 22)
439 "0000000000000000FFFF00000100007F:9E49" -> ("::ffff:127.0.0.1", 40521) 713 "0000000000000000FFFF00000100007F:9E49" -> ("::ffff:127.0.0.1", 40521)
440 714
441 The IPv4 address portion is a little-endian four-byte hexadecimal 715 The IP address portion is a little or big endian four-byte
442 number; that is, the least significant byte is listed first, 716 hexadecimal number; that is, the least significant byte is listed
443 so we need to reverse the order of the bytes to convert it 717 first, so we need to reverse the order of the bytes to convert it
444 to an IP address. 718 to an IP address.
445 The port is represented as a two-byte hexadecimal number. 719 The port is represented as a two-byte hexadecimal number.
446 720
447 Reference: 721 Reference:
448 http://linuxdevcenter.com/pub/a/linux/2000/11/16/LinuxAdmin.html 722 http://linuxdevcenter.com/pub/a/linux/2000/11/16/LinuxAdmin.html
449 """ 723 """
450 ip, port = addr.split(':') 724 ip, port = addr.split(':')
451 port = int(port, 16) 725 port = int(port, 16)
452 if sys.version_info >= (3,): 726 if sys.version_info >= (3,):
453 ip = ip.encode('ascii') 727 ip = ip.encode('ascii')
454 # this usually refers to a local socket in listen mode with 728 # this usually refers to a local socket in listen mode with
455 # no end-points connected 729 # no end-points connected
456 if not port: 730 if not port:
457 return () 731 return ()
458 if family == socket.AF_INET: 732 if family == socket.AF_INET:
459 ip = socket.inet_ntop(family, base64.b16decode(ip)[::-1]) 733 # see: http://code.google.com/p/psutil/issues/detail?id=201
734 if sys.byteorder == 'little':
735 ip = socket.inet_ntop(family, base64.b16decode(ip)[::-1])
736 else:
737 ip = socket.inet_ntop(family, base64.b16decode(ip))
460 else: # IPv6 738 else: # IPv6
461 # old version - let's keep it, just in case... 739 # old version - let's keep it, just in case...
462 #ip = ip.decode('hex') 740 #ip = ip.decode('hex')
463 #return socket.inet_ntop(socket.AF_INET6, 741 #return socket.inet_ntop(socket.AF_INET6,
464 # ''.join(ip[i:i+4][::-1] for i in xrange(0, 16, 4))) 742 # ''.join(ip[i:i+4][::-1] for i in xrange(0, 16, 4)))
465 ip = base64.b16decode(ip) 743 ip = base64.b16decode(ip)
466 ip = socket.inet_ntop(socket.AF_INET6, 744 # see: http://code.google.com/p/psutil/issues/detail?id=201
745 if sys.byteorder == 'little':
746 ip = socket.inet_ntop(socket.AF_INET6,
467 struct.pack('>4I', *struct.unpack('<4I', ip))) 747 struct.pack('>4I', *struct.unpack('<4I', ip)))
748 else:
749 ip = socket.inet_ntop(socket.AF_INET6,
750 struct.pack('<4I', *struct.unpack('<4I', ip)))
468 return (ip, port) 751 return (ip, port)
469
470 PlatformProcess = LinuxProcess
471
OLDNEW
« no previous file with comments | « third_party/psutil/psutil/_psbsd.py ('k') | third_party/psutil/psutil/_psmswindows.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698