mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1196253 - update in-tree psutil to 3.1.1. r=gps
This commit is contained in:
parent
221a5e5c4b
commit
3df7576e09
@ -255,9 +255,56 @@ I: 492
|
||||
|
||||
N: Jeff Tang
|
||||
W: https://github.com/mrjefftang
|
||||
I: 340, 529
|
||||
I: 340, 529, 616, 653, 654
|
||||
|
||||
N: Yaolong Huang
|
||||
E: airekans@gmail.com
|
||||
W: http://airekans.github.io/
|
||||
I: 530
|
||||
|
||||
N: Anders Chrigström
|
||||
W: https://github.com/anders-chrigstrom
|
||||
I: 496
|
||||
|
||||
N: spacewander
|
||||
E: spacewanderlzx@gmail.com
|
||||
I: 561
|
||||
|
||||
N: Sylvain Mouquet
|
||||
E: sylvain.mouquet@gmail.com
|
||||
I: 565
|
||||
|
||||
N: karthikrev
|
||||
I: 568
|
||||
|
||||
N: Bruno Binet
|
||||
E: bruno.binet@gmail.com
|
||||
I: 572
|
||||
|
||||
N: Gabi Davar
|
||||
C: Israel
|
||||
W: https://github.com/mindw
|
||||
I: 578, 581, 587
|
||||
|
||||
N: spacewanderlzx
|
||||
C: Guangzhou,China
|
||||
E: spacewanderlzx@gmail.com
|
||||
I: 555
|
||||
|
||||
N: Fabian Groffen
|
||||
I: 611, 618
|
||||
|
||||
N: desbma
|
||||
W: https://github.com/desbma
|
||||
C: France
|
||||
I: 628
|
||||
|
||||
N: John Burnett
|
||||
W: http://www.johnburnett.com/
|
||||
C: Irvine, CA, US
|
||||
I: 614
|
||||
|
||||
N: Árni Már Jónsson
|
||||
E: Reykjavik, Iceland
|
||||
E: https://github.com/arnimarj
|
||||
I: 634
|
||||
|
@ -1,10 +1,143 @@
|
||||
Bug tracker at https://github.com/giampaolo/psutil/issues
|
||||
|
||||
2.1.3 2014-09-26
|
||||
================
|
||||
3.1.1 - 2015-07-15
|
||||
==================
|
||||
|
||||
**Bug fixes**
|
||||
|
||||
- #645: [Linux] psutil.cpu_times_percent() may produce negative results.
|
||||
- #656: 'from psutil import *' does not work.
|
||||
|
||||
|
||||
3.1.0 - 2015-07-15
|
||||
==================
|
||||
|
||||
**Enhancements**
|
||||
|
||||
- #534: [Linux] disk_partitions() added support for ZFS filesystems.
|
||||
- #646: continuous tests integration for Windows with
|
||||
https://ci.appveyor.com/project/giampaolo/psutil.
|
||||
- #647: new dev guide:
|
||||
https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst
|
||||
- #651: continuous code quality test integration with
|
||||
https://scrutinizer-ci.com/g/giampaolo/psutil/
|
||||
|
||||
**Bug fixes**
|
||||
|
||||
- #340: [Windows] Process.open_files() no longer hangs. Instead it uses a
|
||||
thred which times out and skips the file handle in case it's taking too long
|
||||
to be retrieved. (patch by Jeff Tang, PR #597)
|
||||
- #627: [Windows] Process.name() no longer raises AccessDenied for pids owned
|
||||
by another user.
|
||||
- #636: [Windows] Process.memory_info() raise AccessDenied.
|
||||
- #637: [UNIX] raise exception if trying to send signal to Process PID 0 as it
|
||||
will affect os.getpid()'s process group instead of PID 0.
|
||||
- #639: [Linux] Process.cmdline() can be truncated.
|
||||
- #640: [Linux] *connections functions may swallow errors and return an
|
||||
incomplete list of connnections.
|
||||
- #642: repr() of exceptions is incorrect.
|
||||
- #653: [Windows] Add inet_ntop function for Windows XP to support IPv6.
|
||||
- #641: [Windows] Replace deprecated string functions with safe equivalents.
|
||||
|
||||
|
||||
3.0.1 - 2015-06-18
|
||||
==================
|
||||
|
||||
**Bug fixes**
|
||||
|
||||
- #632: [Linux] better error message if cannot parse process UNIX connections.
|
||||
- #634: [Linux] Proces.cmdline() does not include empty string arguments.
|
||||
- #635: [UNIX] crash on module import if 'enum' package is installed on python
|
||||
< 3.4.
|
||||
|
||||
|
||||
3.0.0 - 2015-06-13
|
||||
==================
|
||||
|
||||
**Enhancements**
|
||||
|
||||
- #250: new psutil.net_if_stats() returning NIC statistics (isup, duplex,
|
||||
speed, MTU).
|
||||
- #376: new psutil.net_if_addrs() returning all NIC addresses a-la ifconfig.
|
||||
- #469: on Python >= 3.4 ``IOPRIO_CLASS_*`` and ``*_PRIORITY_CLASS`` constants
|
||||
returned by psutil.Process' ionice() and nice() methods are enums instead of
|
||||
plain integers.
|
||||
- #581: add .gitignore. (patch by Gabi Davar)
|
||||
- #582: connection constants returned by psutil.net_connections() and
|
||||
psutil.Process.connections() were turned from int to enums on Python > 3.4.
|
||||
- #587: Move native extension into the package.
|
||||
- #589: Process.cpu_affinity() accepts any kind of iterable (set, tuple, ...),
|
||||
not only lists.
|
||||
- #594: all deprecated APIs were removed.
|
||||
- #599: [Windows] process name() can now be determined for all processes even
|
||||
when running as a limited user.
|
||||
- #602: pre-commit GIT hook.
|
||||
- #629: enhanced support for py.test and nose test discovery and tests run.
|
||||
- #616: [Windows] Add inet_ntop function for Windows XP.
|
||||
|
||||
**Bug fixes**
|
||||
|
||||
- #428: [all UNIXes except Linux] correct handling of zombie processes;
|
||||
introduced new ZombieProcess exception class.
|
||||
- #512: [BSD] fix segfault in net_connections().
|
||||
- #555: [Linux] psutil.users() correctly handles ":0" as an alias for
|
||||
"localhost"
|
||||
- #579: [Windows] Fixed open_files() for PID>64K.
|
||||
- #579: [Windows] fixed many compiler warnings.
|
||||
- #585: [FreeBSD] net_connections() may raise KeyError.
|
||||
- #586: [FreeBSD] cpu_affinity() segfaults on set in case an invalid CPU
|
||||
number is provided.
|
||||
- #593: [FreeBSD] Process().memory_maps() segfaults.
|
||||
- #606: Process.parent() may swallow NoSuchProcess exceptions.
|
||||
- #611: [SunOS] net_io_counters has send and received swapped
|
||||
- #614: [Linux]: cpu_count(logical=False) return the number of physical CPUs
|
||||
instead of physical cores.
|
||||
- #618: [SunOS] swap tests fail on Solaris when run as normal user
|
||||
- #628: [Linux] Process.name() truncates process name in case it contains
|
||||
spaces or parentheses.
|
||||
|
||||
|
||||
2.2.1 - 2015-02-02
|
||||
==================
|
||||
|
||||
**Bug fixes**
|
||||
|
||||
- #496: [Linux] fix "ValueError: ambiguos inode with multiple PIDs references"
|
||||
(patch by Bruno Binet)
|
||||
|
||||
|
||||
2.2.0 - 2015-01-06
|
||||
==================
|
||||
|
||||
**Enhancements**
|
||||
|
||||
- #521: drop support for Python 2.4 and 2.5.
|
||||
- #553: new examples/pstree.py script.
|
||||
- #564: C extension version mismatch in case the user messed up with psutil
|
||||
installation or with sys.path is now detected at import time.
|
||||
- #568: New examples/pidof.py script.
|
||||
- #569: [FreeBSD] add support for process CPU affinity.
|
||||
|
||||
**Bug fixes**
|
||||
|
||||
- #496: [Solaris] can't import psutil.
|
||||
- #547: [UNIX] Process.username() may raise KeyError if UID can't be resolved.
|
||||
- #551: [Windows] get rid of the unicode hack for net_io_counters() NIC names.
|
||||
- #556: [Linux] lots of file handles were left open.
|
||||
- #561: [Linux] net_connections() might skip some legitimate UNIX sockets.
|
||||
(patch by spacewander)
|
||||
- #565: [Windows] use proper encoding for psutil.Process.username() and
|
||||
psutil.users(). (patch by Sylvain Mouquet)
|
||||
- #567: [Linux] in the alternative implementation of CPU affinity PyList_Append
|
||||
and Py_BuildValue return values are not checked.
|
||||
- #569: [FreeBSD] fix memory leak in psutil.cpu_count(logical=False).
|
||||
- #571: [Linux] Process.open_files() might swallow AccessDenied exceptions and
|
||||
return an incomplete list of open files.
|
||||
|
||||
|
||||
2.1.3 - 2014-09-26
|
||||
==================
|
||||
|
||||
- #536: [Linux]: fix "undefined symbol: CPU_ALLOC" compilation error.
|
||||
|
||||
|
||||
|
@ -4,12 +4,12 @@ Installing using pip on UNIX
|
||||
|
||||
The easiest way to install psutil on UNIX is by using pip (but first you might
|
||||
need to install python header files; see later).
|
||||
First install pip:
|
||||
First install pip::
|
||||
|
||||
$ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
|
||||
python ez_setup.py
|
||||
$ wget https://bootstrap.pypa.io/get-pip.py
|
||||
$ python get-pip.py
|
||||
|
||||
...then run:
|
||||
...then run::
|
||||
|
||||
$ pip install psutil
|
||||
|
||||
@ -22,51 +22,27 @@ Installing on Windows
|
||||
|
||||
Just get the right installer for your Python version and architecture from:
|
||||
https://pypi.python.org/pypi/psutil/#downloads
|
||||
|
||||
|
||||
==================================
|
||||
Compiling on Windows using mingw32
|
||||
==================================
|
||||
|
||||
First install mingw (http://www.mingw.org/) then add mingw "bin" folder to
|
||||
environment PATH (NOTE: this assumes MinGW is installed in C:\MinGW):
|
||||
|
||||
SET PATH=C:\MinGW\bin;%PATH%
|
||||
|
||||
You can then compile psutil by running:
|
||||
|
||||
setup.py build -c mingw32
|
||||
|
||||
To compile and install:
|
||||
|
||||
setup.py build -c mingw32 install
|
||||
|
||||
You can also use make.bat which automatically sets the env variable for you:
|
||||
|
||||
make.bat build
|
||||
|
||||
FWIW I managed to compile psutil against all 32-bit Python versions but not
|
||||
64 bit.
|
||||
Since wheels installers are also available you may also use pip.
|
||||
|
||||
|
||||
========================================
|
||||
Compiling on Windows using Visual Studio
|
||||
========================================
|
||||
|
||||
To use Visual Studio to compile psutil you must have the same version of
|
||||
Visual Studio used to compile your installation of Python which is::
|
||||
In order to compile psutil on Windows you'll need Visual Studio (Mingw32 is
|
||||
no longer supported). You must have the same version of Visual Studio used to compile
|
||||
your installation of Python, that is::
|
||||
|
||||
Python 2.4: VS 2003
|
||||
Python 2.5: VS 2003
|
||||
Python 2.6: VS 2008
|
||||
Python 2.7: VS 2008
|
||||
Python 3.3+: VS 2010
|
||||
* Python 2.6: VS 2008
|
||||
* Python 2.7: VS 2008
|
||||
* Python 3.3, 3.4: VS 2010 (you can download it from `MS website <http://www.visualstudio.com/downloads/download-visual-studio-vs#d-2010-express>`_)
|
||||
* Python 3.5: `VS 2015 UP <http://www.visualstudio.com/en-au/news/vs2015-preview-vs>`_
|
||||
|
||||
...then run:
|
||||
...then run::
|
||||
|
||||
setup.py build
|
||||
|
||||
...or:
|
||||
...or::
|
||||
|
||||
make.bat build
|
||||
|
||||
@ -75,24 +51,20 @@ Windows SDK and .NET Framework 3.5 SP1 to be installed first.
|
||||
Once you have those run vcvars64.bat, then compile:
|
||||
http://stackoverflow.com/questions/11072521/
|
||||
|
||||
If you do not have the right version of Visual Studio available then try using
|
||||
MinGW instead.
|
||||
|
||||
|
||||
===================
|
||||
Installing on Linux
|
||||
===================
|
||||
|
||||
gcc is required and so the python headers. They can easily be installed by
|
||||
using the distro package manager. For example, on Debian amd Ubuntu:
|
||||
using the distro package manager. For example, on Debian and Ubuntu::
|
||||
|
||||
$ sudo apt-get install gcc python-dev
|
||||
|
||||
...on Redhat and CentOS:
|
||||
...on Redhat and CentOS::
|
||||
|
||||
$ sudo yum install gcc python-devel
|
||||
|
||||
Once done, you can build/install psutil with:
|
||||
Once done, you can build/install psutil with::
|
||||
|
||||
$ python setup.py install
|
||||
|
||||
@ -104,11 +76,11 @@ Installing on OS X
|
||||
OS X installation from source will require gcc which you can obtain as part of
|
||||
the 'XcodeTools' installer from Apple. Then you can run the standard distutils
|
||||
commands.
|
||||
To build only:
|
||||
To build only::
|
||||
|
||||
$ python setup.py build
|
||||
|
||||
To install and build:
|
||||
To install and build::
|
||||
|
||||
$ python setup.py install
|
||||
|
||||
@ -121,11 +93,11 @@ The same compiler used to install Python must be present on the system in order
|
||||
to build modules using distutils. Assuming it is installed, you can build using
|
||||
the standard distutils commands.
|
||||
|
||||
Build only:
|
||||
Build only::
|
||||
|
||||
$ python setup.py build
|
||||
|
||||
Install and build:
|
||||
Install and build::
|
||||
|
||||
$ python setup.py install
|
||||
|
||||
@ -138,7 +110,7 @@ A makefile is available for both UNIX and Windows (make.bat). It provides
|
||||
some automations for the tasks described above and might be preferred over
|
||||
using setup.py. With it you can::
|
||||
|
||||
$ make install # just install
|
||||
$ make install # just install (in --user mode)
|
||||
$ make uninstall # uninstall (needs pip)
|
||||
$ make test # run tests
|
||||
$ make clean # remove installation files
|
||||
|
@ -1,3 +1,7 @@
|
||||
include .coveragerc
|
||||
include .git-pre-commit
|
||||
include .git-pre-commit
|
||||
include .gitignore
|
||||
include .travis.yml
|
||||
include CREDITS
|
||||
include HISTORY.rst
|
||||
@ -10,8 +14,9 @@ include README.rst
|
||||
include setup.py
|
||||
include TODO
|
||||
include tox.ini
|
||||
recursive-include docs *
|
||||
recursive-exclude docs/_build *
|
||||
recursive-include .appveyor/*
|
||||
recursive-include docs *
|
||||
recursive-include examples *.py
|
||||
recursive-include psutil *.py *.c *.h
|
||||
recursive-include test *.py README
|
||||
recursive-include test *.py README*
|
||||
|
@ -16,31 +16,49 @@ clean:
|
||||
rm -f `find . -type f -name \*.bak`
|
||||
rm -f `find . -type f -name \*.rej`
|
||||
rm -rf `find . -type d -name __pycache__`
|
||||
rm -rf *.core
|
||||
rm -rf *.egg-info
|
||||
rm -rf *\$testfile*
|
||||
rm -rf .coverage
|
||||
rm -rf .tox
|
||||
rm -rf build
|
||||
rm -rf dist
|
||||
rm -rf docs/_build
|
||||
rm -rf htmlcov
|
||||
|
||||
build: clean
|
||||
$(PYTHON) setup.py build
|
||||
@# copies *.so files in ./psutil directory in order to allow
|
||||
@# "import psutil" when using the interactive interpreter from within
|
||||
@# this directory.
|
||||
$(PYTHON) setup.py build_ext -i
|
||||
|
||||
# useful deps which are nice to have while developing / testing
|
||||
setup-dev-env:
|
||||
python -c "import urllib2; \
|
||||
r = urllib2.urlopen('https://bootstrap.pypa.io/get-pip.py'); \
|
||||
open('/tmp/get-pip.py', 'w').write(r.read());"
|
||||
$(PYTHON) /tmp/get-pip.py --user
|
||||
rm /tmp/get-pip.py
|
||||
$(PYTHON) -m pip install --user --upgrade pip
|
||||
$(PYTHON) -m pip install --user --upgrade \
|
||||
coverage \
|
||||
flake8 \
|
||||
ipaddress \
|
||||
ipdb \
|
||||
mock==1.0.1 \
|
||||
nose \
|
||||
pep8 \
|
||||
pyflakes \
|
||||
sphinx \
|
||||
sphinx-pypi-upload \
|
||||
unittest2 \
|
||||
|
||||
install: build
|
||||
if test $(PYTHON) = python2.4; then \
|
||||
$(PYTHON) setup.py install; \
|
||||
elif test $(PYTHON) = python2.5; then \
|
||||
$(PYTHON) setup.py install; \
|
||||
else \
|
||||
$(PYTHON) setup.py install --user; \
|
||||
fi
|
||||
$(PYTHON) setup.py install --user
|
||||
|
||||
uninstall:
|
||||
if test $(PYTHON) = python2.4; then \
|
||||
pip-2.4 uninstall -y -v psutil; \
|
||||
else \
|
||||
cd ..; $(PYTHON) -m pip uninstall -y -v psutil; \
|
||||
fi
|
||||
cd ..; $(PYTHON) -m pip uninstall -y -v psutil
|
||||
|
||||
test: install
|
||||
$(PYTHON) $(TSCRIPT)
|
||||
@ -52,27 +70,36 @@ test-system: install
|
||||
$(PYTHON) -m unittest -v test.test_psutil.TestSystemAPIs
|
||||
|
||||
test-memleaks: install
|
||||
$(PYTHON) -m unittest -v test.test_memory_leaks
|
||||
$(PYTHON) test/test_memory_leaks.py
|
||||
|
||||
# Run a specific test by name; e.g. "make test-by-name disk_" will run
|
||||
# all test methods containing "disk_" in their name.
|
||||
# Requires "pip install nose".
|
||||
test-by-name:
|
||||
@$(PYTHON) -m nose test/test_psutil.py --nocapture -v -m $(filter-out $@,$(MAKECMDGOALS))
|
||||
test-by-name: install
|
||||
@$(PYTHON) -m nose test/test_psutil.py test/_* --nocapture -v -m $(filter-out $@,$(MAKECMDGOALS))
|
||||
|
||||
# Same as above but for test_memory_leaks.py script.
|
||||
test-memleaks-by-name: install
|
||||
@$(PYTHON) -m nose test/test_memory_leaks.py --nocapture -v -m $(filter-out $@,$(MAKECMDGOALS))
|
||||
|
||||
coverage: install
|
||||
# Note: coverage options are controlled by .coveragerc file
|
||||
rm -rf .coverage htmlcov
|
||||
$(PYTHON) -m coverage run $(TSCRIPT)
|
||||
$(PYTHON) -m coverage report
|
||||
@echo "writing results to htmlcov/index.html"
|
||||
$(PYTHON) -m coverage html
|
||||
$(PYTHON) -m webbrowser -t htmlcov/index.html
|
||||
|
||||
# requires "pip install pep8"
|
||||
pep8:
|
||||
@git ls-files | grep \\.py$ | xargs pep8
|
||||
@git ls-files | grep \\.py$ | xargs $(PYTHON) -m pep8
|
||||
|
||||
# requires "pip install pyflakes"
|
||||
pyflakes:
|
||||
@export PYFLAKES_NODOCTEST=1 && \
|
||||
git ls-files | grep \\.py$ | xargs pyflakes
|
||||
git ls-files | grep \\.py$ | xargs $(PYTHON) -m pyflakes
|
||||
|
||||
# requires "pip install flake8"
|
||||
flake8:
|
||||
@git ls-files | grep \\.py$ | xargs flake8
|
||||
|
||||
@git ls-files | grep \\.py$ | xargs $(PYTHON) -m flake8
|
||||
|
||||
# Upload source tarball on https://pypi.python.org/pypi/psutil.
|
||||
upload-src: clean
|
||||
@ -88,3 +115,8 @@ upload-doc:
|
||||
git-tag-release:
|
||||
git tag -a release-`python -c "import setup; print(setup.get_version())"` -m `git rev-list HEAD --count`:`git rev-parse --short HEAD`
|
||||
echo "done; now run 'git push --follow-tags' to push the new tag on the remote repo"
|
||||
|
||||
# install GIT pre-commit hook
|
||||
install-git-hooks:
|
||||
ln -sf ../../.git-pre-commit .git/hooks/pre-commit
|
||||
chmod +x .git/hooks/pre-commit
|
||||
|
@ -1,26 +1,42 @@
|
||||
Metadata-Version: 1.1
|
||||
Name: psutil
|
||||
Version: 2.1.3
|
||||
Version: 3.1.1
|
||||
Summary: psutil is a cross-platform library for retrieving information onrunning processes and system utilization (CPU, memory, disks, network)in Python.
|
||||
Home-page: https://github.com/giampaolo/psutil
|
||||
Author: Giampaolo Rodola
|
||||
Author-email: g.rodola <at> gmail <dot> com
|
||||
License: BSD
|
||||
Description: .. image:: https://pypip.in/d/psutil/badge.png
|
||||
:target: https://crate.io/packages/psutil/
|
||||
:alt: Download this month
|
||||
|
||||
.. image:: https://pypip.in/v/psutil/badge.png
|
||||
:target: https://pypi.python.org/pypi/psutil/
|
||||
:alt: Latest version
|
||||
|
||||
.. image:: https://pypip.in/license/psutil/badge.png
|
||||
:target: https://pypi.python.org/pypi/psutil/
|
||||
:alt: License
|
||||
Description: .. image:: https://img.shields.io/pypi/dm/psutil.svg
|
||||
:target: https://pypi.python.org/pypi/psutil#downloads
|
||||
:alt: Downloads this month
|
||||
|
||||
.. image:: https://api.travis-ci.org/giampaolo/psutil.png?branch=master
|
||||
:target: https://travis-ci.org/giampaolo/psutil
|
||||
:alt: Travis
|
||||
:alt: Linux tests (Travis)
|
||||
|
||||
.. image:: https://ci.appveyor.com/api/projects/status/qdwvw7v1t915ywr5/branch/master?svg=true
|
||||
:target: https://ci.appveyor.com/project/giampaolo/psutil
|
||||
:alt: Windows tests (Appveyor)
|
||||
|
||||
.. image:: https://coveralls.io/repos/giampaolo/psutil/badge.svg?branch=master&service=github
|
||||
:target: https://coveralls.io/github/giampaolo/psutil?branch=master
|
||||
:alt: Test coverage (coverall.io)
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/psutil.svg
|
||||
:target: https://pypi.python.org/pypi/psutil/
|
||||
:alt: Latest version
|
||||
|
||||
.. image:: https://img.shields.io/github/stars/giampaolo/psutil.svg
|
||||
:target: https://github.com/giampaolo/psutil/
|
||||
:alt: Github stars
|
||||
|
||||
.. image:: https://img.shields.io/scrutinizer/g/giampaolo/psutil.svg
|
||||
:target: https://scrutinizer-ci.com/g/giampaolo/psutil/
|
||||
:alt: Code quality (scrutinizer-ci.com)
|
||||
|
||||
.. image:: https://img.shields.io/pypi/l/psutil.svg
|
||||
:target: https://pypi.python.org/pypi/psutil/
|
||||
:alt: License
|
||||
|
||||
===========
|
||||
Quick links
|
||||
@ -28,9 +44,11 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
|
||||
|
||||
- `Home page <https://github.com/giampaolo/psutil>`_
|
||||
- `Documentation <http://pythonhosted.org/psutil/>`_
|
||||
- `Installation <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
|
||||
- `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`_
|
||||
- `Forum <http://groups.google.com/group/psutil/topics>`_
|
||||
- `Blog <http://grodola.blogspot.com/search/label/psutil>`_
|
||||
- `Development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_
|
||||
- `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`_
|
||||
|
||||
=======
|
||||
@ -45,8 +63,9 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
|
||||
tools such as: ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice,
|
||||
ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap. It currently supports
|
||||
**Linux, Windows, OSX, FreeBSD** and **Sun Solaris**, both **32-bit** and
|
||||
**64-bit** architectures, with Python versions from **2.4 to 3.4**. PyPy is
|
||||
also known to work.
|
||||
**64-bit** architectures, with Python versions from **2.6 to 3.5** (users of
|
||||
Python 2.4 and 2.5 may use `2.1.3 <https://pypi.python.org/pypi?name=psutil&version=2.1.3&:action=files>`__ version).
|
||||
`PyPy <http://pypy.org/>`__ is also known to work.
|
||||
|
||||
====================
|
||||
Example applications
|
||||
@ -67,8 +86,8 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
|
||||
See also:
|
||||
|
||||
* https://github.com/nicolargo/glances
|
||||
* https://github.com/google/grr
|
||||
* https://github.com/Jahaja/psdash
|
||||
* https://code.google.com/p/grr/
|
||||
|
||||
==============
|
||||
Example usages
|
||||
@ -117,9 +136,9 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
|
||||
.. code-block:: python
|
||||
|
||||
>>> psutil.virtual_memory()
|
||||
svmem(total=8374149120L, available=2081050624L, percent=75.1, used=8074080256L, free=300068864L, active=3294920704, inactive=1361616896, buffers=529895424L, cached=1251086336)
|
||||
svmem(total=8374149120, available=2081050624, percent=75.1, used=8074080256, free=300068864, active=3294920704, inactive=1361616896, buffers=529895424, cached=1251086336)
|
||||
>>> psutil.swap_memory()
|
||||
sswap(total=2097147904L, used=296128512L, free=1801019392L, percent=14.1, sin=304193536, sout=677842944)
|
||||
sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944)
|
||||
>>>
|
||||
|
||||
Disks
|
||||
@ -148,11 +167,23 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
|
||||
'lo': netio(bytes_sent=2838627, bytes_recv=2838627, packets_sent=30567, packets_recv=30567, errin=0, errout=0, dropin=0, dropout=0)}
|
||||
>>>
|
||||
>>> psutil.net_connections()
|
||||
[pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
|
||||
pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
|
||||
pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
|
||||
pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None)
|
||||
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
|
||||
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
|
||||
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
|
||||
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None)
|
||||
...]
|
||||
>>>
|
||||
>>> psutil.net_if_addrs()
|
||||
{'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1'),
|
||||
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None),
|
||||
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00')],
|
||||
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255'),
|
||||
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None),
|
||||
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff')]}
|
||||
>>>
|
||||
>>> psutil.net_if_stats()
|
||||
{'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500),
|
||||
'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536)}
|
||||
|
||||
Other system info
|
||||
=================
|
||||
@ -218,7 +249,7 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
|
||||
>>>
|
||||
>>> p.memory_info()
|
||||
pmem(rss=7471104, vms=68513792)
|
||||
>>> p.ext_memory_info()
|
||||
>>> p.memory_info_ex()
|
||||
extmem(rss=9662464, vms=49192960, shared=3612672, text=2564096, lib=0, data=5754880, dirty=0)
|
||||
>>> p.memory_maps()
|
||||
[pmmap_grouped(path='/lib/x86_64-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0),
|
||||
@ -235,10 +266,10 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
|
||||
[popenfile(path='/home/giampaolo/svn/psutil/somefile', fd=3)]
|
||||
>>>
|
||||
>>> p.connections()
|
||||
[pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
|
||||
pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
|
||||
pconn(fd=119, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
|
||||
pconn(fd=123, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
|
||||
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
|
||||
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
|
||||
pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
|
||||
pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
|
||||
>>>
|
||||
>>> p.num_threads()
|
||||
4
|
||||
@ -259,7 +290,7 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
|
||||
>>>
|
||||
>>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # IO priority (Win and Linux only)
|
||||
>>> p.ionice()
|
||||
pionice(ioclass=3, value=0)
|
||||
pionice(ioclass=<IOPriority.IOPRIO_CLASS_IDLE: 3>, value=0)
|
||||
>>>
|
||||
>>> p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) # set resource limits (Linux only)
|
||||
>>> p.rlimit(psutil.RLIMIT_NOFILE)
|
||||
@ -327,6 +358,12 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
|
||||
Timeline
|
||||
========
|
||||
|
||||
- 2015-07-15: `psutil-3.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.1.tar.gz>`_
|
||||
- 2015-07-15: `psutil-3.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.0.tar.gz>`_
|
||||
- 2015-06-18: `psutil-3.0.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.1.tar.gz>`_
|
||||
- 2015-06-13: `psutil-3.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.0.tar.gz>`_
|
||||
- 2015-02-02: `psutil-2.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.1.tar.gz>`_
|
||||
- 2015-01-06: `psutil-2.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.0.tar.gz>`_
|
||||
- 2014-09-26: `psutil-2.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.3.tar.gz>`_
|
||||
- 2014-09-21: `psutil-2.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.2.tar.gz>`_
|
||||
- 2014-04-30: `psutil-2.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.1.tar.gz>`_
|
||||
@ -356,7 +393,7 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
|
||||
- 2009-03-06: `psutil-0.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.1.tar.gz>`_
|
||||
- 2009-01-27: `psutil-0.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.0.tar.gz>`_
|
||||
|
||||
Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,monitoring,ulimit,prlimit
|
||||
Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,pstree,monitoring,ulimit,prlimit
|
||||
Platform: Platform Independent
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Console
|
||||
@ -375,8 +412,6 @@ Classifier: Operating System :: POSIX :: SunOS/Solaris
|
||||
Classifier: Operating System :: POSIX
|
||||
Classifier: Programming Language :: C
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.4
|
||||
Classifier: Programming Language :: Python :: 2.5
|
||||
Classifier: Programming Language :: Python :: 2.6
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
|
@ -1,18 +1,34 @@
|
||||
.. image:: https://pypip.in/d/psutil/badge.png
|
||||
:target: https://crate.io/packages/psutil/
|
||||
:alt: Download this month
|
||||
|
||||
.. image:: https://pypip.in/v/psutil/badge.png
|
||||
:target: https://pypi.python.org/pypi/psutil/
|
||||
:alt: Latest version
|
||||
|
||||
.. image:: https://pypip.in/license/psutil/badge.png
|
||||
:target: https://pypi.python.org/pypi/psutil/
|
||||
:alt: License
|
||||
.. image:: https://img.shields.io/pypi/dm/psutil.svg
|
||||
:target: https://pypi.python.org/pypi/psutil#downloads
|
||||
:alt: Downloads this month
|
||||
|
||||
.. image:: https://api.travis-ci.org/giampaolo/psutil.png?branch=master
|
||||
:target: https://travis-ci.org/giampaolo/psutil
|
||||
:alt: Travis
|
||||
:alt: Linux tests (Travis)
|
||||
|
||||
.. image:: https://ci.appveyor.com/api/projects/status/qdwvw7v1t915ywr5/branch/master?svg=true
|
||||
:target: https://ci.appveyor.com/project/giampaolo/psutil
|
||||
:alt: Windows tests (Appveyor)
|
||||
|
||||
.. image:: https://coveralls.io/repos/giampaolo/psutil/badge.svg?branch=master&service=github
|
||||
:target: https://coveralls.io/github/giampaolo/psutil?branch=master
|
||||
:alt: Test coverage (coverall.io)
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/psutil.svg
|
||||
:target: https://pypi.python.org/pypi/psutil/
|
||||
:alt: Latest version
|
||||
|
||||
.. image:: https://img.shields.io/github/stars/giampaolo/psutil.svg
|
||||
:target: https://github.com/giampaolo/psutil/
|
||||
:alt: Github stars
|
||||
|
||||
.. image:: https://img.shields.io/scrutinizer/g/giampaolo/psutil.svg
|
||||
:target: https://scrutinizer-ci.com/g/giampaolo/psutil/
|
||||
:alt: Code quality (scrutinizer-ci.com)
|
||||
|
||||
.. image:: https://img.shields.io/pypi/l/psutil.svg
|
||||
:target: https://pypi.python.org/pypi/psutil/
|
||||
:alt: License
|
||||
|
||||
===========
|
||||
Quick links
|
||||
@ -20,9 +36,11 @@ Quick links
|
||||
|
||||
- `Home page <https://github.com/giampaolo/psutil>`_
|
||||
- `Documentation <http://pythonhosted.org/psutil/>`_
|
||||
- `Installation <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
|
||||
- `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`_
|
||||
- `Forum <http://groups.google.com/group/psutil/topics>`_
|
||||
- `Blog <http://grodola.blogspot.com/search/label/psutil>`_
|
||||
- `Development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_
|
||||
- `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`_
|
||||
|
||||
=======
|
||||
@ -37,8 +55,9 @@ running processes**. It implements many functionalities offered by command line
|
||||
tools such as: ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice,
|
||||
ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap. It currently supports
|
||||
**Linux, Windows, OSX, FreeBSD** and **Sun Solaris**, both **32-bit** and
|
||||
**64-bit** architectures, with Python versions from **2.4 to 3.4**. PyPy is
|
||||
also known to work.
|
||||
**64-bit** architectures, with Python versions from **2.6 to 3.5** (users of
|
||||
Python 2.4 and 2.5 may use `2.1.3 <https://pypi.python.org/pypi?name=psutil&version=2.1.3&:action=files>`__ version).
|
||||
`PyPy <http://pypy.org/>`__ is also known to work.
|
||||
|
||||
====================
|
||||
Example applications
|
||||
@ -59,8 +78,8 @@ Example applications
|
||||
See also:
|
||||
|
||||
* https://github.com/nicolargo/glances
|
||||
* https://github.com/google/grr
|
||||
* https://github.com/Jahaja/psdash
|
||||
* https://code.google.com/p/grr/
|
||||
|
||||
==============
|
||||
Example usages
|
||||
@ -109,9 +128,9 @@ Memory
|
||||
.. code-block:: python
|
||||
|
||||
>>> psutil.virtual_memory()
|
||||
svmem(total=8374149120L, available=2081050624L, percent=75.1, used=8074080256L, free=300068864L, active=3294920704, inactive=1361616896, buffers=529895424L, cached=1251086336)
|
||||
svmem(total=8374149120, available=2081050624, percent=75.1, used=8074080256, free=300068864, active=3294920704, inactive=1361616896, buffers=529895424, cached=1251086336)
|
||||
>>> psutil.swap_memory()
|
||||
sswap(total=2097147904L, used=296128512L, free=1801019392L, percent=14.1, sin=304193536, sout=677842944)
|
||||
sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944)
|
||||
>>>
|
||||
|
||||
Disks
|
||||
@ -140,11 +159,23 @@ Network
|
||||
'lo': netio(bytes_sent=2838627, bytes_recv=2838627, packets_sent=30567, packets_recv=30567, errin=0, errout=0, dropin=0, dropout=0)}
|
||||
>>>
|
||||
>>> psutil.net_connections()
|
||||
[pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
|
||||
pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
|
||||
pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
|
||||
pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None)
|
||||
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
|
||||
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
|
||||
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
|
||||
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None)
|
||||
...]
|
||||
>>>
|
||||
>>> psutil.net_if_addrs()
|
||||
{'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1'),
|
||||
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None),
|
||||
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00')],
|
||||
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255'),
|
||||
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None),
|
||||
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff')]}
|
||||
>>>
|
||||
>>> psutil.net_if_stats()
|
||||
{'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500),
|
||||
'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536)}
|
||||
|
||||
Other system info
|
||||
=================
|
||||
@ -210,7 +241,7 @@ Process management
|
||||
>>>
|
||||
>>> p.memory_info()
|
||||
pmem(rss=7471104, vms=68513792)
|
||||
>>> p.ext_memory_info()
|
||||
>>> p.memory_info_ex()
|
||||
extmem(rss=9662464, vms=49192960, shared=3612672, text=2564096, lib=0, data=5754880, dirty=0)
|
||||
>>> p.memory_maps()
|
||||
[pmmap_grouped(path='/lib/x86_64-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0),
|
||||
@ -227,10 +258,10 @@ Process management
|
||||
[popenfile(path='/home/giampaolo/svn/psutil/somefile', fd=3)]
|
||||
>>>
|
||||
>>> p.connections()
|
||||
[pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
|
||||
pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
|
||||
pconn(fd=119, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
|
||||
pconn(fd=123, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
|
||||
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
|
||||
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
|
||||
pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
|
||||
pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
|
||||
>>>
|
||||
>>> p.num_threads()
|
||||
4
|
||||
@ -251,7 +282,7 @@ Process management
|
||||
>>>
|
||||
>>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # IO priority (Win and Linux only)
|
||||
>>> p.ionice()
|
||||
pionice(ioclass=3, value=0)
|
||||
pionice(ioclass=<IOPriority.IOPRIO_CLASS_IDLE: 3>, value=0)
|
||||
>>>
|
||||
>>> p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) # set resource limits (Linux only)
|
||||
>>> p.rlimit(psutil.RLIMIT_NOFILE)
|
||||
@ -319,6 +350,12 @@ http://groups.google.com/group/psutil/
|
||||
Timeline
|
||||
========
|
||||
|
||||
- 2015-07-15: `psutil-3.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.1.tar.gz>`_
|
||||
- 2015-07-15: `psutil-3.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.0.tar.gz>`_
|
||||
- 2015-06-18: `psutil-3.0.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.1.tar.gz>`_
|
||||
- 2015-06-13: `psutil-3.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.0.tar.gz>`_
|
||||
- 2015-02-02: `psutil-2.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.1.tar.gz>`_
|
||||
- 2015-01-06: `psutil-2.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.0.tar.gz>`_
|
||||
- 2014-09-26: `psutil-2.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.3.tar.gz>`_
|
||||
- 2014-09-21: `psutil-2.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.2.tar.gz>`_
|
||||
- 2014-04-30: `psutil-2.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.1.tar.gz>`_
|
||||
|
@ -9,22 +9,29 @@ https://github.com/giampaolo/psutil/issues
|
||||
HIGHER PRIORITY
|
||||
===============
|
||||
|
||||
* #250: net ifaces speed.
|
||||
|
||||
* #376: ifconfig functionalities aka psutil.net_ifaces (could be merged
|
||||
with #250)
|
||||
|
||||
* OpenBSD support.
|
||||
|
||||
* #371: CPU temperature (apparently OSX and Linux only; on Linux it requires
|
||||
lm-sensors lib).
|
||||
|
||||
* #269: expose network ifaces RX/TW queues.
|
||||
* #269: expose network ifaces RX/TW queues. This should probably go into
|
||||
net_if_stats(). Figure out on what platforms this is supported:
|
||||
Linux: yes
|
||||
Others: ?
|
||||
|
||||
* Process.threads(): thread names
|
||||
* Process.threads(): thread names; patch for OSX available at:
|
||||
https://code.google.com/p/plcrashreporter/issues/detail?id=65
|
||||
|
||||
* Asynchronous psutil.Popen (see http://bugs.python.org/issue1191964)
|
||||
|
||||
* (Windows) fall back on using WMIC for Process methods returning AccessDenied
|
||||
|
||||
* #613: thread names.
|
||||
|
||||
* #604: emulate os.getloadavg() on Windows
|
||||
|
||||
* #269: NIC rx/tx queue.
|
||||
|
||||
|
||||
LOWER PRIORITY
|
||||
==============
|
||||
@ -39,11 +46,6 @@ LOWER PRIORITY
|
||||
|
||||
* AIX support?
|
||||
|
||||
* examples/pidof.py (same as 'pidof' cli tool)
|
||||
|
||||
* examples/pstree.py (same as 'pstree' cli tool)
|
||||
* threads() should also return thread names in order to implement it
|
||||
|
||||
* examples/taskmgr-gui.py (using tk).
|
||||
|
||||
* system-wide number of open file descriptors:
|
||||
@ -55,10 +57,7 @@ LOWER PRIORITY
|
||||
|
||||
* #357: what CPU a process is on.
|
||||
|
||||
* thread names:
|
||||
* https://code.google.com/p/plcrashreporter/issues/detail?id=65
|
||||
|
||||
* Doc / wiki which compares similarities between UNIX cli tools and psutil.
|
||||
* Doc / wiki which compares similarities between UNIX cli tools and psutil.
|
||||
Example:
|
||||
df -a -> psutil.disk_partitions
|
||||
lsof -> psutil.Process.open_files() and psutil.Process.open_connections()
|
||||
@ -70,7 +69,13 @@ LOWER PRIORITY
|
||||
DEBATABLE
|
||||
=========
|
||||
|
||||
* support wheels? http://pythonwheels.com/
|
||||
* psutil.proc_tree() something which obtains a {pid:ppid, ...} dict for
|
||||
all running processes in one shot. This can be factored out from
|
||||
Process.children() and exposed as a first class function.
|
||||
PROS: on Windows we can take advantage of _psutil_windows.ppid_map()
|
||||
which is faster than iterating over all pids and calling ppid().
|
||||
CONS: examples/pstree.py shows this can be easily done in the user code
|
||||
so maybe it's not worth the addition.
|
||||
|
||||
* advanced cmdline interface exposing the whole API and providing different
|
||||
kind of outputs (e.g. pprinted, colorized, json).
|
||||
@ -91,10 +96,18 @@ DEBATABLE
|
||||
Also, we can probably reimplement wait_pid() on POSIX which is currently
|
||||
implemented as a busy-loop.
|
||||
|
||||
* Certain systems (XXX figure out which ones exactly) provide CPU times about
|
||||
process children. On those systems Process.cpu_times() might return
|
||||
a (user, system, user_children, system_children) ntuple.
|
||||
Also, os.times() provides 'elapsed' times as well.
|
||||
* Certain systems provide CPU times about process children. On those systems
|
||||
Process.cpu_times() might return a (user, system, user_children,
|
||||
system_children) ntuple.
|
||||
* Linux: /proc/{PID}/stat
|
||||
* Solaris: pr_cutime and pr_cstime
|
||||
* FreeBSD: none
|
||||
* OSX: none
|
||||
* Windows: none
|
||||
|
||||
* ...also, os.times() provides 'elapsed' times as well.
|
||||
|
||||
* ...also Linux provides guest_time and cguest_time.
|
||||
|
||||
* Enrich exception classes hierarchy on Python >= 3.3 / post PEP-3151 so that:
|
||||
- NoSuchProcess inherits from ProcessLookupError
|
||||
@ -130,6 +143,10 @@ DEBATABLE
|
||||
|
||||
* round Process.memory_percent() result?
|
||||
|
||||
* #550: number of threads per core.
|
||||
|
||||
* Have psutil.Process().cpu_affinity([]) be an alias for "all CPUs"?
|
||||
|
||||
|
||||
COMPATIBILITY BREAKAGE
|
||||
======================
|
||||
@ -147,4 +164,4 @@ Removals (will likely happen in 2.2):
|
||||
REJECTED IDEAS
|
||||
==============
|
||||
|
||||
STUB
|
||||
STUB
|
||||
|
@ -14,29 +14,17 @@
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
if sys.version_info >= (3, ):
|
||||
def u(s):
|
||||
return s
|
||||
else:
|
||||
def u(s):
|
||||
if not isinstance(s, unicode): # NOQA
|
||||
s = unicode(s, "unicode_escape") # NOQA
|
||||
return s
|
||||
|
||||
|
||||
PROJECT_NAME = u("psutil")
|
||||
AUTHOR = u("Giampaolo Rodola'")
|
||||
PROJECT_NAME = "psutil"
|
||||
AUTHOR = "Giampaolo Rodola'"
|
||||
THIS_YEAR = str(datetime.datetime.now().year)
|
||||
HERE = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
|
||||
def get_version():
|
||||
INIT = os.path.abspath(os.path.join(HERE, '../psutil/__init__.py'))
|
||||
f = open(INIT, 'r')
|
||||
try:
|
||||
with open(INIT, 'r') as f:
|
||||
for line in f:
|
||||
if line.startswith('__version__'):
|
||||
ret = eval(line.strip().split(' = ')[1])
|
||||
@ -46,8 +34,6 @@ def get_version():
|
||||
return ret
|
||||
else:
|
||||
raise ValueError("couldn't find version string")
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
VERSION = get_version()
|
||||
|
||||
@ -77,7 +63,7 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = PROJECT_NAME
|
||||
copyright = u('2009-%s, %s' % (THIS_YEAR, AUTHOR))
|
||||
copyright = '2009-%s, %s' % (THIS_YEAR, AUTHOR)
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
@ -223,7 +209,7 @@ htmlhelp_basename = '%s-doc' % PROJECT_NAME
|
||||
# [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', '%s.tex' % PROJECT_NAME,
|
||||
u('%s documentation') % PROJECT_NAME, AUTHOR),
|
||||
'%s documentation' % PROJECT_NAME, AUTHOR),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at
|
||||
@ -255,7 +241,7 @@ latex_documents = [
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', PROJECT_NAME, u('%s documentation') % PROJECT_NAME, [AUTHOR], 1)
|
||||
('index', PROJECT_NAME, '%s documentation' % PROJECT_NAME, [AUTHOR], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
|
@ -18,8 +18,10 @@ Quick links
|
||||
|
||||
* `Home page <https://github.com/giampaolo/psutil>`__
|
||||
* `Blog <http://grodola.blogspot.com/search/label/psutil>`__
|
||||
* `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`__
|
||||
* `Forum <http://groups.google.com/group/psutil/topics>`__
|
||||
* `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`__
|
||||
* `Installation <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
|
||||
* `Development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_
|
||||
* `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`__
|
||||
|
||||
About
|
||||
@ -38,8 +40,8 @@ From project's home page:
|
||||
ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap*.
|
||||
It currently supports **Linux, Windows, OSX, FreeBSD** and **Sun Solaris**,
|
||||
both **32-bit** and **64-bit** architectures, with Python versions from
|
||||
**2.4** to **3.4**.
|
||||
`Pypy <http://pypy.org/>`__ is also known to work.
|
||||
**2.6 to 3.4** (users of Python 2.4 and 2.5 may use `2.1.3 <https://pypi.python.org/pypi?name=psutil&version=2.1.3&:action=files>`__ version).
|
||||
`PyPy <http://pypy.org/>`__ is also known to work.
|
||||
|
||||
The psutil documentation you're reading is distributed as a single HTML page.
|
||||
|
||||
@ -66,7 +68,7 @@ CPU
|
||||
- **guest** *(Linux 2.6.24+)*
|
||||
- **guest_nice** *(Linux 3.2.0+)*
|
||||
|
||||
When *percpu* is ``True`` return a list of nameduples for each logical CPU
|
||||
When *percpu* is ``True`` return a list of namedtuples for each logical CPU
|
||||
on the system.
|
||||
First element of the list refers to first CPU, second element to second CPU
|
||||
and so on.
|
||||
@ -199,7 +201,7 @@ Memory
|
||||
* **total**: total swap memory in bytes
|
||||
* **used**: used swap memory in bytes
|
||||
* **free**: free swap memory in bytes
|
||||
* **percent**: the percentage usage
|
||||
* **percent**: the percentage usage calculated as ``(total - available) / total * 100``
|
||||
* **sin**: the number of bytes the system has swapped in from disk
|
||||
(cumulative)
|
||||
* **sout**: the number of bytes the system has swapped out from disk
|
||||
@ -274,7 +276,7 @@ Disks
|
||||
|
||||
If *perdisk* is ``True`` return the same information for every physical disk
|
||||
installed on the system as a dictionary with partition names as the keys and
|
||||
the namedutuple described above as the values.
|
||||
the namedtuple described above as the values.
|
||||
See `examples/iotop.py <https://github.com/giampaolo/psutil/blob/master/examples/iotop.py>`__
|
||||
for an example application.
|
||||
|
||||
@ -321,7 +323,7 @@ Network
|
||||
|
||||
.. function:: net_connections(kind='inet')
|
||||
|
||||
Return system-wide socket connections as a list of namedutples.
|
||||
Return system-wide socket connections as a list of namedtuples.
|
||||
Every namedtuple provides 7 attributes:
|
||||
|
||||
- **fd**: the socket file descriptor, if retrievable, else ``-1``.
|
||||
@ -383,6 +385,7 @@ Network
|
||||
| "all" | the sum of all the possible families and protocols |
|
||||
+----------------+-----------------------------------------------------+
|
||||
|
||||
On OSX this function requires root privileges.
|
||||
To get per-process connections use :meth:`Process.connections`.
|
||||
Also, see
|
||||
`netstat.py sample script <https://github.com/giampaolo/psutil/blob/master/examples/netstat.py>`__.
|
||||
@ -390,17 +393,85 @@ Network
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.net_connections()
|
||||
[pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
|
||||
pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
|
||||
pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
|
||||
pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None)
|
||||
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
|
||||
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
|
||||
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
|
||||
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None)
|
||||
...]
|
||||
|
||||
.. note:: (OSX) :class:`psutil.AccessDenied` is always raised unless running
|
||||
as root (lsof does the same).
|
||||
.. note:: (Solaris) UNIX sockets are not supported.
|
||||
|
||||
*New in 2.1.0*
|
||||
.. versionadded:: 2.1.0
|
||||
|
||||
.. function:: net_if_addrs()
|
||||
|
||||
Return the addresses associated to each NIC (network interface card)
|
||||
installed on the system as a dictionary whose keys are the NIC names and
|
||||
value is a list of namedtuples for each address assigned to the NIC.
|
||||
Each namedtuple includes 4 fields:
|
||||
|
||||
- **family**
|
||||
- **address**
|
||||
- **netmask**
|
||||
- **broadcast**
|
||||
|
||||
*family* can be either
|
||||
`AF_INET <http://docs.python.org//library/socket.html#socket.AF_INET>`__,
|
||||
`AF_INET6 <http://docs.python.org//library/socket.html#socket.AF_INET6>`__
|
||||
or :const:`psutil.AF_LINK`, which refers to a MAC address.
|
||||
*address* is the primary address, *netmask* and *broadcast* may be ``None``.
|
||||
Example::
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.net_if_addrs()
|
||||
{'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1'),
|
||||
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None),
|
||||
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00')],
|
||||
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255'),
|
||||
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None),
|
||||
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff')]}
|
||||
>>>
|
||||
|
||||
See also `examples/ifconfig.py <https://github.com/giampaolo/psutil/blob/master/examples/ifconfig.py>`__
|
||||
for an example application.
|
||||
|
||||
.. note:: if you're interested in others families (e.g. AF_BLUETOOTH) you can
|
||||
use the more powerful `netifaces <https://pypi.python.org/pypi/netifaces/>`__
|
||||
extension.
|
||||
|
||||
.. note:: you can have more than one address of the same family associated
|
||||
with each interface (that's why dict values are lists).
|
||||
|
||||
*New in 3.0.0*
|
||||
|
||||
.. function:: net_if_stats()
|
||||
|
||||
Return information about each NIC (network interface card) installed on the
|
||||
system as a dictionary whose keys are the NIC names and value is a namedtuple
|
||||
with the following fields:
|
||||
|
||||
- **isup**
|
||||
- **duplex**
|
||||
- **speed**
|
||||
- **mtu**
|
||||
|
||||
*isup* is a boolean indicating whether the NIC is up and running, *duplex*
|
||||
can be either :const:`NIC_DUPLEX_FULL`, :const:`NIC_DUPLEX_HALF` or
|
||||
:const:`NIC_DUPLEX_UNKNOWN`, *speed* is the NIC speed expressed in mega bits
|
||||
(MB), if it can't be determined (e.g. 'localhost') it will be set to ``0``,
|
||||
*mtu* is the maximum transmission unit expressed in bytes.
|
||||
See also `examples/ifconfig.py <https://github.com/giampaolo/psutil/blob/master/examples/ifconfig.py>`__
|
||||
for an example application.
|
||||
Example:
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.net_if_stats()
|
||||
{'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500),
|
||||
'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536)}
|
||||
|
||||
*New in 3.0.0*
|
||||
|
||||
|
||||
Other system info
|
||||
@ -498,7 +569,7 @@ Functions
|
||||
import psutil
|
||||
|
||||
def on_terminate(proc):
|
||||
print("process {} terminated".format(proc))
|
||||
print("process {} terminated with exit code {}".format(proc, proc.returncode))
|
||||
|
||||
procs = [...] # a list of Process instances
|
||||
for p in procs:
|
||||
@ -521,6 +592,18 @@ Exceptions
|
||||
exists. "name" is the name the process had before disappearing
|
||||
and gets set only if :meth:`Process.name()` was previosly called.
|
||||
|
||||
.. class:: ZombieProcess(pid, name=None, ppid=None, msg=None)
|
||||
|
||||
This may be raised by :class:`Process` class methods when querying a zombie
|
||||
process on UNIX (Windows doesn't have zombie processes). Depending on the
|
||||
method called the OS may be able to succeed in retrieving the process
|
||||
information or not.
|
||||
Note: this is a subclass of :class:`NoSuchProcess` so if you're not
|
||||
interested in retrieving zombies (e.g. when using :func:`process_iter()`)
|
||||
you can ignore this exception and just catch :class:`NoSuchProcess`.
|
||||
|
||||
*New in 3.0.0*
|
||||
|
||||
.. class:: AccessDenied(pid=None, name=None, msg=None)
|
||||
|
||||
Raised by :class:`Process` class methods when permission to perform an
|
||||
@ -609,20 +692,24 @@ Process class
|
||||
>>> datetime.datetime.fromtimestamp(p.create_time()).strftime("%Y-%m-%d %H:%M:%S")
|
||||
'2011-03-05 18:03:52'
|
||||
|
||||
.. method:: as_dict(attrs=[], ad_value=None)
|
||||
.. method:: as_dict(attrs=None, ad_value=None)
|
||||
|
||||
Utility method returning process information as a hashable dictionary.
|
||||
If *attrs* is specified it must be a list of strings reflecting available
|
||||
:class:`Process` class's attribute names (e.g. ``['cpu_times', 'name']``)
|
||||
else all public (read only) attributes are assumed. *ad_value* is the
|
||||
value which gets assigned to a dict key in case :class:`AccessDenied`
|
||||
exception is raised when retrieving that particular process information.
|
||||
or :class:`ZombieProcess` exception is raised when retrieving that
|
||||
particular process information.
|
||||
|
||||
>>> import psutil
|
||||
>>> p = psutil.Process()
|
||||
>>> p.as_dict(attrs=['pid', 'name', 'username'])
|
||||
{'username': 'giampaolo', 'pid': 12366, 'name': 'python'}
|
||||
|
||||
.. versionchanged:: 3.0.0 *ad_value* is used also when incurring into
|
||||
:class:`ZombieProcess` exception, not only :class:`AccessDenied`
|
||||
|
||||
.. method:: parent()
|
||||
|
||||
Utility method which returns the parent process as a :class:`Process`
|
||||
@ -646,7 +733,7 @@ Process class
|
||||
.. method:: uids()
|
||||
|
||||
The **real**, **effective** and **saved** user ids of this process as a
|
||||
nameduple. This is the same as
|
||||
namedtuple. This is the same as
|
||||
`os.getresuid() <http://docs.python.org//library/os.html#os.getresuid>`__
|
||||
but can be used for every process PID.
|
||||
|
||||
@ -655,7 +742,7 @@ Process class
|
||||
.. method:: gids()
|
||||
|
||||
The **real**, **effective** and **saved** group ids of this process as a
|
||||
nameduple. This is the same as
|
||||
namedtuple. This is the same as
|
||||
`os.getresgid() <http://docs.python.org//library/os.html#os.getresgid>`__
|
||||
but can be used for every process PID.
|
||||
|
||||
@ -682,6 +769,13 @@ Process class
|
||||
10
|
||||
>>>
|
||||
|
||||
Starting from `Python 3.3 <http://bugs.python.org/issue10784>`__ this
|
||||
functionality is also available as
|
||||
`os.getpriority() <http://docs.python.org/3/library/os.html#os.getpriority>`__
|
||||
and
|
||||
`os.setpriority() <http://docs.python.org/3/library/os.html#os.setpriority>`__
|
||||
(UNIX only).
|
||||
|
||||
On Windows this is available as well by using
|
||||
`GetPriorityClass <http://msdn.microsoft.com/en-us/library/ms683211(v=vs.85).aspx>`__
|
||||
and `SetPriorityClass <http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx>`__
|
||||
@ -692,12 +786,6 @@ Process class
|
||||
|
||||
>>> p.nice(psutil.HIGH_PRIORITY_CLASS)
|
||||
|
||||
Starting from `Python 3.3 <http://bugs.python.org/issue10784>`__ this
|
||||
same functionality is available as
|
||||
`os.getpriority() <http://docs.python.org/3/library/os.html#os.getpriority>`__
|
||||
and
|
||||
`os.setpriority() <http://docs.python.org/3/library/os.html#os.setpriority>`__.
|
||||
|
||||
.. method:: ionice(ioclass=None, value=None)
|
||||
|
||||
Get or set
|
||||
@ -714,7 +802,7 @@ Process class
|
||||
>>> p = psutil.Process()
|
||||
>>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # set
|
||||
>>> p.ionice() # get
|
||||
pionice(ioclass=3, value=0)
|
||||
pionice(ioclass=<IOPriority.IOPRIO_CLASS_IDLE: 3>, value=0)
|
||||
>>>
|
||||
|
||||
On Windows only *ioclass* is used and it can be set to ``2`` (normal),
|
||||
@ -722,6 +810,10 @@ Process class
|
||||
|
||||
Availability: Linux and Windows > Vista
|
||||
|
||||
.. versionchanged:: 3.0.0 on >= Python 3.4 the returned ``ioclass``
|
||||
constant is an `enum <https://docs.python.org/3/library/enum.html#module-enum>`__
|
||||
instead of a plain integer.
|
||||
|
||||
.. method:: rlimit(resource, limits=None)
|
||||
|
||||
Get or set process resource limits (see
|
||||
@ -761,7 +853,7 @@ Process class
|
||||
>>> p.io_counters()
|
||||
pio(read_count=454556, write_count=3456, read_bytes=110592, write_bytes=0)
|
||||
|
||||
Availability: all platforms except OSX
|
||||
Availability: all platforms except OSX and Solaris
|
||||
|
||||
.. method:: num_ctx_switches()
|
||||
|
||||
@ -836,7 +928,8 @@ Process class
|
||||
`CPU affinity <http://www.linuxjournal.com/article/6799?page=0,0>`__.
|
||||
CPU affinity consists in telling the OS to run a certain process on a
|
||||
limited set of CPUs only. The number of eligible CPUs can be obtained with
|
||||
``list(range(psutil.cpu_count()))``.
|
||||
``list(range(psutil.cpu_count()))``. On set raises ``ValueError`` in case
|
||||
an invalid CPU number is specified.
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.cpu_count()
|
||||
@ -845,9 +938,17 @@ Process class
|
||||
>>> p.cpu_affinity() # get
|
||||
[0, 1, 2, 3]
|
||||
>>> p.cpu_affinity([0]) # set; from now on, process will run on CPU #0 only
|
||||
>>> p.cpu_affinity()
|
||||
[0]
|
||||
>>>
|
||||
>>> # reset affinity against all CPUs
|
||||
>>> all_cpus = list(range(psutil.cpu_count()))
|
||||
>>> p.cpu_affinity(all_cpus)
|
||||
>>>
|
||||
|
||||
Availability: Linux, Windows
|
||||
Availability: Linux, Windows, BSD
|
||||
|
||||
.. versionchanged:: 2.2.0 added support for FreeBSD
|
||||
|
||||
.. method:: memory_info()
|
||||
|
||||
@ -903,7 +1004,7 @@ Process class
|
||||
|
||||
.. method:: memory_maps(grouped=True)
|
||||
|
||||
Return process's mapped memory regions as a list of nameduples whose
|
||||
Return process's mapped memory regions as a list of namedtuples whose
|
||||
fields are variable depending on the platform. As such, portable
|
||||
applications should rely on namedtuple's `path` and `rss` fields only.
|
||||
This method is useful to obtain a detailed representation of process
|
||||
@ -958,15 +1059,31 @@ Process class
|
||||
the absolute file name and the file descriptor number (on Windows this is
|
||||
always ``-1``). Example:
|
||||
|
||||
>>> import psutil
|
||||
>>> f = open('file.ext', 'w')
|
||||
>>> p = psutil.Process()
|
||||
>>> p.open_files()
|
||||
[popenfile(path='/home/giampaolo/svn/psutil/file.ext', fd=3)]
|
||||
>>> import psutil
|
||||
>>> f = open('file.ext', 'w')
|
||||
>>> p = psutil.Process()
|
||||
>>> p.open_files()
|
||||
[popenfile(path='/home/giampaolo/svn/psutil/file.ext', fd=3)]
|
||||
|
||||
.. warning::
|
||||
on Windows this is not fully reliable as due to some limitations of the
|
||||
Windows API the underlying implementation may hang when retrieving
|
||||
certain file handles.
|
||||
In order to work around that psutil on Windows Vista (and higher) spawns
|
||||
a thread and kills it if it's not responding after 100ms.
|
||||
That implies that on Windows this method is not guaranteed to enumerate
|
||||
all regular file handles (see full discusion
|
||||
`here <https://github.com/giampaolo/psutil/pull/597>`_).
|
||||
|
||||
.. warning::
|
||||
on FreeBSD this method can return files with a 'null' path (see
|
||||
`issue 595 <https://github.com/giampaolo/psutil/pull/595>`_).
|
||||
|
||||
.. versionchanged:: 3.1.0 no longer hangs on Windows.
|
||||
|
||||
.. method:: connections(kind="inet")
|
||||
|
||||
Return socket connections opened by process as a list of namedutples.
|
||||
Return socket connections opened by process as a list of namedtuples.
|
||||
To get system-wide connections use :func:`psutil.net_connections()`.
|
||||
Every namedtuple provides 6 attributes:
|
||||
|
||||
@ -1032,10 +1149,10 @@ Process class
|
||||
>>> p.name()
|
||||
'firefox'
|
||||
>>> p.connections()
|
||||
[pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
|
||||
pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
|
||||
pconn(fd=119, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
|
||||
pconn(fd=123, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
|
||||
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
|
||||
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
|
||||
pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
|
||||
pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
|
||||
|
||||
.. method:: is_running()
|
||||
|
||||
@ -1125,7 +1242,7 @@ Popen class
|
||||
:meth:`send_signal() <psutil.Process.send_signal()>`,
|
||||
:meth:`terminate() <psutil.Process.terminate()>` and
|
||||
:meth:`kill() <psutil.Process.kill()>`
|
||||
so that you don't accidentally terminate another process, fixing
|
||||
so that you can't accidentally terminate another process, fixing
|
||||
http://bugs.python.org/issue6973.
|
||||
|
||||
>>> import psutil
|
||||
@ -1197,6 +1314,10 @@ Constants
|
||||
|
||||
Availability: Windows
|
||||
|
||||
.. versionchanged:: 3.0.0 on Python >= 3.4 these constants are
|
||||
`enums <https://docs.python.org/3/library/enum.html#module-enum>`__
|
||||
instead of a plain integer.
|
||||
|
||||
.. _const-ioprio:
|
||||
.. data:: IOPRIO_CLASS_NONE
|
||||
IOPRIO_CLASS_RT
|
||||
@ -1220,6 +1341,10 @@ Constants
|
||||
|
||||
Availability: Linux
|
||||
|
||||
.. versionchanged:: 3.0.0 on Python >= 3.4 thse constants are
|
||||
`enums <https://docs.python.org/3/library/enum.html#module-enum>`__
|
||||
instead of a plain integer.
|
||||
|
||||
.. _const-rlimit:
|
||||
.. data:: RLIMIT_INFINITY
|
||||
RLIMIT_AS
|
||||
@ -1245,3 +1370,31 @@ Constants
|
||||
`man prlimit <http://linux.die.net/man/2/prlimit>`__ for futher information.
|
||||
|
||||
Availability: Linux
|
||||
|
||||
.. _const-aflink:
|
||||
.. data:: AF_LINK
|
||||
|
||||
Constant which identifies a MAC address associated with a network interface.
|
||||
To be used in conjunction with :func:`psutil.net_if_addrs()`.
|
||||
|
||||
*New in 3.0.0*
|
||||
|
||||
.. _const-duplex:
|
||||
.. data:: NIC_DUPLEX_FULL
|
||||
NIC_DUPLEX_HALF
|
||||
NIC_DUPLEX_UNKNOWN
|
||||
|
||||
Constants which identifies whether a NIC (network interface card) has full or
|
||||
half mode speed. NIC_DUPLEX_FULL means the NIC is able to send and receive
|
||||
data (files) simultaneously, NIC_DUPLEX_FULL means the NIC can either send or
|
||||
receive data at a time.
|
||||
To be used in conjunction with :func:`psutil.net_if_stats()`.
|
||||
|
||||
*New in 3.0.0*
|
||||
|
||||
Development guide
|
||||
=================
|
||||
|
||||
If you plan on hacking on psutil (e.g. want to add a new feature or fix a bug)
|
||||
take a look at the
|
||||
`development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_.
|
||||
|
11
python/psutil/docs/xxx
Normal file
11
python/psutil/docs/xxx
Normal file
@ -0,0 +1,11 @@
|
||||
cpu 1974613 1749 485728 6305758 80280 15 5924 0 0 0
|
||||
|
||||
cpu0 519156 374 132999 5977865 72925 10 1458 0 0 0
|
||||
|
||||
cpu1 524667 401 125931 108960 2110 4 2214 0 0 0
|
||||
|
||||
cpu2 462286 520 117046 109514 2666 0 828 0 0 0
|
||||
|
||||
cpu3 468502 453 109750 109418 2578 0 1424 0 0 0
|
||||
|
||||
|
@ -18,7 +18,6 @@ Device Total Used Free Use % Type Mount
|
||||
import sys
|
||||
import os
|
||||
import psutil
|
||||
from psutil._compat import print_
|
||||
|
||||
|
||||
def bytes2human(n):
|
||||
@ -40,8 +39,8 @@ def bytes2human(n):
|
||||
|
||||
def main():
|
||||
templ = "%-17s %8s %8s %8s %5s%% %9s %s"
|
||||
print_(templ % ("Device", "Total", "Used", "Free", "Use ", "Type",
|
||||
"Mount"))
|
||||
print(templ % ("Device", "Total", "Used", "Free", "Use ", "Type",
|
||||
"Mount"))
|
||||
for part in psutil.disk_partitions(all=False):
|
||||
if os.name == 'nt':
|
||||
if 'cdrom' in part.opts or part.fstype == '':
|
||||
@ -50,7 +49,7 @@ def main():
|
||||
# partition or just hang.
|
||||
continue
|
||||
usage = psutil.disk_usage(part.mountpoint)
|
||||
print_(templ % (
|
||||
print(templ % (
|
||||
part.device,
|
||||
bytes2human(usage.total),
|
||||
bytes2human(usage.used),
|
||||
|
@ -14,15 +14,14 @@ Swap: 0 0 0
|
||||
"""
|
||||
|
||||
import psutil
|
||||
from psutil._compat import print_
|
||||
|
||||
|
||||
def main():
|
||||
virt = psutil.virtual_memory()
|
||||
swap = psutil.swap_memory()
|
||||
templ = "%-7s %10s %10s %10s %10s %10s %10s"
|
||||
print_(templ % ('', 'total', 'used', 'free', 'shared', 'buffers', 'cache'))
|
||||
print_(templ % (
|
||||
print(templ % ('', 'total', 'used', 'free', 'shared', 'buffers', 'cache'))
|
||||
print(templ % (
|
||||
'Mem:',
|
||||
int(virt.total / 1024),
|
||||
int(virt.used / 1024),
|
||||
@ -30,7 +29,7 @@ def main():
|
||||
int(getattr(virt, 'shared', 0) / 1024),
|
||||
int(getattr(virt, 'buffers', 0) / 1024),
|
||||
int(getattr(virt, 'cached', 0) / 1024)))
|
||||
print_(templ % (
|
||||
print(templ % (
|
||||
'Swap:', int(swap.total / 1024),
|
||||
int(swap.used / 1024),
|
||||
int(swap.free / 1024),
|
||||
|
78
python/psutil/examples/ifconfig.py
Normal file
78
python/psutil/examples/ifconfig.py
Normal file
@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
"""
|
||||
A clone of 'ifconfig' on UNIX.
|
||||
|
||||
$ python examples/ifconfig.py
|
||||
lo (speed=0MB, duplex=?, mtu=65536, up=yes):
|
||||
IPv4 address : 127.0.0.1
|
||||
broadcast : 127.0.0.1
|
||||
netmask : 255.0.0.0
|
||||
IPv6 address : ::1
|
||||
netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
|
||||
MAC address : 00:00:00:00:00:00
|
||||
broadcast : 00:00:00:00:00:00
|
||||
|
||||
wlan0 (speed=0MB, duplex=?, mtu=1500, up=yes):
|
||||
IPv4 address : 10.0.3.1
|
||||
broadcast : 10.0.3.255
|
||||
netmask : 255.255.255.0
|
||||
IPv6 address : fe80::3005:adff:fe31:8698
|
||||
netmask : ffff:ffff:ffff:ffff::
|
||||
MAC address : 32:05:ad:31:86:98
|
||||
broadcast : ff:ff:ff:ff:ff:ff
|
||||
|
||||
eth0 (speed=100MB, duplex=full, mtu=1500, up=yes):
|
||||
IPv4 address : 192.168.1.2
|
||||
broadcast : 192.168.1.255
|
||||
netmask : 255.255.255.0
|
||||
IPv6 address : fe80::c685:8ff:fe45:641
|
||||
netmask : ffff:ffff:ffff:ffff::
|
||||
MAC address : c4:85:08:45:06:41
|
||||
broadcast : ff:ff:ff:ff:ff:ff
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
import socket
|
||||
|
||||
import psutil
|
||||
|
||||
|
||||
af_map = {
|
||||
socket.AF_INET: 'IPv4',
|
||||
socket.AF_INET6: 'IPv6',
|
||||
psutil.AF_LINK: 'MAC',
|
||||
}
|
||||
|
||||
duplex_map = {
|
||||
psutil.NIC_DUPLEX_FULL: "full",
|
||||
psutil.NIC_DUPLEX_HALF: "half",
|
||||
psutil.NIC_DUPLEX_UNKNOWN: "?",
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
stats = psutil.net_if_stats()
|
||||
for nic, addrs in psutil.net_if_addrs().items():
|
||||
if nic in stats:
|
||||
print("%s (speed=%sMB, duplex=%s, mtu=%s, up=%s):" % (
|
||||
nic, stats[nic].speed, duplex_map[stats[nic].duplex],
|
||||
stats[nic].mtu, "yes" if stats[nic].isup else "no"))
|
||||
else:
|
||||
print("%s:" % (nic))
|
||||
for addr in addrs:
|
||||
print(" %-8s" % af_map.get(addr.family, addr.family), end="")
|
||||
print(" address : %s" % addr.address)
|
||||
if addr.broadcast:
|
||||
print(" broadcast : %s" % addr.broadcast)
|
||||
if addr.netmask:
|
||||
print(" netmask : %s" % addr.netmask)
|
||||
print("")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -30,14 +30,15 @@ PID USER DISK READ DISK WRITE COMMAND
|
||||
Author: Giampaolo Rodola' <g.rodola@gmail.com>
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import psutil
|
||||
if not hasattr(psutil.Process, 'io_counters') or os.name != 'posix':
|
||||
sys.exit('platform not supported')
|
||||
import time
|
||||
import curses
|
||||
import atexit
|
||||
import time
|
||||
import sys
|
||||
try:
|
||||
import curses
|
||||
except ImportError:
|
||||
sys.exit('platform not supported')
|
||||
|
||||
import psutil
|
||||
|
||||
|
||||
# --- curses stuff
|
||||
@ -116,7 +117,7 @@ def poll(interval):
|
||||
if not p._cmdline:
|
||||
p._cmdline = p.name()
|
||||
p._username = p.username()
|
||||
except psutil.NoSuchProcess:
|
||||
except (psutil.NoSuchProcess, psutil.ZombieProcess):
|
||||
procs.remove(p)
|
||||
disks_after = psutil.disk_io_counters()
|
||||
|
||||
@ -167,7 +168,7 @@ def refresh_window(procs, disks_read, disks_write):
|
||||
def main():
|
||||
try:
|
||||
interval = 0
|
||||
while 1:
|
||||
while True:
|
||||
args = poll(interval)
|
||||
refresh_window(*args)
|
||||
interval = 1
|
||||
|
@ -31,7 +31,6 @@ Sout : 0B
|
||||
"""
|
||||
|
||||
import psutil
|
||||
from psutil._compat import print_
|
||||
|
||||
|
||||
def bytes2human(n):
|
||||
@ -56,13 +55,13 @@ def pprint_ntuple(nt):
|
||||
value = getattr(nt, name)
|
||||
if name != 'percent':
|
||||
value = bytes2human(value)
|
||||
print_('%-10s : %7s' % (name.capitalize(), value))
|
||||
print('%-10s : %7s' % (name.capitalize(), value))
|
||||
|
||||
|
||||
def main():
|
||||
print_('MEMORY\n------')
|
||||
print('MEMORY\n------')
|
||||
pprint_ntuple(psutil.virtual_memory())
|
||||
print_('\nSWAP\n----')
|
||||
print('\nSWAP\n----')
|
||||
pprint_ntuple(psutil.swap_memory())
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -23,7 +23,6 @@ import socket
|
||||
from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM
|
||||
|
||||
import psutil
|
||||
from psutil._compat import print_
|
||||
|
||||
|
||||
AD = "-"
|
||||
@ -38,7 +37,7 @@ proto_map = {
|
||||
|
||||
def main():
|
||||
templ = "%-5s %-30s %-30s %-13s %-6s %s"
|
||||
print_(templ % (
|
||||
print(templ % (
|
||||
"Proto", "Local address", "Remote address", "Status", "PID",
|
||||
"Program name"))
|
||||
proc_names = {}
|
||||
@ -52,7 +51,7 @@ def main():
|
||||
raddr = ""
|
||||
if c.raddr:
|
||||
raddr = "%s:%s" % (c.raddr)
|
||||
print_(templ % (
|
||||
print(templ % (
|
||||
proto_map[(c.family, c.type)],
|
||||
laddr,
|
||||
raddr or AD,
|
||||
|
@ -31,13 +31,13 @@ pkts-sent 0 0
|
||||
pkts-recv 1214470 0
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
if os.name != 'posix':
|
||||
sys.exit('platform not supported')
|
||||
import atexit
|
||||
import curses
|
||||
import time
|
||||
import sys
|
||||
try:
|
||||
import curses
|
||||
except ImportError:
|
||||
sys.exit('platform not supported')
|
||||
|
||||
import psutil
|
||||
|
||||
|
53
python/psutil/examples/pidof.py
Executable file
53
python/psutil/examples/pidof.py
Executable file
@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2009, Giampaolo Rodola', karthikrev. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
|
||||
"""
|
||||
A clone of 'pidof' cmdline utility.
|
||||
$ pidof python
|
||||
1140 1138 1136 1134 1133 1129 1127 1125 1121 1120 1119
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
import psutil
|
||||
import sys
|
||||
|
||||
|
||||
def pidof(pgname):
|
||||
pids = []
|
||||
for proc in psutil.process_iter():
|
||||
# search for matches in the process name and cmdline
|
||||
try:
|
||||
name = proc.name()
|
||||
except psutil.Error:
|
||||
pass
|
||||
else:
|
||||
if name == pgname:
|
||||
pids.append(str(proc.pid))
|
||||
continue
|
||||
|
||||
try:
|
||||
cmdline = proc.cmdline()
|
||||
except psutil.Error:
|
||||
pass
|
||||
else:
|
||||
if cmdline and cmdline[0] == pgname:
|
||||
pids.append(str(proc.pid))
|
||||
|
||||
return pids
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
sys.exit('usage: %s pgname' % __file__)
|
||||
else:
|
||||
pgname = sys.argv[1]
|
||||
pids = pidof(pgname)
|
||||
if pids:
|
||||
print(" ".join(pids))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -33,26 +33,25 @@ ffffffffff600000 0K r-xp [vsyscall]
|
||||
import sys
|
||||
|
||||
import psutil
|
||||
from psutil._compat import print_
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
sys.exit('usage: pmap <pid>')
|
||||
p = psutil.Process(int(sys.argv[1]))
|
||||
print_("pid=%s, name=%s" % (p.pid, p.name()))
|
||||
print("pid=%s, name=%s" % (p.pid, p.name()))
|
||||
templ = "%-16s %10s %-7s %s"
|
||||
print_(templ % ("Address", "RSS", "Mode", "Mapping"))
|
||||
print(templ % ("Address", "RSS", "Mode", "Mapping"))
|
||||
total_rss = 0
|
||||
for m in p.memory_maps(grouped=False):
|
||||
total_rss += m.rss
|
||||
print_(templ % (
|
||||
print(templ % (
|
||||
m.addr.split('-')[0].zfill(16),
|
||||
str(m.rss / 1024) + 'K',
|
||||
m.perms,
|
||||
m.path))
|
||||
print_("-" * 33)
|
||||
print_(templ % ("Total", str(total_rss / 1024) + 'K', '', ''))
|
||||
print("-" * 33)
|
||||
print(templ % ("Total", str(total_rss / 1024) + 'K', '', ''))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -68,8 +68,8 @@ def run(pid):
|
||||
try:
|
||||
p = psutil.Process(pid)
|
||||
pinfo = p.as_dict(ad_value=ACCESS_DENIED)
|
||||
except psutil.NoSuchProcess:
|
||||
sys.exit(str(sys.exc_info()[1]))
|
||||
except psutil.NoSuchProcess as err:
|
||||
sys.exit(str(err))
|
||||
|
||||
try:
|
||||
parent = p.parent()
|
||||
@ -79,13 +79,19 @@ def run(pid):
|
||||
parent = ''
|
||||
except psutil.Error:
|
||||
parent = ''
|
||||
started = datetime.datetime.fromtimestamp(
|
||||
pinfo['create_time']).strftime('%Y-%m-%d %H:%M')
|
||||
if pinfo['create_time'] != ACCESS_DENIED:
|
||||
started = datetime.datetime.fromtimestamp(
|
||||
pinfo['create_time']).strftime('%Y-%m-%d %H:%M')
|
||||
else:
|
||||
started = ACCESS_DENIED
|
||||
io = pinfo.get('io_counters', ACCESS_DENIED)
|
||||
mem = '%s%% (resident=%s, virtual=%s) ' % (
|
||||
round(pinfo['memory_percent'], 1),
|
||||
convert_bytes(pinfo['memory_info'].rss),
|
||||
convert_bytes(pinfo['memory_info'].vms))
|
||||
if pinfo['memory_info'] != ACCESS_DENIED:
|
||||
mem = '%s%% (resident=%s, virtual=%s) ' % (
|
||||
round(pinfo['memory_percent'], 1),
|
||||
convert_bytes(pinfo['memory_info'].rss),
|
||||
convert_bytes(pinfo['memory_info'].vms))
|
||||
else:
|
||||
mem = ACCESS_DENIED
|
||||
children = p.children()
|
||||
|
||||
print_('pid', pinfo['pid'])
|
||||
@ -101,8 +107,7 @@ def run(pid):
|
||||
print_('gids', 'real=%s, effective=%s, saved=%s' % pinfo['gids'])
|
||||
if POSIX:
|
||||
print_('terminal', pinfo['terminal'] or '')
|
||||
if hasattr(p, 'getcwd'):
|
||||
print_('cwd', pinfo['cwd'])
|
||||
print_('cwd', pinfo['cwd'])
|
||||
print_('memory', mem)
|
||||
print_('cpu', '%s%% (user=%s, system=%s)' % (
|
||||
pinfo['cpu_percent'],
|
||||
|
@ -16,7 +16,6 @@ import os
|
||||
import time
|
||||
|
||||
import psutil
|
||||
from psutil._compat import print_
|
||||
|
||||
|
||||
def main():
|
||||
@ -27,8 +26,8 @@ def main():
|
||||
if os.name == 'posix':
|
||||
attrs.append('uids')
|
||||
attrs.append('terminal')
|
||||
print_(templ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY",
|
||||
"START", "TIME", "COMMAND"))
|
||||
print(templ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY",
|
||||
"START", "TIME", "COMMAND"))
|
||||
for p in psutil.process_iter():
|
||||
try:
|
||||
pinfo = p.as_dict(attrs, ad_value='')
|
||||
@ -65,16 +64,17 @@ def main():
|
||||
int(pinfo['memory_info'].rss / 1024) or '?'
|
||||
memp = pinfo['memory_percent'] and \
|
||||
round(pinfo['memory_percent'], 1) or '?'
|
||||
print_(templ % (user[:10],
|
||||
pinfo['pid'],
|
||||
pinfo['cpu_percent'],
|
||||
memp,
|
||||
vms,
|
||||
rss,
|
||||
pinfo.get('terminal', '') or '?',
|
||||
ctime,
|
||||
cputime,
|
||||
pinfo['name'].strip() or '?'))
|
||||
print(templ % (
|
||||
user[:10],
|
||||
pinfo['pid'],
|
||||
pinfo['cpu_percent'],
|
||||
memp,
|
||||
vms,
|
||||
rss,
|
||||
pinfo.get('terminal', '') or '?',
|
||||
ctime,
|
||||
cputime,
|
||||
pinfo['name'].strip() or '?'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
71
python/psutil/examples/pstree.py
Normal file
71
python/psutil/examples/pstree.py
Normal file
@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
"""
|
||||
Similar to 'ps aux --forest' on Linux, prints the process list
|
||||
as a tree structure.
|
||||
|
||||
$ python examples/pstree.py
|
||||
0 ?
|
||||
|- 1 init
|
||||
| |- 289 cgmanager
|
||||
| |- 616 upstart-socket-bridge
|
||||
| |- 628 rpcbind
|
||||
| |- 892 upstart-file-bridge
|
||||
| |- 907 dbus-daemon
|
||||
| |- 978 avahi-daemon
|
||||
| | `_ 979 avahi-daemon
|
||||
| |- 987 NetworkManager
|
||||
| | |- 2242 dnsmasq
|
||||
| | `_ 10699 dhclient
|
||||
| |- 993 polkitd
|
||||
| |- 1061 getty
|
||||
| |- 1066 su
|
||||
| | `_ 1190 salt-minion...
|
||||
...
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
import collections
|
||||
import sys
|
||||
|
||||
import psutil
|
||||
|
||||
|
||||
def print_tree(parent, tree, indent=''):
|
||||
try:
|
||||
name = psutil.Process(parent).name()
|
||||
except psutil.Error:
|
||||
name = "?"
|
||||
print(parent, name)
|
||||
if parent not in tree:
|
||||
return
|
||||
children = tree[parent][:-1]
|
||||
for child in children:
|
||||
sys.stdout.write(indent + "|- ")
|
||||
print_tree(child, tree, indent + "| ")
|
||||
child = tree[parent][-1]
|
||||
sys.stdout.write(indent + "`_ ")
|
||||
print_tree(child, tree, indent + " ")
|
||||
|
||||
|
||||
def main():
|
||||
# construct a dict where 'values' are all the processes
|
||||
# having 'key' as their parent
|
||||
tree = collections.defaultdict(list)
|
||||
for p in psutil.process_iter():
|
||||
try:
|
||||
tree[p.ppid()].append(p.pid)
|
||||
except (psutil.NoSuchProcess, psutil.ZombieProcess):
|
||||
pass
|
||||
# on systems supporting PID 0, PID 0's parent is usually 0
|
||||
if 0 in tree and 0 in tree[0]:
|
||||
tree[0].remove(0)
|
||||
print_tree(min(tree), tree)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -34,14 +34,15 @@ PID USER NI VIRT RES CPU% MEM% TIME+ NAME
|
||||
...
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
if os.name != 'posix':
|
||||
sys.exit('platform not supported')
|
||||
import atexit
|
||||
import curses
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
import atexit
|
||||
import os
|
||||
import time
|
||||
import sys
|
||||
try:
|
||||
import curses
|
||||
except ImportError:
|
||||
sys.exit('platform not supported')
|
||||
|
||||
import psutil
|
||||
|
||||
@ -221,7 +222,7 @@ def refresh_window(procs, procs_status):
|
||||
def main():
|
||||
try:
|
||||
interval = 0
|
||||
while 1:
|
||||
while True:
|
||||
args = poll(interval)
|
||||
refresh_window(*args)
|
||||
interval = 1
|
||||
|
@ -18,13 +18,12 @@ giampaolo pts/9 2014-02-27 01:32 (:0)
|
||||
from datetime import datetime
|
||||
|
||||
import psutil
|
||||
from psutil._compat import print_
|
||||
|
||||
|
||||
def main():
|
||||
users = psutil.users()
|
||||
for user in users:
|
||||
print_("%-15s %-15s %s (%s)" % (
|
||||
print("%-15s %-15s %s (%s)" % (
|
||||
user.name,
|
||||
user.terminal or '-',
|
||||
datetime.fromtimestamp(user.started).strftime("%Y-%m-%d %H:%M"),
|
||||
|
@ -7,18 +7,16 @@ rem psutil ("make.bat build", "make.bat install") and running tests
|
||||
rem ("make.bat test").
|
||||
rem
|
||||
rem This script is modeled after my Windows installation which uses:
|
||||
rem - mingw32 for Python 2.4 and 2.5
|
||||
rem - Visual studio 2008 for Python 2.6, 2.7, 3.2
|
||||
rem - Visual studio 2010 for Python 3.3+
|
||||
rem ...therefore it might not work on your Windows installation.
|
||||
rem
|
||||
rem By default C:\Python27\python.exe is used.
|
||||
rem To compile for a specific Python version run:
|
||||
rem set PYTHON=C:\Python34\python.exe & make.bat build
|
||||
rem
|
||||
rem set PYTHON=C:\Python24\python.exe & make.bat build
|
||||
rem
|
||||
rem If you compile by using mingw on Python 2.4 and 2.5 you need to patch
|
||||
rem distutils first: http://stackoverflow.com/questions/13592192
|
||||
rem To use a different test script:
|
||||
rem set PYTHON=C:\Python34\python.exe & set TSCRIPT=foo.py & make.bat test
|
||||
rem ==========================================================================
|
||||
|
||||
if "%PYTHON%" == "" (
|
||||
@ -28,8 +26,16 @@ if "%TSCRIPT%" == "" (
|
||||
set TSCRIPT=test\test_psutil.py
|
||||
)
|
||||
|
||||
rem Needed to compile using Mingw.
|
||||
set PATH=C:\MinGW\bin;%PATH%
|
||||
set PYTHON26=C:\Python26\python.exe
|
||||
set PYTHON27=C:\Python27\python.exe
|
||||
set PYTHON33=C:\Python33\python.exe
|
||||
set PYTHON34=C:\Python34\python.exe
|
||||
set PYTHON26-64=C:\Python26-64\python.exe
|
||||
set PYTHON27-64=C:\Python27-64\python.exe
|
||||
set PYTHON33-64=C:\Python33-64\python.exe
|
||||
set PYTHON34-64=C:\Python34-64\python.exe
|
||||
|
||||
set ALL_PYTHONS=%PYTHON26% %PYTHON27% %PYTHON33% %PYTHON34% %PYTHON26-64% %PYTHON27-64% %PYTHON33-64% %PYTHON34-64%
|
||||
|
||||
rem Needed to locate the .pypirc file and upload exes on PYPI.
|
||||
set HOME=%USERPROFILE%
|
||||
@ -40,23 +46,21 @@ if "%1" == "help" (
|
||||
:help
|
||||
echo Run `make ^<target^>` where ^<target^> is one of:
|
||||
echo build compile without installing
|
||||
echo build-exes create exe installers in dist directory
|
||||
echo build-wheels create wheel installers in dist directory
|
||||
echo build-all build exes + wheels
|
||||
echo clean clean build files
|
||||
echo flake8 run flake8
|
||||
echo install compile and install
|
||||
echo memtest run memory leak tests
|
||||
echo setup-env install pip, unittest2, wheels for all python versions
|
||||
echo setup-dev-env install pip, pywin32, wheels, etc. for all python versions
|
||||
echo test run tests
|
||||
echo test-memleaks run memory leak tests
|
||||
echo test-process run process related tests
|
||||
echo test-system run system APIs related tests
|
||||
echo uninstall uninstall
|
||||
echo upload-exes upload exe installers on pypi
|
||||
echo upload-wheels upload wheel installers on pypi
|
||||
echo upload-all upload exes + wheels
|
||||
goto :eof
|
||||
)
|
||||
|
||||
if "%1" == "clean" (
|
||||
:clean
|
||||
for /r %%R in (__pycache__) do if exist %%R (rmdir /S /Q %%R)
|
||||
for /r %%R in (*.pyc) do if exist %%R (del /s %%R)
|
||||
for /r %%R in (*.pyd) do if exist %%R (del /s %%R)
|
||||
@ -71,31 +75,25 @@ if "%1" == "clean" (
|
||||
|
||||
if "%1" == "build" (
|
||||
:build
|
||||
if %PYTHON%==C:\Python24\python.exe (
|
||||
%PYTHON% setup.py build -c mingw32
|
||||
) else if %PYTHON%==C:\Python25\python.exe (
|
||||
%PYTHON% setup.py build -c mingw32
|
||||
) else (
|
||||
%PYTHON% setup.py build
|
||||
)
|
||||
"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat"
|
||||
%PYTHON% setup.py build
|
||||
if %errorlevel% neq 0 goto :error
|
||||
rem copies *.pyd files in ./psutil directory in order to allow
|
||||
rem "import psutil" when using the interactive interpreter from
|
||||
rem within this directory.
|
||||
%PYTHON% setup.py build_ext -i
|
||||
if %errorlevel% neq 0 goto :error
|
||||
goto :eof
|
||||
)
|
||||
|
||||
if "%1" == "install" (
|
||||
:install
|
||||
if %PYTHON%==C:\Python24\python.exe (
|
||||
%PYTHON% setup.py build -c mingw32 install
|
||||
) else if %PYTHON%==C:\Python25\python.exe (
|
||||
%PYTHON% setup.py build -c mingw32 install
|
||||
) else (
|
||||
%PYTHON% setup.py build install
|
||||
)
|
||||
call :build
|
||||
%PYTHON% setup.py install
|
||||
goto :eof
|
||||
)
|
||||
|
||||
if "%1" == "uninstall" (
|
||||
:uninstall
|
||||
for %%A in ("%PYTHON%") do (
|
||||
set folder=%%~dpA
|
||||
)
|
||||
@ -106,125 +104,98 @@ if "%1" == "uninstall" (
|
||||
)
|
||||
|
||||
if "%1" == "test" (
|
||||
:test
|
||||
call :install
|
||||
%PYTHON% %TSCRIPT%
|
||||
goto :eof
|
||||
)
|
||||
|
||||
if "%1" == "test-process" (
|
||||
:test
|
||||
call :install
|
||||
%PYTHON% -m unittest -v test.test_psutil.TestProcess
|
||||
goto :eof
|
||||
)
|
||||
|
||||
if "%1" == "test-system" (
|
||||
:test
|
||||
call :install
|
||||
%PYTHON% -m unittest -v test.test_psutil.TestSystem
|
||||
goto :eof
|
||||
)
|
||||
|
||||
if "%1" == "test-memleaks" (
|
||||
:memtest
|
||||
call :install
|
||||
%PYTHON% test\test_memory_leaks.py
|
||||
goto :eof
|
||||
)
|
||||
|
||||
if "%1" == "build-exes" (
|
||||
:build-exes
|
||||
rem mingw 32 versions
|
||||
C:\Python24\python.exe setup.py build -c mingw32 bdist_wininst || goto :error
|
||||
C:\Python25\python.exe setup.py build -c mingw32 bdist_wininst || goto :error
|
||||
rem "standard" 32 bit versions, using VS 2008 (2.6, 2.7) or VS 2010 (3.3+)
|
||||
C:\Python26\python.exe setup.py build bdist_wininst || goto :error
|
||||
C:\Python27\python.exe setup.py build bdist_wininst || goto :error
|
||||
C:\Python33\python.exe setup.py build bdist_wininst || goto :error
|
||||
C:\Python34\python.exe setup.py build bdist_wininst || goto :error
|
||||
rem 64 bit versions
|
||||
rem Python 2.7 + VS 2008 requires vcvars64.bat to be run first:
|
||||
rem http://stackoverflow.com/questions/11072521/
|
||||
rem Windows SDK and .NET Framework 3.5 SP1 also need to be installed (sigh)
|
||||
if "%1" == "build-all" (
|
||||
:build-all
|
||||
"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat"
|
||||
C:\Python27-64\python.exe setup.py build bdist_wininst || goto :error
|
||||
C:\Python33-64\python.exe setup.py build bdist_wininst || goto :error
|
||||
C:\Python34-64\python.exe setup.py build bdist_wininst || goto :error
|
||||
for %%P in (%ALL_PYTHONS%) do (
|
||||
@echo ------------------------------------------------
|
||||
@echo building exe for %%P
|
||||
@echo ------------------------------------------------
|
||||
%%P setup.py build bdist_wininst || goto :error
|
||||
@echo ------------------------------------------------
|
||||
@echo building wheel for %%P
|
||||
@echo ------------------------------------------------
|
||||
%%P setup.py build bdist_wheel || goto :error
|
||||
)
|
||||
echo OK
|
||||
goto :eof
|
||||
)
|
||||
|
||||
if "%1" == "upload-exes" (
|
||||
if "%1" == "upload-all" (
|
||||
:upload-exes
|
||||
rem mingw 32 versions
|
||||
C:\Python25\python.exe setup.py build -c mingw32 bdist_wininst upload || goto :error
|
||||
rem "standard" 32 bit versions, using VS 2008 (2.6, 2.7) or VS 2010 (3.3+)
|
||||
C:\Python26\python.exe setup.py bdist_wininst upload || goto :error
|
||||
C:\Python27\python.exe setup.py bdist_wininst upload || goto :error
|
||||
C:\Python33\python.exe setup.py bdist_wininst upload || goto :error
|
||||
C:\Python34\python.exe setup.py bdist_wininst upload || goto :error
|
||||
rem 64 bit versions
|
||||
C:\Python27-64\python.exe setup.py build bdist_wininst upload || goto :error
|
||||
C:\Python33-64\python.exe setup.py build bdist_wininst upload || goto :error
|
||||
C:\Python34-64\python.exe setup.py build bdist_wininst upload || goto :error
|
||||
"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat"
|
||||
for %%P in (%ALL_PYTHONS%) do (
|
||||
@echo ------------------------------------------------
|
||||
@echo uploading exe for %%P
|
||||
@echo ------------------------------------------------
|
||||
%%P setup.py build bdist_wininst upload || goto :error
|
||||
@echo ------------------------------------------------
|
||||
@echo uploading wheel for %%P
|
||||
@echo ------------------------------------------------
|
||||
%%P setup.py build bdist_wheel upload || goto :error
|
||||
)
|
||||
echo OK
|
||||
goto :eof
|
||||
)
|
||||
|
||||
if "%1" == "setup-env" (
|
||||
if "%1" == "setup-dev-env" (
|
||||
:setup-env
|
||||
C:\python27\python.exe -c "import urllib2; url = urllib2.urlopen('https://raw.github.com/pypa/pip/master/contrib/get-pip.py'); data = url.read(); f = open('get-pip.py', 'w'); f.write(data)"
|
||||
C:\python26\python.exe get-pip.py & C:\python26\scripts\pip install unittest2 wheel --upgrade
|
||||
C:\python27\python.exe get-pip.py & C:\python27\scripts\pip install wheel --upgrade
|
||||
C:\python33\python.exe get-pip.py & C:\python33\scripts\pip install wheel --upgrade
|
||||
C:\python34\scripts\easy_install.exe wheel
|
||||
rem 64-bit versions
|
||||
C:\python27-64\python.exe get-pip.py & C:\python27-64\scripts\pip install wheel --upgrade
|
||||
C:\python33-64\python.exe get-pip.py & C:\python33-64\scripts\pip install wheel --upgrade
|
||||
C:\python34-64\scripts\easy_install.exe wheel
|
||||
@echo ------------------------------------------------
|
||||
@echo downloading pip installer
|
||||
@echo ------------------------------------------------
|
||||
C:\python27\python.exe -c "import urllib2; r = urllib2.urlopen('https://raw.github.com/pypa/pip/master/contrib/get-pip.py'); open('get-pip.py', 'wb').write(r.read())"
|
||||
for %%P in (%ALL_PYTHONS%) do (
|
||||
@echo ------------------------------------------------
|
||||
@echo installing pip for %%P
|
||||
@echo ------------------------------------------------
|
||||
%%P get-pip.py
|
||||
)
|
||||
for %%P in (%ALL_PYTHONS%) do (
|
||||
@echo ------------------------------------------------
|
||||
@echo installing deps for %%P
|
||||
@echo ------------------------------------------------
|
||||
rem mandatory / for unittests
|
||||
%%P -m pip install unittest2 ipaddress mock wmi wheel pypiwin32 --upgrade
|
||||
rem nice to have
|
||||
%%P -m pip install ipdb pep8 pyflakes flake8 --upgrade
|
||||
)
|
||||
goto :eof
|
||||
)
|
||||
|
||||
if "%1" == "build-wheels" (
|
||||
:build-wheels
|
||||
C:\Python26\python.exe setup.py build bdist_wheel || goto :error
|
||||
C:\Python27\python.exe setup.py build bdist_wheel || goto :error
|
||||
C:\Python33\python.exe setup.py build bdist_wheel || goto :error
|
||||
C:\Python34\python.exe setup.py build bdist_wheel || goto :error
|
||||
rem 64 bit versions
|
||||
rem Python 2.7 + VS 2008 requires vcvars64.bat to be run first:
|
||||
rem http://stackoverflow.com/questions/11072521/
|
||||
rem Windows SDK and .NET Framework 3.5 SP1 also need to be installed (sigh)
|
||||
"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat"
|
||||
C:\Python27-64\python.exe setup.py build bdist_wheel || goto :error
|
||||
C:\Python33-64\python.exe setup.py build bdist_wheel || goto :error
|
||||
C:\Python34-64\python.exe setup.py build bdist_wheel || goto :error
|
||||
echo OK
|
||||
goto :eof
|
||||
)
|
||||
|
||||
if "%1" == "upload-wheels" (
|
||||
:build-wheels
|
||||
C:\Python26\python.exe setup.py build bdist_wheel upload || goto :error
|
||||
C:\Python27\python.exe setup.py build bdist_wheel upload || goto :error
|
||||
C:\Python33\python.exe setup.py build bdist_wheel upload || goto :error
|
||||
C:\Python34\python.exe setup.py build bdist_wheel upload || goto :error
|
||||
rem 64 bit versions
|
||||
rem Python 2.7 + VS 2008 requires vcvars64.bat to be run first:
|
||||
rem http://stackoverflow.com/questions/11072521/
|
||||
rem Windows SDK and .NET Framework 3.5 SP1 also need to be installed (sigh)
|
||||
"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat"
|
||||
C:\Python27-64\python.exe setup.py build bdist_wheel upload || goto :error
|
||||
C:\Python33-64\python.exe setup.py build bdist_wheel upload || goto :error
|
||||
C:\Python34-64\python.exe setup.py build bdist_wheel upload || goto :error
|
||||
echo OK
|
||||
if "%1" == "flake8" (
|
||||
:flake8
|
||||
%PYTHON% -c "from flake8.main import main; main()"
|
||||
goto :eof
|
||||
)
|
||||
|
||||
goto :help
|
||||
|
||||
:error
|
||||
echo last command exited with error code %errorlevel%
|
||||
exit /b %errorlevel%
|
||||
@echo ------------------------------------------------
|
||||
@echo last command exited with error code %errorlevel%
|
||||
@echo ------------------------------------------------
|
||||
@exit /b %errorlevel%
|
||||
goto :eof
|
||||
|
434
python/psutil/psutil.egg-info/PKG-INFO
Normal file
434
python/psutil/psutil.egg-info/PKG-INFO
Normal file
@ -0,0 +1,434 @@
|
||||
Metadata-Version: 1.1
|
||||
Name: psutil
|
||||
Version: 3.1.1
|
||||
Summary: psutil is a cross-platform library for retrieving information onrunning processes and system utilization (CPU, memory, disks, network)in Python.
|
||||
Home-page: https://github.com/giampaolo/psutil
|
||||
Author: Giampaolo Rodola
|
||||
Author-email: g.rodola <at> gmail <dot> com
|
||||
License: BSD
|
||||
Description: .. image:: https://img.shields.io/pypi/dm/psutil.svg
|
||||
:target: https://pypi.python.org/pypi/psutil#downloads
|
||||
:alt: Downloads this month
|
||||
|
||||
.. image:: https://api.travis-ci.org/giampaolo/psutil.png?branch=master
|
||||
:target: https://travis-ci.org/giampaolo/psutil
|
||||
:alt: Linux tests (Travis)
|
||||
|
||||
.. image:: https://ci.appveyor.com/api/projects/status/qdwvw7v1t915ywr5/branch/master?svg=true
|
||||
:target: https://ci.appveyor.com/project/giampaolo/psutil
|
||||
:alt: Windows tests (Appveyor)
|
||||
|
||||
.. image:: https://coveralls.io/repos/giampaolo/psutil/badge.svg?branch=master&service=github
|
||||
:target: https://coveralls.io/github/giampaolo/psutil?branch=master
|
||||
:alt: Test coverage (coverall.io)
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/psutil.svg
|
||||
:target: https://pypi.python.org/pypi/psutil/
|
||||
:alt: Latest version
|
||||
|
||||
.. image:: https://img.shields.io/github/stars/giampaolo/psutil.svg
|
||||
:target: https://github.com/giampaolo/psutil/
|
||||
:alt: Github stars
|
||||
|
||||
.. image:: https://img.shields.io/scrutinizer/g/giampaolo/psutil.svg
|
||||
:target: https://scrutinizer-ci.com/g/giampaolo/psutil/
|
||||
:alt: Code quality (scrutinizer-ci.com)
|
||||
|
||||
.. image:: https://img.shields.io/pypi/l/psutil.svg
|
||||
:target: https://pypi.python.org/pypi/psutil/
|
||||
:alt: License
|
||||
|
||||
===========
|
||||
Quick links
|
||||
===========
|
||||
|
||||
- `Home page <https://github.com/giampaolo/psutil>`_
|
||||
- `Documentation <http://pythonhosted.org/psutil/>`_
|
||||
- `Installation <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
|
||||
- `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`_
|
||||
- `Forum <http://groups.google.com/group/psutil/topics>`_
|
||||
- `Blog <http://grodola.blogspot.com/search/label/psutil>`_
|
||||
- `Development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_
|
||||
- `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`_
|
||||
|
||||
=======
|
||||
Summary
|
||||
=======
|
||||
|
||||
psutil (python system and process utilities) is a cross-platform library for
|
||||
retrieving information on **running processes** and **system utilization**
|
||||
(CPU, memory, disks, network) in Python. It is useful mainly for **system
|
||||
monitoring**, **profiling and limiting process resources** and **management of
|
||||
running processes**. It implements many functionalities offered by command line
|
||||
tools such as: ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice,
|
||||
ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap. It currently supports
|
||||
**Linux, Windows, OSX, FreeBSD** and **Sun Solaris**, both **32-bit** and
|
||||
**64-bit** architectures, with Python versions from **2.6 to 3.5** (users of
|
||||
Python 2.4 and 2.5 may use `2.1.3 <https://pypi.python.org/pypi?name=psutil&version=2.1.3&:action=files>`__ version).
|
||||
`PyPy <http://pypy.org/>`__ is also known to work.
|
||||
|
||||
====================
|
||||
Example applications
|
||||
====================
|
||||
|
||||
.. image:: http://psutil.googlecode.com/svn/wiki/images/top-thumb.png
|
||||
:target: http://psutil.googlecode.com/svn/wiki/images/top.png
|
||||
:alt: top
|
||||
|
||||
.. image:: http://psutil.googlecode.com/svn/wiki/images/nettop-thumb.png
|
||||
:target: http://psutil.googlecode.com/svn/wiki/images/nettop.png
|
||||
:alt: nettop
|
||||
|
||||
.. image:: http://psutil.googlecode.com/svn/wiki/images/iotop-thumb.png
|
||||
:target: http://psutil.googlecode.com/svn/wiki/images/iotop.png
|
||||
:alt: iotop
|
||||
|
||||
See also:
|
||||
|
||||
* https://github.com/nicolargo/glances
|
||||
* https://github.com/google/grr
|
||||
* https://github.com/Jahaja/psdash
|
||||
|
||||
==============
|
||||
Example usages
|
||||
==============
|
||||
|
||||
CPU
|
||||
===
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.cpu_times()
|
||||
scputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540, iowait=629.59, irq=0.0, softirq=19.42, steal=0.0, guest=0, nice=0.0)
|
||||
>>>
|
||||
>>> for x in range(3):
|
||||
... psutil.cpu_percent(interval=1)
|
||||
...
|
||||
4.0
|
||||
5.9
|
||||
3.8
|
||||
>>>
|
||||
>>> for x in range(3):
|
||||
... psutil.cpu_percent(interval=1, percpu=True)
|
||||
...
|
||||
[4.0, 6.9, 3.7, 9.2]
|
||||
[7.0, 8.5, 2.4, 2.1]
|
||||
[1.2, 9.0, 9.9, 7.2]
|
||||
>>>
|
||||
>>>
|
||||
>>> for x in range(3):
|
||||
... psutil.cpu_times_percent(interval=1, percpu=False)
|
||||
...
|
||||
scputimes(user=1.5, nice=0.0, system=0.5, idle=96.5, iowait=1.5, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
|
||||
scputimes(user=1.0, nice=0.0, system=0.0, idle=99.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
|
||||
scputimes(user=2.0, nice=0.0, system=0.0, idle=98.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
|
||||
>>>
|
||||
>>> psutil.cpu_count()
|
||||
4
|
||||
>>> psutil.cpu_count(logical=False)
|
||||
2
|
||||
>>>
|
||||
|
||||
Memory
|
||||
======
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> psutil.virtual_memory()
|
||||
svmem(total=8374149120, available=2081050624, percent=75.1, used=8074080256, free=300068864, active=3294920704, inactive=1361616896, buffers=529895424, cached=1251086336)
|
||||
>>> psutil.swap_memory()
|
||||
sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944)
|
||||
>>>
|
||||
|
||||
Disks
|
||||
=====
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> psutil.disk_partitions()
|
||||
[sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
|
||||
sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')]
|
||||
>>>
|
||||
>>> psutil.disk_usage('/')
|
||||
sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
|
||||
>>>
|
||||
>>> psutil.disk_io_counters(perdisk=False)
|
||||
sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220032, write_bytes=24081764352, read_time=5023392, write_time=63199568)
|
||||
>>>
|
||||
|
||||
Network
|
||||
=======
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> psutil.net_io_counters(pernic=True)
|
||||
{'eth0': netio(bytes_sent=485291293, bytes_recv=6004858642, packets_sent=3251564, packets_recv=4787798, errin=0, errout=0, dropin=0, dropout=0),
|
||||
'lo': netio(bytes_sent=2838627, bytes_recv=2838627, packets_sent=30567, packets_recv=30567, errin=0, errout=0, dropin=0, dropout=0)}
|
||||
>>>
|
||||
>>> psutil.net_connections()
|
||||
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
|
||||
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
|
||||
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
|
||||
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None)
|
||||
...]
|
||||
>>>
|
||||
>>> psutil.net_if_addrs()
|
||||
{'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1'),
|
||||
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None),
|
||||
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00')],
|
||||
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255'),
|
||||
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None),
|
||||
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff')]}
|
||||
>>>
|
||||
>>> psutil.net_if_stats()
|
||||
{'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500),
|
||||
'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536)}
|
||||
|
||||
Other system info
|
||||
=================
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> psutil.users()
|
||||
[user(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0),
|
||||
user(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0)]
|
||||
>>>
|
||||
>>> psutil.boot_time()
|
||||
1365519115.0
|
||||
>>>
|
||||
|
||||
Process management
|
||||
==================
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> import psutil
|
||||
>>> psutil.pids()
|
||||
[1, 2, 3, 4, 5, 6, 7, 46, 48, 50, 51, 178, 182, 222, 223, 224,
|
||||
268, 1215, 1216, 1220, 1221, 1243, 1244, 1301, 1601, 2237, 2355,
|
||||
2637, 2774, 3932, 4176, 4177, 4185, 4187, 4189, 4225, 4243, 4245,
|
||||
4263, 4282, 4306, 4311, 4312, 4313, 4314, 4337, 4339, 4357, 4358,
|
||||
4363, 4383, 4395, 4408, 4433, 4443, 4445, 4446, 5167, 5234, 5235,
|
||||
5252, 5318, 5424, 5644, 6987, 7054, 7055, 7071]
|
||||
>>>
|
||||
>>> p = psutil.Process(7055)
|
||||
>>> p.name()
|
||||
'python'
|
||||
>>> p.exe()
|
||||
'/usr/bin/python'
|
||||
>>> p.cwd()
|
||||
'/home/giampaolo'
|
||||
>>> p.cmdline()
|
||||
['/usr/bin/python', 'main.py']
|
||||
>>>
|
||||
>>> p.status()
|
||||
'running'
|
||||
>>> p.username()
|
||||
'giampaolo'
|
||||
>>> p.create_time()
|
||||
1267551141.5019531
|
||||
>>> p.terminal()
|
||||
'/dev/pts/0'
|
||||
>>>
|
||||
>>> p.uids()
|
||||
puids(real=1000, effective=1000, saved=1000)
|
||||
>>> p.gids()
|
||||
pgids(real=1000, effective=1000, saved=1000)
|
||||
>>>
|
||||
>>> p.cpu_times()
|
||||
pcputimes(user=1.02, system=0.31)
|
||||
>>> p.cpu_percent(interval=1.0)
|
||||
12.1
|
||||
>>> p.cpu_affinity()
|
||||
[0, 1, 2, 3]
|
||||
>>> p.cpu_affinity([0]) # set
|
||||
>>>
|
||||
>>> p.memory_percent()
|
||||
0.63423
|
||||
>>>
|
||||
>>> p.memory_info()
|
||||
pmem(rss=7471104, vms=68513792)
|
||||
>>> p.memory_info_ex()
|
||||
extmem(rss=9662464, vms=49192960, shared=3612672, text=2564096, lib=0, data=5754880, dirty=0)
|
||||
>>> p.memory_maps()
|
||||
[pmmap_grouped(path='/lib/x86_64-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0),
|
||||
pmmap_grouped(path='/lib/x86_64-linux-gnu/libc-2.15.so', rss=6384, anonymous=15, swap=0),
|
||||
pmmap_grouped(path='/lib/x86_64-linux-gnu/libcrypto.so.1.0.0', rss=34124, anonymous=1245, swap=0),
|
||||
pmmap_grouped(path='[heap]', rss=54653, anonymous=8192, swap=0),
|
||||
pmmap_grouped(path='[stack]', rss=1542, anonymous=166, swap=0),
|
||||
...]
|
||||
>>>
|
||||
>>> p.io_counters()
|
||||
pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632)
|
||||
>>>
|
||||
>>> p.open_files()
|
||||
[popenfile(path='/home/giampaolo/svn/psutil/somefile', fd=3)]
|
||||
>>>
|
||||
>>> p.connections()
|
||||
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
|
||||
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
|
||||
pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
|
||||
pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
|
||||
>>>
|
||||
>>> p.num_threads()
|
||||
4
|
||||
>>> p.num_fds()
|
||||
8
|
||||
>>> p.threads()
|
||||
[pthread(id=5234, user_time=22.5, system_time=9.2891),
|
||||
pthread(id=5235, user_time=0.0, system_time=0.0),
|
||||
pthread(id=5236, user_time=0.0, system_time=0.0),
|
||||
pthread(id=5237, user_time=0.0707, system_time=1.1)]
|
||||
>>>
|
||||
>>> p.num_ctx_switches()
|
||||
pctxsw(voluntary=78, involuntary=19)
|
||||
>>>
|
||||
>>> p.nice()
|
||||
0
|
||||
>>> p.nice(10) # set
|
||||
>>>
|
||||
>>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # IO priority (Win and Linux only)
|
||||
>>> p.ionice()
|
||||
pionice(ioclass=<IOPriority.IOPRIO_CLASS_IDLE: 3>, value=0)
|
||||
>>>
|
||||
>>> p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) # set resource limits (Linux only)
|
||||
>>> p.rlimit(psutil.RLIMIT_NOFILE)
|
||||
(5, 5)
|
||||
>>>
|
||||
>>> p.suspend()
|
||||
>>> p.resume()
|
||||
>>>
|
||||
>>> p.terminate()
|
||||
>>> p.wait(timeout=3)
|
||||
0
|
||||
>>>
|
||||
>>> psutil.test()
|
||||
USER PID %CPU %MEM VSZ RSS TTY START TIME COMMAND
|
||||
root 1 0.0 0.0 24584 2240 Jun17 00:00 init
|
||||
root 2 0.0 0.0 0 0 Jun17 00:00 kthreadd
|
||||
root 3 0.0 0.0 0 0 Jun17 00:05 ksoftirqd/0
|
||||
...
|
||||
giampaolo 31475 0.0 0.0 20760 3024 /dev/pts/0 Jun19 00:00 python2.4
|
||||
giampaolo 31721 0.0 2.2 773060 181896 00:04 10:30 chrome
|
||||
root 31763 0.0 0.0 0 0 00:05 00:00 kworker/0:1
|
||||
>>>
|
||||
|
||||
Further process APIs
|
||||
====================
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> for p in psutil.process_iter():
|
||||
... print(p)
|
||||
...
|
||||
psutil.Process(pid=1, name='init')
|
||||
psutil.Process(pid=2, name='kthreadd')
|
||||
psutil.Process(pid=3, name='ksoftirqd/0')
|
||||
...
|
||||
>>>
|
||||
>>> def on_terminate(proc):
|
||||
... print("process {} terminated".format(proc))
|
||||
...
|
||||
>>> # waits for multiple processes to terminate
|
||||
>>> gone, alive = psutil.wait_procs(procs_list, 3, callback=on_terminate)
|
||||
>>>
|
||||
|
||||
======
|
||||
Donate
|
||||
======
|
||||
|
||||
A lot of time and effort went into making psutil as it is right now.
|
||||
If you feel psutil is useful to you or your business and want to support its future development please consider donating me (`Giampaolo Rodola' <http://grodola.blogspot.com/p/about.html>`_) some money.
|
||||
I only ask for a small donation, but of course I appreciate any amount.
|
||||
|
||||
.. image:: http://www.paypal.com/en_US/i/btn/x-click-but04.gif
|
||||
:target: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8
|
||||
:alt: Donate via PayPal
|
||||
|
||||
Don't want to donate money? Then maybe you could `write me a recommendation on Linkedin <http://www.linkedin.com/in/grodola>`_.
|
||||
|
||||
============
|
||||
Mailing list
|
||||
============
|
||||
|
||||
http://groups.google.com/group/psutil/
|
||||
|
||||
========
|
||||
Timeline
|
||||
========
|
||||
|
||||
- 2015-07-15: `psutil-3.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.1.tar.gz>`_
|
||||
- 2015-07-15: `psutil-3.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.0.tar.gz>`_
|
||||
- 2015-06-18: `psutil-3.0.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.1.tar.gz>`_
|
||||
- 2015-06-13: `psutil-3.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.0.tar.gz>`_
|
||||
- 2015-02-02: `psutil-2.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.1.tar.gz>`_
|
||||
- 2015-01-06: `psutil-2.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.0.tar.gz>`_
|
||||
- 2014-09-26: `psutil-2.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.3.tar.gz>`_
|
||||
- 2014-09-21: `psutil-2.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.2.tar.gz>`_
|
||||
- 2014-04-30: `psutil-2.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.1.tar.gz>`_
|
||||
- 2014-04-08: `psutil-2.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.0.tar.gz>`_
|
||||
- 2014-03-10: `psutil-2.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.0.0.tar.gz>`_
|
||||
- 2013-11-25: `psutil-1.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.2.1.tar.gz>`_
|
||||
- 2013-11-20: `psutil-1.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.2.0.tar.gz>`_
|
||||
- 2013-11-07: `psutil-1.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.3.tar.gz>`_
|
||||
- 2013-10-22: `psutil-1.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.2.tar.gz>`_
|
||||
- 2013-10-08: `psutil-1.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.1.tar.gz>`_
|
||||
- 2013-09-28: `psutil-1.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.0.tar.gz>`_
|
||||
- 2013-07-12: `psutil-1.0.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.0.1.tar.gz>`_
|
||||
- 2013-07-10: `psutil-1.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.0.0.tar.gz>`_
|
||||
- 2013-05-03: `psutil-0.7.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.7.1.tar.gz>`_
|
||||
- 2013-04-12: `psutil-0.7.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.7.0.tar.gz>`_
|
||||
- 2012-08-16: `psutil-0.6.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.6.1.tar.gz>`_
|
||||
- 2012-08-13: `psutil-0.6.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.6.0.tar.gz>`_
|
||||
- 2012-06-29: `psutil-0.5.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.5.1.tar.gz>`_
|
||||
- 2012-06-27: `psutil-0.5.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.5.0.tar.gz>`_
|
||||
- 2011-12-14: `psutil-0.4.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.4.1.tar.gz>`_
|
||||
- 2011-10-29: `psutil-0.4.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.4.0.tar.gz>`_
|
||||
- 2011-07-08: `psutil-0.3.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.3.0.tar.gz>`_
|
||||
- 2011-03-20: `psutil-0.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.2.1.tar.gz>`_
|
||||
- 2010-11-13: `psutil-0.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.2.0.tar.gz>`_
|
||||
- 2010-03-02: `psutil-0.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.3.tar.gz>`_
|
||||
- 2009-05-06: `psutil-0.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.2.tar.gz>`_
|
||||
- 2009-03-06: `psutil-0.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.1.tar.gz>`_
|
||||
- 2009-01-27: `psutil-0.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.0.tar.gz>`_
|
||||
|
||||
Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,pstree,monitoring,ulimit,prlimit
|
||||
Platform: Platform Independent
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Console
|
||||
Classifier: Environment :: Win32 (MS Windows)
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Intended Audience :: Information Technology
|
||||
Classifier: Intended Audience :: System Administrators
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: MacOS :: MacOS X
|
||||
Classifier: Operating System :: Microsoft :: Windows :: Windows NT/2000
|
||||
Classifier: Operating System :: Microsoft
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Operating System :: POSIX :: BSD :: FreeBSD
|
||||
Classifier: Operating System :: POSIX :: Linux
|
||||
Classifier: Operating System :: POSIX :: SunOS/Solaris
|
||||
Classifier: Operating System :: POSIX
|
||||
Classifier: Programming Language :: C
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.6
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.0
|
||||
Classifier: Programming Language :: Python :: 3.1
|
||||
Classifier: Programming Language :: Python :: 3.2
|
||||
Classifier: Programming Language :: Python :: 3.3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Classifier: Topic :: Software Development :: Libraries
|
||||
Classifier: Topic :: System :: Benchmark
|
||||
Classifier: Topic :: System :: Hardware
|
||||
Classifier: Topic :: System :: Monitoring
|
||||
Classifier: Topic :: System :: Networking :: Monitoring
|
||||
Classifier: Topic :: System :: Networking
|
||||
Classifier: Topic :: System :: Systems Administration
|
||||
Classifier: Topic :: Utilities
|
96
python/psutil/psutil.egg-info/SOURCES.txt
Normal file
96
python/psutil/psutil.egg-info/SOURCES.txt
Normal file
@ -0,0 +1,96 @@
|
||||
.coveragerc
|
||||
.git-pre-commit
|
||||
.gitignore
|
||||
.travis.yml
|
||||
CREDITS
|
||||
HISTORY.rst
|
||||
INSTALL.rst
|
||||
LICENSE
|
||||
MANIFEST.in
|
||||
Makefile
|
||||
README.rst
|
||||
TODO
|
||||
make.bat
|
||||
setup.py
|
||||
tox.ini
|
||||
docs/Makefile
|
||||
docs/README
|
||||
docs/conf.py
|
||||
docs/index.rst
|
||||
docs/make.bat
|
||||
docs/xxx
|
||||
docs/_static/copybutton.js
|
||||
docs/_static/favicon.ico
|
||||
docs/_static/logo.png
|
||||
docs/_static/sidebar.js
|
||||
docs/_template/globaltoc.html
|
||||
docs/_template/indexcontent.html
|
||||
docs/_template/indexsidebar.html
|
||||
docs/_template/page.html
|
||||
docs/_themes/pydoctheme/theme.conf
|
||||
docs/_themes/pydoctheme/static/pydoctheme.css
|
||||
examples/disk_usage.py
|
||||
examples/free.py
|
||||
examples/ifconfig.py
|
||||
examples/iotop.py
|
||||
examples/killall.py
|
||||
examples/meminfo.py
|
||||
examples/netstat.py
|
||||
examples/nettop.py
|
||||
examples/pidof.py
|
||||
examples/pmap.py
|
||||
examples/process_detail.py
|
||||
examples/ps.py
|
||||
examples/pstree.py
|
||||
examples/top.py
|
||||
examples/who.py
|
||||
psutil/__init__.py
|
||||
psutil/_common.py
|
||||
psutil/_compat.py
|
||||
psutil/_psbsd.py
|
||||
psutil/_pslinux.py
|
||||
psutil/_psosx.py
|
||||
psutil/_psposix.py
|
||||
psutil/_pssunos.py
|
||||
psutil/_psutil_bsd.c
|
||||
psutil/_psutil_bsd.h
|
||||
psutil/_psutil_common.c
|
||||
psutil/_psutil_common.h
|
||||
psutil/_psutil_linux.c
|
||||
psutil/_psutil_linux.h
|
||||
psutil/_psutil_osx.c
|
||||
psutil/_psutil_osx.h
|
||||
psutil/_psutil_posix.c
|
||||
psutil/_psutil_posix.h
|
||||
psutil/_psutil_sunos.c
|
||||
psutil/_psutil_sunos.h
|
||||
psutil/_psutil_windows.c
|
||||
psutil/_psutil_windows.h
|
||||
psutil/_pswindows.py
|
||||
psutil.egg-info/PKG-INFO
|
||||
psutil.egg-info/SOURCES.txt
|
||||
psutil.egg-info/dependency_links.txt
|
||||
psutil.egg-info/top_level.txt
|
||||
psutil/arch/bsd/process_info.c
|
||||
psutil/arch/bsd/process_info.h
|
||||
psutil/arch/osx/process_info.c
|
||||
psutil/arch/osx/process_info.h
|
||||
psutil/arch/windows/glpi.h
|
||||
psutil/arch/windows/inet_ntop.c
|
||||
psutil/arch/windows/inet_ntop.h
|
||||
psutil/arch/windows/ntextapi.h
|
||||
psutil/arch/windows/process_handles.c
|
||||
psutil/arch/windows/process_handles.h
|
||||
psutil/arch/windows/process_info.c
|
||||
psutil/arch/windows/process_info.h
|
||||
psutil/arch/windows/security.c
|
||||
psutil/arch/windows/security.h
|
||||
test/README.rst
|
||||
test/_bsd.py
|
||||
test/_linux.py
|
||||
test/_osx.py
|
||||
test/_posix.py
|
||||
test/_sunos.py
|
||||
test/_windows.py
|
||||
test/test_memory_leaks.py
|
||||
test/test_psutil.py
|
1
python/psutil/psutil.egg-info/dependency_links.txt
Normal file
1
python/psutil/psutil.egg-info/dependency_links.txt
Normal file
@ -0,0 +1 @@
|
||||
|
1
python/psutil/psutil.egg-info/top_level.txt
Normal file
1
python/psutil/psutil.egg-info/top_level.txt
Normal file
@ -0,0 +1 @@
|
||||
psutil
|
File diff suppressed because it is too large
Load Diff
@ -8,19 +8,23 @@
|
||||
|
||||
from __future__ import division
|
||||
import errno
|
||||
import functools
|
||||
import os
|
||||
import socket
|
||||
import stat
|
||||
import sys
|
||||
import warnings
|
||||
from collections import namedtuple
|
||||
from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM
|
||||
try:
|
||||
import threading
|
||||
except ImportError:
|
||||
import dummy_threading as threading
|
||||
|
||||
from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM
|
||||
if sys.version_info >= (3, 4):
|
||||
import enum
|
||||
else:
|
||||
enum = None
|
||||
|
||||
from psutil._compat import namedtuple, wraps
|
||||
|
||||
# --- constants
|
||||
|
||||
@ -53,6 +57,18 @@ CONN_LISTEN = "LISTEN"
|
||||
CONN_CLOSING = "CLOSING"
|
||||
CONN_NONE = "NONE"
|
||||
|
||||
if enum is None:
|
||||
NIC_DUPLEX_FULL = 2
|
||||
NIC_DUPLEX_HALF = 1
|
||||
NIC_DUPLEX_UNKNOWN = 0
|
||||
else:
|
||||
class NicDuplex(enum.IntEnum):
|
||||
NIC_DUPLEX_FULL = 2
|
||||
NIC_DUPLEX_HALF = 1
|
||||
NIC_DUPLEX_UNKNOWN = 0
|
||||
|
||||
globals().update(NicDuplex.__members__)
|
||||
|
||||
|
||||
# --- functions
|
||||
|
||||
@ -82,7 +98,7 @@ def memoize(fun):
|
||||
>>> foo.cache_clear()
|
||||
>>>
|
||||
"""
|
||||
@wraps(fun)
|
||||
@functools.wraps(fun)
|
||||
def wrapper(*args, **kwargs):
|
||||
key = (args, frozenset(sorted(kwargs.items())))
|
||||
lock.acquire()
|
||||
@ -109,43 +125,6 @@ def memoize(fun):
|
||||
return wrapper
|
||||
|
||||
|
||||
# http://code.activestate.com/recipes/577819-deprecated-decorator/
|
||||
def deprecated(replacement=None):
|
||||
"""A decorator which can be used to mark functions as deprecated."""
|
||||
def outer(fun):
|
||||
msg = "psutil.%s is deprecated" % fun.__name__
|
||||
if replacement is not None:
|
||||
msg += "; use %s instead" % replacement
|
||||
if fun.__doc__ is None:
|
||||
fun.__doc__ = msg
|
||||
|
||||
@wraps(fun)
|
||||
def inner(*args, **kwargs):
|
||||
warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
|
||||
return fun(*args, **kwargs)
|
||||
|
||||
return inner
|
||||
return outer
|
||||
|
||||
|
||||
def deprecated_method(replacement):
|
||||
"""A decorator which can be used to mark a method as deprecated
|
||||
'replcement' is the method name which will be called instead.
|
||||
"""
|
||||
def outer(fun):
|
||||
msg = "%s() is deprecated; use %s() instead" % (
|
||||
fun.__name__, replacement)
|
||||
if fun.__doc__ is None:
|
||||
fun.__doc__ = msg
|
||||
|
||||
@wraps(fun)
|
||||
def inner(self, *args, **kwargs):
|
||||
warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
|
||||
return getattr(self, replacement)(*args, **kwargs)
|
||||
return inner
|
||||
return outer
|
||||
|
||||
|
||||
def isfile_strict(path):
|
||||
"""Same as os.path.isfile() but does not swallow EACCES / EPERM
|
||||
exceptions, see:
|
||||
@ -153,8 +132,7 @@ def isfile_strict(path):
|
||||
"""
|
||||
try:
|
||||
st = os.stat(path)
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
except OSError as err:
|
||||
if err.errno in (errno.EPERM, errno.EACCES):
|
||||
raise
|
||||
return False
|
||||
@ -162,6 +140,30 @@ def isfile_strict(path):
|
||||
return stat.S_ISREG(st.st_mode)
|
||||
|
||||
|
||||
def sockfam_to_enum(num):
|
||||
"""Convert a numeric socket family value to an IntEnum member.
|
||||
If it's not a known member, return the numeric value itself.
|
||||
"""
|
||||
if enum is None:
|
||||
return num
|
||||
try:
|
||||
return socket.AddressFamily(num)
|
||||
except (ValueError, AttributeError):
|
||||
return num
|
||||
|
||||
|
||||
def socktype_to_enum(num):
|
||||
"""Convert a numeric socket type value to an IntEnum member.
|
||||
If it's not a known member, return the numeric value itself.
|
||||
"""
|
||||
if enum is None:
|
||||
return num
|
||||
try:
|
||||
return socket.AddressType(num)
|
||||
except (ValueError, AttributeError):
|
||||
return num
|
||||
|
||||
|
||||
# --- Process.connections() 'kind' parameter mapping
|
||||
|
||||
conn_tmap = {
|
||||
@ -186,7 +188,7 @@ if AF_UNIX is not None:
|
||||
"unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]),
|
||||
})
|
||||
|
||||
del AF_INET, AF_INET6, AF_UNIX, SOCK_STREAM, SOCK_DGRAM, socket
|
||||
del AF_INET, AF_INET6, AF_UNIX, SOCK_STREAM, SOCK_DGRAM
|
||||
|
||||
|
||||
# --- namedtuples for psutil.* system-related functions
|
||||
@ -212,6 +214,10 @@ suser = namedtuple('suser', ['name', 'terminal', 'host', 'started'])
|
||||
# psutil.net_connections()
|
||||
sconn = namedtuple('sconn', ['fd', 'family', 'type', 'laddr', 'raddr',
|
||||
'status', 'pid'])
|
||||
# psutil.net_if_addrs()
|
||||
snic = namedtuple('snic', ['family', 'address', 'netmask', 'broadcast'])
|
||||
# psutil.net_if_stats()
|
||||
snicstats = namedtuple('snicstats', ['isup', 'duplex', 'speed', 'mtu'])
|
||||
|
||||
|
||||
# --- namedtuples for psutil.Process methods
|
||||
@ -235,24 +241,6 @@ pio = namedtuple('pio', ['read_count', 'write_count',
|
||||
pionice = namedtuple('pionice', ['ioclass', 'value'])
|
||||
# psutil.Process.ctx_switches()
|
||||
pctxsw = namedtuple('pctxsw', ['voluntary', 'involuntary'])
|
||||
|
||||
|
||||
# --- misc
|
||||
|
||||
# backward compatibility layer for Process.connections() ntuple
|
||||
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
|
||||
# psutil.Process.connections()
|
||||
pconn = namedtuple('pconn', ['fd', 'family', 'type', 'laddr', 'raddr',
|
||||
'status'])
|
||||
|
@ -6,59 +6,29 @@
|
||||
|
||||
"""Module which provides compatibility with older Python versions."""
|
||||
|
||||
__all__ = ["PY3", "int", "long", "xrange", "exec_", "callable", "namedtuple",
|
||||
"property", "wraps", "defaultdict", "update_wrapper", "lru_cache"]
|
||||
|
||||
import collections
|
||||
import functools
|
||||
import sys
|
||||
try:
|
||||
import __builtin__
|
||||
except ImportError:
|
||||
import builtins as __builtin__ # py3
|
||||
|
||||
__all__ = ["PY3", "long", "xrange", "unicode", "callable", "lru_cache"]
|
||||
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
if PY3:
|
||||
int = int
|
||||
long = int
|
||||
xrange = range
|
||||
unicode = str
|
||||
basestring = str
|
||||
exec_ = getattr(__builtin__, "exec")
|
||||
print_ = getattr(__builtin__, "print")
|
||||
|
||||
def u(s):
|
||||
return s
|
||||
|
||||
def b(s):
|
||||
return s.encode("latin-1")
|
||||
else:
|
||||
int = int
|
||||
long = long
|
||||
xrange = xrange
|
||||
unicode = unicode
|
||||
basestring = basestring
|
||||
|
||||
def u(s):
|
||||
return unicode(s, "unicode_escape")
|
||||
|
||||
def b(s):
|
||||
return s
|
||||
|
||||
def exec_(code, globs=None, locs=None):
|
||||
if globs is None:
|
||||
frame = _sys._getframe(1)
|
||||
globs = frame.f_globals
|
||||
if locs is None:
|
||||
locs = frame.f_locals
|
||||
del frame
|
||||
elif locs is None:
|
||||
locs = globs
|
||||
exec("""exec code in globs, locs""")
|
||||
|
||||
def print_(s):
|
||||
sys.stdout.write(s + '\n')
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
# removed in 3.0, reintroduced in 3.2
|
||||
try:
|
||||
@ -70,222 +40,6 @@ except NameError:
|
||||
|
||||
# --- stdlib additions
|
||||
|
||||
# py 2.6 collections.namedtuple
|
||||
# Taken from: http://code.activestate.com/recipes/500261/
|
||||
# Credits: Raymond Hettinger
|
||||
try:
|
||||
from collections import namedtuple
|
||||
except ImportError:
|
||||
from operator import itemgetter as _itemgetter
|
||||
from keyword import iskeyword as _iskeyword
|
||||
import sys as _sys
|
||||
|
||||
def namedtuple(typename, field_names, verbose=False, rename=False):
|
||||
"""A collections.namedtuple implementation, see:
|
||||
http://docs.python.org/library/collections.html#namedtuple
|
||||
"""
|
||||
if isinstance(field_names, basestring):
|
||||
field_names = field_names.replace(',', ' ').split()
|
||||
field_names = tuple(map(str, field_names))
|
||||
if rename:
|
||||
names = list(field_names)
|
||||
seen = set()
|
||||
for i, name in enumerate(names):
|
||||
if ((not min(c.isalnum() or c == '_' for c in name)
|
||||
or _iskeyword(name)
|
||||
or not name or name[0].isdigit()
|
||||
or name.startswith('_')
|
||||
or name in seen)):
|
||||
names[i] = '_%d' % i
|
||||
seen.add(name)
|
||||
field_names = tuple(names)
|
||||
for name in (typename,) + field_names:
|
||||
if not min(c.isalnum() or c == '_' for c in name):
|
||||
raise ValueError('Type names and field names can only contain '
|
||||
'alphanumeric characters and underscores: %r'
|
||||
% name)
|
||||
if _iskeyword(name):
|
||||
raise ValueError('Type names and field names cannot be a '
|
||||
'keyword: %r' % name)
|
||||
if name[0].isdigit():
|
||||
raise ValueError('Type names and field names cannot start '
|
||||
'with a number: %r' % name)
|
||||
seen_names = set()
|
||||
for name in field_names:
|
||||
if name.startswith('_') and not rename:
|
||||
raise ValueError(
|
||||
'Field names cannot start with an underscore: %r' % name)
|
||||
if name in seen_names:
|
||||
raise ValueError('Encountered duplicate field name: %r' % name)
|
||||
seen_names.add(name)
|
||||
|
||||
numfields = len(field_names)
|
||||
argtxt = repr(field_names).replace("'", "")[1:-1]
|
||||
reprtxt = ', '.join('%s=%%r' % name for name in field_names)
|
||||
template = '''class %(typename)s(tuple):
|
||||
'%(typename)s(%(argtxt)s)' \n
|
||||
__slots__ = () \n
|
||||
_fields = %(field_names)r \n
|
||||
def __new__(_cls, %(argtxt)s):
|
||||
return _tuple.__new__(_cls, (%(argtxt)s)) \n
|
||||
@classmethod
|
||||
def _make(cls, iterable, new=tuple.__new__, len=len):
|
||||
'Make a new %(typename)s object from a sequence or iterable'
|
||||
result = new(cls, iterable)
|
||||
if len(result) != %(numfields)d:
|
||||
raise TypeError(
|
||||
'Expected %(numfields)d arguments, got %%d' %% len(result))
|
||||
return result \n
|
||||
def __repr__(self):
|
||||
return '%(typename)s(%(reprtxt)s)' %% self \n
|
||||
def _asdict(self):
|
||||
'Return a new dict which maps field names to their values'
|
||||
return dict(zip(self._fields, self)) \n
|
||||
def _replace(_self, **kwds):
|
||||
result = _self._make(map(kwds.pop, %(field_names)r, _self))
|
||||
if kwds:
|
||||
raise ValueError(
|
||||
'Got unexpected field names: %%r' %% kwds.keys())
|
||||
return result \n
|
||||
def __getnewargs__(self):
|
||||
return tuple(self) \n\n''' % locals()
|
||||
for i, name in enumerate(field_names):
|
||||
template += ' %s = _property(_itemgetter(%d))\n' % (name, i)
|
||||
if verbose:
|
||||
sys.stdout.write(template + '\n')
|
||||
sys.stdout.flush()
|
||||
|
||||
namespace = dict(
|
||||
_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
|
||||
_property=property, _tuple=tuple)
|
||||
try:
|
||||
exec_(template, namespace)
|
||||
except SyntaxError:
|
||||
e = sys.exc_info()[1]
|
||||
raise SyntaxError(e.message + ':\n' + template)
|
||||
result = namespace[typename]
|
||||
try:
|
||||
result.__module__ = _sys._getframe(
|
||||
1).f_globals.get('__name__', '__main__')
|
||||
except (AttributeError, ValueError):
|
||||
pass
|
||||
|
||||
return result
|
||||
|
||||
|
||||
# hack to support property getter/setter/deleter on python < 2.6
|
||||
# http://docs.python.org/library/functions.html?highlight=property#property
|
||||
if hasattr(property, 'setter'):
|
||||
property = property
|
||||
else:
|
||||
class property(__builtin__.property):
|
||||
__metaclass__ = type
|
||||
|
||||
def __init__(self, fget, *args, **kwargs):
|
||||
super(property, self).__init__(fget, *args, **kwargs)
|
||||
self.__doc__ = fget.__doc__
|
||||
|
||||
def getter(self, method):
|
||||
return property(method, self.fset, self.fdel)
|
||||
|
||||
def setter(self, method):
|
||||
return property(self.fget, method, self.fdel)
|
||||
|
||||
def deleter(self, method):
|
||||
return property(self.fget, self.fset, method)
|
||||
|
||||
|
||||
# py 2.5 collections.defauldict
|
||||
# Taken from:
|
||||
# http://code.activestate.com/recipes/523034-emulate-collectionsdefaultdict/
|
||||
# Credits: Jason Kirtland
|
||||
try:
|
||||
from collections import defaultdict
|
||||
except ImportError:
|
||||
class defaultdict(dict):
|
||||
"""Dict subclass that calls a factory function to supply
|
||||
missing values:
|
||||
http://docs.python.org/library/collections.html#collections.defaultdict
|
||||
"""
|
||||
|
||||
def __init__(self, default_factory=None, *a, **kw):
|
||||
if ((default_factory is not None and
|
||||
not hasattr(default_factory, '__call__'))):
|
||||
raise TypeError('first argument must be callable')
|
||||
dict.__init__(self, *a, **kw)
|
||||
self.default_factory = default_factory
|
||||
|
||||
def __getitem__(self, key):
|
||||
try:
|
||||
return dict.__getitem__(self, key)
|
||||
except KeyError:
|
||||
return self.__missing__(key)
|
||||
|
||||
def __missing__(self, key):
|
||||
if self.default_factory is None:
|
||||
raise KeyError(key)
|
||||
self[key] = value = self.default_factory()
|
||||
return value
|
||||
|
||||
def __reduce__(self):
|
||||
if self.default_factory is None:
|
||||
args = tuple()
|
||||
else:
|
||||
args = self.default_factory,
|
||||
return type(self), args, None, None, self.items()
|
||||
|
||||
def copy(self):
|
||||
return self.__copy__()
|
||||
|
||||
def __copy__(self):
|
||||
return type(self)(self.default_factory, self)
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
import copy
|
||||
return type(self)(self.default_factory,
|
||||
copy.deepcopy(self.items()))
|
||||
|
||||
def __repr__(self):
|
||||
return 'defaultdict(%s, %s)' % (self.default_factory,
|
||||
dict.__repr__(self))
|
||||
|
||||
|
||||
# py 2.5 functools.wraps
|
||||
try:
|
||||
from functools import wraps
|
||||
except ImportError:
|
||||
def wraps(original):
|
||||
def inner(fn):
|
||||
for attribute in ['__module__', '__name__', '__doc__']:
|
||||
setattr(fn, attribute, getattr(original, attribute))
|
||||
for attribute in ['__dict__']:
|
||||
if hasattr(fn, attribute):
|
||||
getattr(fn, attribute).update(getattr(original, attribute))
|
||||
else:
|
||||
setattr(fn, attribute,
|
||||
getattr(original, attribute).copy())
|
||||
return fn
|
||||
return inner
|
||||
|
||||
|
||||
# py 2.5 functools.update_wrapper
|
||||
try:
|
||||
from functools import update_wrapper
|
||||
except ImportError:
|
||||
WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
|
||||
WRAPPER_UPDATES = ('__dict__',)
|
||||
|
||||
def update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS,
|
||||
updated=WRAPPER_UPDATES):
|
||||
"""Update a wrapper function to look like the wrapped function, see:
|
||||
http://docs.python.org/library/functools.html#functools.update_wrapper
|
||||
"""
|
||||
for attr in assigned:
|
||||
setattr(wrapper, attr, getattr(wrapped, attr))
|
||||
for attr in updated:
|
||||
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
|
||||
return wrapper
|
||||
|
||||
|
||||
# py 3.2 functools.lru_cache
|
||||
# Taken from: http://code.activestate.com/recipes/578078
|
||||
@ -298,8 +52,8 @@ except ImportError:
|
||||
except ImportError:
|
||||
from dummy_threading import RLock
|
||||
|
||||
_CacheInfo = namedtuple("CacheInfo",
|
||||
["hits", "misses", "maxsize", "currsize"])
|
||||
_CacheInfo = collections.namedtuple(
|
||||
"CacheInfo", ["hits", "misses", "maxsize", "currsize"])
|
||||
|
||||
class _HashedSeq(list):
|
||||
__slots__ = 'hashvalue'
|
||||
@ -430,6 +184,6 @@ except ImportError:
|
||||
wrapper.__wrapped__ = user_function
|
||||
wrapper.cache_info = cache_info
|
||||
wrapper.cache_clear = cache_clear
|
||||
return update_wrapper(wrapper, user_function)
|
||||
return functools.update_wrapper(wrapper, user_function)
|
||||
|
||||
return decorating_function
|
||||
|
@ -7,15 +7,17 @@
|
||||
"""FreeBSD platform implementation."""
|
||||
|
||||
import errno
|
||||
import functools
|
||||
import os
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
from collections import namedtuple
|
||||
|
||||
from psutil import _common
|
||||
from psutil import _psposix
|
||||
from psutil._common import conn_tmap, usage_percent
|
||||
from psutil._compat import namedtuple, wraps
|
||||
import _psutil_bsd as cext
|
||||
import _psutil_posix
|
||||
from . import _common
|
||||
from . import _psposix
|
||||
from . import _psutil_bsd as cext
|
||||
from . import _psutil_posix as cext_posix
|
||||
from ._common import conn_tmap, usage_percent, sockfam_to_enum
|
||||
from ._common import socktype_to_enum
|
||||
|
||||
|
||||
__extra__all__ = []
|
||||
@ -48,6 +50,7 @@ TCP_STATUSES = {
|
||||
}
|
||||
|
||||
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
|
||||
AF_LINK = cext_posix.AF_LINK
|
||||
|
||||
# extend base mem ntuple with BSD-specific memory metrics
|
||||
svmem = namedtuple(
|
||||
@ -63,12 +66,13 @@ pmmap_ext = namedtuple(
|
||||
|
||||
# set later from __init__.py
|
||||
NoSuchProcess = None
|
||||
ZombieProcess = None
|
||||
AccessDenied = None
|
||||
TimeoutExpired = None
|
||||
|
||||
|
||||
def virtual_memory():
|
||||
"""System virtual memory as a namedutple."""
|
||||
"""System virtual memory as a namedtuple."""
|
||||
mem = cext.virtual_mem()
|
||||
total, free, active, inactive, wired, cached, buffers, shared = mem
|
||||
avail = inactive + cached + free
|
||||
@ -86,14 +90,14 @@ def swap_memory():
|
||||
|
||||
|
||||
def cpu_times():
|
||||
"""Return system per-CPU times as a named tuple"""
|
||||
"""Return system per-CPU times as a namedtuple"""
|
||||
user, nice, system, idle, irq = cext.cpu_times()
|
||||
return scputimes(user, nice, system, idle, irq)
|
||||
|
||||
|
||||
if hasattr(cext, "per_cpu_times"):
|
||||
def per_cpu_times():
|
||||
"""Return system CPU times as a named tuple"""
|
||||
"""Return system CPU times as a namedtuple"""
|
||||
ret = []
|
||||
for cpu_t in cext.per_cpu_times():
|
||||
user, nice, system, idle, irq = cpu_t
|
||||
@ -131,19 +135,25 @@ def cpu_count_physical():
|
||||
# We may get None in case "sysctl kern.sched.topology_spec"
|
||||
# is not supported on this BSD version, in which case we'll mimic
|
||||
# os.cpu_count() and return None.
|
||||
ret = None
|
||||
s = cext.cpu_count_phys()
|
||||
if s is not None:
|
||||
# get rid of padding chars appended at the end of the string
|
||||
index = s.rfind("</groups>")
|
||||
if index != -1:
|
||||
s = s[:index + 9]
|
||||
if sys.version_info >= (2, 5):
|
||||
import xml.etree.ElementTree as ET
|
||||
root = ET.fromstring(s)
|
||||
return len(root.findall('group/children/group/cpu')) or None
|
||||
else:
|
||||
s = s[s.find('<children>'):]
|
||||
return s.count("<cpu") or None
|
||||
root = ET.fromstring(s)
|
||||
try:
|
||||
ret = len(root.findall('group/children/group/cpu')) or None
|
||||
finally:
|
||||
# needed otherwise it will memleak
|
||||
root.clear()
|
||||
if not ret:
|
||||
# If logical CPUs are 1 it's obvious we'll have only 1
|
||||
# physical CPU.
|
||||
if cpu_count_logical() == 1:
|
||||
return 1
|
||||
return ret
|
||||
|
||||
|
||||
def boot_time():
|
||||
@ -183,15 +193,36 @@ def net_connections(kind):
|
||||
raise ValueError("invalid %r kind argument; choose between %s"
|
||||
% (kind, ', '.join([repr(x) for x in conn_tmap])))
|
||||
families, types = conn_tmap[kind]
|
||||
ret = []
|
||||
ret = set()
|
||||
rawlist = cext.net_connections()
|
||||
for item in rawlist:
|
||||
fd, fam, type, laddr, raddr, status, pid = item
|
||||
# TODO: apply filter at C level
|
||||
if fam in families and type in types:
|
||||
status = TCP_STATUSES[status]
|
||||
try:
|
||||
status = TCP_STATUSES[status]
|
||||
except KeyError:
|
||||
# XXX: Not sure why this happens. I saw this occurring
|
||||
# with IPv6 sockets opened by 'vim'. Those sockets
|
||||
# have a very short lifetime so maybe the kernel
|
||||
# can't initialize their status?
|
||||
status = TCP_STATUSES[cext.PSUTIL_CONN_NONE]
|
||||
fam = sockfam_to_enum(fam)
|
||||
type = socktype_to_enum(type)
|
||||
nt = _common.sconn(fd, fam, type, laddr, raddr, status, pid)
|
||||
ret.append(nt)
|
||||
ret.add(nt)
|
||||
return list(ret)
|
||||
|
||||
|
||||
def net_if_stats():
|
||||
"""Get NIC stats (isup, duplex, speed, mtu)."""
|
||||
names = net_io_counters().keys()
|
||||
ret = {}
|
||||
for name in names:
|
||||
isup, duplex, speed, mtu = cext_posix.net_if_stats(name)
|
||||
if hasattr(_common, 'NicDuplex'):
|
||||
duplex = _common.NicDuplex(duplex)
|
||||
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
|
||||
return ret
|
||||
|
||||
|
||||
@ -200,23 +231,27 @@ pid_exists = _psposix.pid_exists
|
||||
disk_usage = _psposix.disk_usage
|
||||
net_io_counters = cext.net_io_counters
|
||||
disk_io_counters = cext.disk_io_counters
|
||||
net_if_addrs = cext_posix.net_if_addrs
|
||||
|
||||
|
||||
def wrap_exceptions(fun):
|
||||
"""Decorator which translates bare OSError exceptions into
|
||||
NoSuchProcess and AccessDenied.
|
||||
"""
|
||||
@wraps(fun)
|
||||
@functools.wraps(fun)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
return fun(self, *args, **kwargs)
|
||||
except OSError:
|
||||
except OSError as err:
|
||||
# support for private module import
|
||||
if NoSuchProcess is None or AccessDenied is None:
|
||||
if (NoSuchProcess is None or AccessDenied is None or
|
||||
ZombieProcess is None):
|
||||
raise
|
||||
err = sys.exc_info()[1]
|
||||
if err.errno == errno.ESRCH:
|
||||
raise NoSuchProcess(self.pid, self._name)
|
||||
if not pid_exists(self.pid):
|
||||
raise NoSuchProcess(self.pid, self._name)
|
||||
else:
|
||||
raise ZombieProcess(self.pid, self._name, self._ppid)
|
||||
if err.errno in (errno.EPERM, errno.EACCES):
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
raise
|
||||
@ -226,11 +261,12 @@ def wrap_exceptions(fun):
|
||||
class Process(object):
|
||||
"""Wrapper class around underlying C implementation."""
|
||||
|
||||
__slots__ = ["pid", "_name"]
|
||||
__slots__ = ["pid", "_name", "_ppid"]
|
||||
|
||||
def __init__(self, pid):
|
||||
self.pid = pid
|
||||
self._name = None
|
||||
self._ppid = None
|
||||
|
||||
@wrap_exceptions
|
||||
def name(self):
|
||||
@ -312,6 +348,8 @@ class Process(object):
|
||||
ret = []
|
||||
for item in rawlist:
|
||||
fd, fam, type, laddr, raddr, status = item
|
||||
fam = sockfam_to_enum(fam)
|
||||
type = socktype_to_enum(type)
|
||||
status = TCP_STATUSES[status]
|
||||
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
|
||||
ret.append(nt)
|
||||
@ -329,11 +367,11 @@ class Process(object):
|
||||
|
||||
@wrap_exceptions
|
||||
def nice_get(self):
|
||||
return _psutil_posix.getpriority(self.pid)
|
||||
return cext_posix.getpriority(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def nice_set(self, value):
|
||||
return _psutil_posix.setpriority(self.pid, value)
|
||||
return cext_posix.setpriority(self.pid, value)
|
||||
|
||||
@wrap_exceptions
|
||||
def status(self):
|
||||
@ -387,3 +425,31 @@ class Process(object):
|
||||
proc_cwd = _not_implemented
|
||||
memory_maps = _not_implemented
|
||||
num_fds = _not_implemented
|
||||
|
||||
@wrap_exceptions
|
||||
def cpu_affinity_get(self):
|
||||
return cext.proc_cpu_affinity_get(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def cpu_affinity_set(self, cpus):
|
||||
# Pre-emptively check if CPUs are valid because the C
|
||||
# function has a weird behavior in case of invalid CPUs,
|
||||
# see: https://github.com/giampaolo/psutil/issues/586
|
||||
allcpus = tuple(range(len(per_cpu_times())))
|
||||
for cpu in cpus:
|
||||
if cpu not in allcpus:
|
||||
raise ValueError("invalid CPU #%i (choose between %s)"
|
||||
% (cpu, allcpus))
|
||||
try:
|
||||
cext.proc_cpu_affinity_set(self.pid, cpus)
|
||||
except OSError as err:
|
||||
# 'man cpuset_setaffinity' about EDEADLK:
|
||||
# <<the call would leave a thread without a valid CPU to run
|
||||
# on because the set does not overlap with the thread's
|
||||
# anonymous mask>>
|
||||
if err.errno in (errno.EINVAL, errno.EDEADLK):
|
||||
for cpu in cpus:
|
||||
if cpu not in allcpus:
|
||||
raise ValueError("invalid CPU #%i (choose between %s)"
|
||||
% (cpu, allcpus))
|
||||
raise
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,15 +7,16 @@
|
||||
"""OSX platform implementation."""
|
||||
|
||||
import errno
|
||||
import functools
|
||||
import os
|
||||
import sys
|
||||
from collections import namedtuple
|
||||
|
||||
from psutil import _common
|
||||
from psutil import _psposix
|
||||
from psutil._common import conn_tmap, usage_percent, isfile_strict
|
||||
from psutil._compat import namedtuple, wraps
|
||||
import _psutil_osx as cext
|
||||
import _psutil_posix
|
||||
from . import _common
|
||||
from . import _psposix
|
||||
from . import _psutil_osx as cext
|
||||
from . import _psutil_posix as cext_posix
|
||||
from ._common import conn_tmap, usage_percent, isfile_strict
|
||||
from ._common import sockfam_to_enum, socktype_to_enum
|
||||
|
||||
|
||||
__extra__all__ = []
|
||||
@ -23,6 +24,7 @@ __extra__all__ = []
|
||||
# --- constants
|
||||
|
||||
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
|
||||
AF_LINK = cext_posix.AF_LINK
|
||||
|
||||
# http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h
|
||||
TCP_STATUSES = {
|
||||
@ -65,6 +67,7 @@ pmmap_ext = namedtuple(
|
||||
|
||||
# set later from __init__.py
|
||||
NoSuchProcess = None
|
||||
ZombieProcess = None
|
||||
AccessDenied = None
|
||||
TimeoutExpired = None
|
||||
|
||||
@ -165,28 +168,44 @@ def net_connections(kind='inet'):
|
||||
return ret
|
||||
|
||||
|
||||
def net_if_stats():
|
||||
"""Get NIC stats (isup, duplex, speed, mtu)."""
|
||||
names = net_io_counters().keys()
|
||||
ret = {}
|
||||
for name in names:
|
||||
isup, duplex, speed, mtu = cext_posix.net_if_stats(name)
|
||||
if hasattr(_common, 'NicDuplex'):
|
||||
duplex = _common.NicDuplex(duplex)
|
||||
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
|
||||
return ret
|
||||
|
||||
|
||||
pids = cext.pids
|
||||
pid_exists = _psposix.pid_exists
|
||||
disk_usage = _psposix.disk_usage
|
||||
net_io_counters = cext.net_io_counters
|
||||
disk_io_counters = cext.disk_io_counters
|
||||
net_if_addrs = cext_posix.net_if_addrs
|
||||
|
||||
|
||||
def wrap_exceptions(fun):
|
||||
"""Decorator which translates bare OSError exceptions into
|
||||
NoSuchProcess and AccessDenied.
|
||||
"""
|
||||
@wraps(fun)
|
||||
@functools.wraps(fun)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
return fun(self, *args, **kwargs)
|
||||
except OSError:
|
||||
except OSError as err:
|
||||
# support for private module import
|
||||
if NoSuchProcess is None or AccessDenied is None:
|
||||
if (NoSuchProcess is None or AccessDenied is None or
|
||||
ZombieProcess is None):
|
||||
raise
|
||||
err = sys.exc_info()[1]
|
||||
if err.errno == errno.ESRCH:
|
||||
raise NoSuchProcess(self.pid, self._name)
|
||||
if not pid_exists(self.pid):
|
||||
raise NoSuchProcess(self.pid, self._name)
|
||||
else:
|
||||
raise ZombieProcess(self.pid, self._name, self._ppid)
|
||||
if err.errno in (errno.EPERM, errno.EACCES):
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
raise
|
||||
@ -196,11 +215,12 @@ def wrap_exceptions(fun):
|
||||
class Process(object):
|
||||
"""Wrapper class around underlying C implementation."""
|
||||
|
||||
__slots__ = ["pid", "_name"]
|
||||
__slots__ = ["pid", "_name", "_ppid"]
|
||||
|
||||
def __init__(self, pid):
|
||||
self.pid = pid
|
||||
self._name = None
|
||||
self._ppid = None
|
||||
|
||||
@wrap_exceptions
|
||||
def name(self):
|
||||
@ -293,6 +313,8 @@ class Process(object):
|
||||
for item in rawlist:
|
||||
fd, fam, type, laddr, raddr, status = item
|
||||
status = TCP_STATUSES[status]
|
||||
fam = sockfam_to_enum(fam)
|
||||
type = socktype_to_enum(type)
|
||||
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
|
||||
ret.append(nt)
|
||||
return ret
|
||||
@ -315,11 +337,11 @@ class Process(object):
|
||||
|
||||
@wrap_exceptions
|
||||
def nice_get(self):
|
||||
return _psutil_posix.getpriority(self.pid)
|
||||
return cext_posix.getpriority(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def nice_set(self, value):
|
||||
return _psutil_posix.setpriority(self.pid, value)
|
||||
return cext_posix.setpriority(self.pid, value)
|
||||
|
||||
@wrap_exceptions
|
||||
def status(self):
|
||||
|
@ -12,8 +12,8 @@ import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
from psutil._common import sdiskusage, usage_percent, memoize
|
||||
from psutil._compat import PY3, unicode
|
||||
from ._common import sdiskusage, usage_percent, memoize
|
||||
from ._compat import PY3, unicode
|
||||
|
||||
|
||||
class TimeoutExpired(Exception):
|
||||
@ -31,8 +31,7 @@ def pid_exists(pid):
|
||||
return True
|
||||
try:
|
||||
os.kill(pid, 0)
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
except OSError as err:
|
||||
if err.errno == errno.ESRCH:
|
||||
# ESRCH == No such process
|
||||
return False
|
||||
@ -69,17 +68,18 @@ def wait_pid(pid, timeout=None):
|
||||
|
||||
timer = getattr(time, 'monotonic', time.time)
|
||||
if timeout is not None:
|
||||
waitcall = lambda: os.waitpid(pid, os.WNOHANG)
|
||||
def waitcall():
|
||||
return os.waitpid(pid, os.WNOHANG)
|
||||
stop_at = timer() + timeout
|
||||
else:
|
||||
waitcall = lambda: os.waitpid(pid, 0)
|
||||
def waitcall():
|
||||
return os.waitpid(pid, 0)
|
||||
|
||||
delay = 0.0001
|
||||
while 1:
|
||||
while True:
|
||||
try:
|
||||
retpid, status = waitcall()
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
except OSError as err:
|
||||
if err.errno == errno.EINTR:
|
||||
delay = check_timeout(delay)
|
||||
continue
|
||||
@ -90,7 +90,7 @@ def wait_pid(pid, timeout=None):
|
||||
# - pid never existed in the first place
|
||||
# In both cases we'll eventually return None as we
|
||||
# can't determine its exit status code.
|
||||
while 1:
|
||||
while True:
|
||||
if pid_exists(pid):
|
||||
delay = check_timeout(delay)
|
||||
else:
|
||||
@ -150,8 +150,7 @@ def _get_terminal_map():
|
||||
assert name not in ret
|
||||
try:
|
||||
ret[os.stat(name).st_rdev] = name
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
except OSError as err:
|
||||
if err.errno != errno.ENOENT:
|
||||
raise
|
||||
return ret
|
||||
|
@ -11,18 +11,21 @@ import os
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
from collections import namedtuple
|
||||
|
||||
from psutil import _common
|
||||
from psutil import _psposix
|
||||
from psutil._common import usage_percent, isfile_strict
|
||||
from psutil._compat import namedtuple, PY3
|
||||
import _psutil_posix
|
||||
import _psutil_sunos as cext
|
||||
from . import _common
|
||||
from . import _psposix
|
||||
from . import _psutil_posix as cext_posix
|
||||
from . import _psutil_sunos as cext
|
||||
from ._common import isfile_strict, socktype_to_enum, sockfam_to_enum
|
||||
from ._common import usage_percent
|
||||
from ._compat import PY3
|
||||
|
||||
|
||||
__extra__all__ = ["CONN_IDLE", "CONN_BOUND"]
|
||||
|
||||
PAGE_SIZE = os.sysconf('SC_PAGE_SIZE')
|
||||
AF_LINK = cext_posix.AF_LINK
|
||||
|
||||
CONN_IDLE = "IDLE"
|
||||
CONN_BOUND = "BOUND"
|
||||
@ -63,6 +66,7 @@ pmmap_ext = namedtuple(
|
||||
|
||||
# set later from __init__.py
|
||||
NoSuchProcess = None
|
||||
ZombieProcess = None
|
||||
AccessDenied = None
|
||||
TimeoutExpired = None
|
||||
|
||||
@ -71,6 +75,7 @@ TimeoutExpired = None
|
||||
disk_io_counters = cext.disk_io_counters
|
||||
net_io_counters = cext.net_io_counters
|
||||
disk_usage = _psposix.disk_usage
|
||||
net_if_addrs = cext_posix.net_if_addrs
|
||||
|
||||
|
||||
def virtual_memory():
|
||||
@ -91,7 +96,9 @@ def swap_memory():
|
||||
# usr/src/cmd/swap/swap.c
|
||||
# ...nevertheless I can't manage to obtain the same numbers as 'swap'
|
||||
# cmdline utility, so let's parse its output (sigh!)
|
||||
p = subprocess.Popen(['swap', '-l', '-k'], stdout=subprocess.PIPE)
|
||||
p = subprocess.Popen(['/usr/bin/env', 'PATH=/usr/sbin:/sbin:%s' %
|
||||
os.environ['PATH'], 'swap', '-l', '-k'],
|
||||
stdout=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
if PY3:
|
||||
stdout = stdout.decode(sys.stdout.encoding)
|
||||
@ -209,7 +216,7 @@ def net_connections(kind, _pid=-1):
|
||||
% (kind, ', '.join([repr(x) for x in cmap])))
|
||||
families, types = _common.conn_tmap[kind]
|
||||
rawlist = cext.net_connections(_pid, families, types)
|
||||
ret = []
|
||||
ret = set()
|
||||
for item in rawlist:
|
||||
fd, fam, type_, laddr, raddr, status, pid = item
|
||||
if fam not in families:
|
||||
@ -217,11 +224,24 @@ def net_connections(kind, _pid=-1):
|
||||
if type_ not in types:
|
||||
continue
|
||||
status = TCP_STATUSES[status]
|
||||
fam = sockfam_to_enum(fam)
|
||||
type_ = socktype_to_enum(type_)
|
||||
if _pid == -1:
|
||||
nt = _common.sconn(fd, fam, type_, laddr, raddr, status, pid)
|
||||
else:
|
||||
nt = _common.pconn(fd, fam, type_, laddr, raddr, status)
|
||||
ret.append(nt)
|
||||
ret.add(nt)
|
||||
return list(ret)
|
||||
|
||||
|
||||
def net_if_stats():
|
||||
"""Get NIC stats (isup, duplex, speed, mtu)."""
|
||||
ret = cext.net_if_stats()
|
||||
for name, items in ret.items():
|
||||
isup, duplex, speed, mtu = items
|
||||
if hasattr(_common, 'NicDuplex'):
|
||||
duplex = _common.NicDuplex(duplex)
|
||||
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
|
||||
return ret
|
||||
|
||||
|
||||
@ -232,16 +252,19 @@ def wrap_exceptions(fun):
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
return fun(self, *args, **kwargs)
|
||||
except EnvironmentError:
|
||||
except EnvironmentError as err:
|
||||
# support for private module import
|
||||
if NoSuchProcess is None or AccessDenied is None:
|
||||
if (NoSuchProcess is None or AccessDenied is None or
|
||||
ZombieProcess is None):
|
||||
raise
|
||||
# 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._name)
|
||||
if not pid_exists(self.pid):
|
||||
raise NoSuchProcess(self.pid, self._name)
|
||||
else:
|
||||
raise ZombieProcess(self.pid, self._name, self._ppid)
|
||||
if err.errno in (errno.EPERM, errno.EACCES):
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
raise
|
||||
@ -251,11 +274,12 @@ def wrap_exceptions(fun):
|
||||
class Process(object):
|
||||
"""Wrapper class around underlying C implementation."""
|
||||
|
||||
__slots__ = ["pid", "_name"]
|
||||
__slots__ = ["pid", "_name", "_ppid"]
|
||||
|
||||
def __init__(self, pid):
|
||||
self.pid = pid
|
||||
self._name = None
|
||||
self._ppid = None
|
||||
|
||||
@wrap_exceptions
|
||||
def name(self):
|
||||
@ -292,10 +316,11 @@ class Process(object):
|
||||
# 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):
|
||||
return cext_posix.getpriority(self.pid)
|
||||
except EnvironmentError as err:
|
||||
# 48 is 'operation not supported' but errno does not expose
|
||||
# it. It occurs for low system pids.
|
||||
if err.errno in (errno.ENOENT, errno.ESRCH, 48):
|
||||
if pid_exists(self.pid):
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
raise
|
||||
@ -308,7 +333,7 @@ class Process(object):
|
||||
# The process actually exists though, as it has a name,
|
||||
# creation time, etc.
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
return _psutil_posix.setpriority(self.pid, value)
|
||||
return cext_posix.setpriority(self.pid, value)
|
||||
|
||||
@wrap_exceptions
|
||||
def ppid(self):
|
||||
@ -338,8 +363,7 @@ class Process(object):
|
||||
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]
|
||||
except OSError as err:
|
||||
if err.errno == errno.ENOENT:
|
||||
hit_enoent = True
|
||||
continue
|
||||
@ -356,8 +380,7 @@ class Process(object):
|
||||
# Reference: http://goo.gl/55XgO
|
||||
try:
|
||||
return os.readlink("/proc/%s/path/cwd" % self.pid)
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
except OSError as err:
|
||||
if err.errno == errno.ENOENT:
|
||||
os.stat("/proc/%s" % self.pid)
|
||||
return None
|
||||
@ -388,9 +411,8 @@ class Process(object):
|
||||
try:
|
||||
utime, stime = cext.query_process_thread(
|
||||
self.pid, tid)
|
||||
except EnvironmentError:
|
||||
except EnvironmentError as err:
|
||||
# ENOENT == thread gone in meantime
|
||||
err = sys.exc_info()[1]
|
||||
if err.errno == errno.ENOENT:
|
||||
hit_enoent = True
|
||||
continue
|
||||
@ -413,9 +435,8 @@ class Process(object):
|
||||
if os.path.islink(path):
|
||||
try:
|
||||
file = os.readlink(path)
|
||||
except OSError:
|
||||
except OSError as err:
|
||||
# ENOENT == file which is gone in the meantime
|
||||
err = sys.exc_info()[1]
|
||||
if err.errno == errno.ENOENT:
|
||||
hit_enoent = True
|
||||
continue
|
||||
@ -495,8 +516,7 @@ class Process(object):
|
||||
if not name.startswith('['):
|
||||
try:
|
||||
name = os.readlink('/proc/%s/path/%s' % (self.pid, name))
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
except OSError as err:
|
||||
if err.errno == errno.ENOENT:
|
||||
# sometimes the link may not be resolved by
|
||||
# readlink() even if it exists (ls shows it).
|
||||
|
@ -21,12 +21,14 @@
|
||||
#include <sys/user.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/cpuset.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h> // for struct xsocket
|
||||
#include <sys/un.h>
|
||||
#include <sys/unpcb.h>
|
||||
#include <sys/sockio.h>
|
||||
// for xinpcb struct
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
@ -49,6 +51,7 @@
|
||||
#include <net/if.h> // net io counters
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <netinet/in.h> // process open files/connections
|
||||
#include <sys/un.h>
|
||||
@ -91,6 +94,18 @@ psutil_kinfo_proc(const pid_t pid, struct kinfo_proc *proc)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set exception to AccessDenied if pid exists else NoSuchProcess.
|
||||
*/
|
||||
void
|
||||
psutil_raise_ad_or_nsp(long pid) {
|
||||
if (psutil_pid_exists(pid) == 0)
|
||||
NoSuchProcess();
|
||||
else
|
||||
AccessDenied();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return a Python list of all the PIDs running on the system.
|
||||
*/
|
||||
@ -104,9 +119,8 @@ psutil_pids(PyObject *self, PyObject *args)
|
||||
PyObject *retlist = PyList_New(0);
|
||||
PyObject *pid = NULL;
|
||||
|
||||
if (retlist == NULL) {
|
||||
if (retlist == NULL)
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_get_proc_list(&proclist, &num_processes) != 0) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"failed to retrieve process list.");
|
||||
@ -132,9 +146,8 @@ psutil_pids(PyObject *self, PyObject *args)
|
||||
error:
|
||||
Py_XDECREF(pid);
|
||||
Py_DECREF(retlist);
|
||||
if (orig_address != NULL) {
|
||||
if (orig_address != NULL)
|
||||
free(orig_address);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -167,12 +180,10 @@ psutil_proc_name(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("s", kp.ki_comm);
|
||||
}
|
||||
|
||||
@ -191,9 +202,8 @@ psutil_proc_exe(PyObject *self, PyObject *args)
|
||||
int mib[4];
|
||||
size_t size;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
@ -207,12 +217,10 @@ psutil_proc_exe(PyObject *self, PyObject *args)
|
||||
return NULL;
|
||||
}
|
||||
if (size == 0 || strlen(pathname) == 0) {
|
||||
if (psutil_pid_exists(pid) == 0) {
|
||||
if (psutil_pid_exists(pid) == 0)
|
||||
return NoSuchProcess();
|
||||
}
|
||||
else {
|
||||
else
|
||||
strcpy(pathname, "");
|
||||
}
|
||||
}
|
||||
return Py_BuildValue("s", pathname);
|
||||
}
|
||||
@ -227,18 +235,16 @@ psutil_proc_cmdline(PyObject *self, PyObject *args)
|
||||
long pid;
|
||||
PyObject *arglist = NULL;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the commandline, defined in arch/bsd/process_info.c
|
||||
arglist = psutil_get_arg_list(pid);
|
||||
|
||||
// psutil_get_arg_list() returns NULL only if psutil_cmd_args
|
||||
// failed with ESRCH (no process with that PID)
|
||||
if (NULL == arglist) {
|
||||
if (NULL == arglist)
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
return Py_BuildValue("N", arglist);
|
||||
}
|
||||
|
||||
@ -251,12 +257,10 @@ psutil_proc_ppid(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("l", (long)kp.ki_ppid);
|
||||
}
|
||||
|
||||
@ -269,12 +273,10 @@ psutil_proc_status(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("i", (int)kp.ki_stat);
|
||||
}
|
||||
|
||||
@ -288,12 +290,10 @@ psutil_proc_uids(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("lll",
|
||||
(long)kp.ki_ruid,
|
||||
(long)kp.ki_uid,
|
||||
@ -310,12 +310,10 @@ psutil_proc_gids(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("lll",
|
||||
(long)kp.ki_rgid,
|
||||
(long)kp.ki_groups[0],
|
||||
@ -332,12 +330,10 @@ psutil_proc_tty_nr(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("i", kp.ki_tdev);
|
||||
}
|
||||
|
||||
@ -350,12 +346,10 @@ psutil_proc_num_ctx_switches(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("(ll)",
|
||||
kp.ki_rusage.ru_nvcsw,
|
||||
kp.ki_rusage.ru_nivcsw);
|
||||
@ -370,12 +364,10 @@ psutil_proc_num_threads(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("l", (long)kp.ki_numthreads);
|
||||
}
|
||||
|
||||
@ -456,9 +448,8 @@ psutil_proc_threads(PyObject *self, PyObject *args)
|
||||
error:
|
||||
Py_XDECREF(pyTuple);
|
||||
Py_DECREF(retList);
|
||||
if (kip != NULL) {
|
||||
if (kip != NULL)
|
||||
free(kip);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -472,12 +463,10 @@ psutil_proc_cpu_times(PyObject *self, PyObject *args)
|
||||
long pid;
|
||||
double user_t, sys_t;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
// convert from microseconds to seconds
|
||||
user_t = TV2DOUBLE(kp.ki_rusage.ru_utime);
|
||||
sys_t = TV2DOUBLE(kp.ki_rusage.ru_stime);
|
||||
@ -500,14 +489,10 @@ psutil_cpu_count_logical(PyObject *self, PyObject *args)
|
||||
mib[1] = HW_NCPU;
|
||||
len = sizeof(ncpu);
|
||||
|
||||
if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) {
|
||||
// mimic os.cpu_count()
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
else {
|
||||
if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1)
|
||||
Py_RETURN_NONE; // mimic os.cpu_count()
|
||||
else
|
||||
return Py_BuildValue("i", ncpu);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -520,6 +505,7 @@ psutil_cpu_count_phys(PyObject *self, PyObject *args)
|
||||
{
|
||||
void *topology = NULL;
|
||||
size_t size = 0;
|
||||
PyObject *py_str;
|
||||
|
||||
if (sysctlbyname("kern.sched.topology_spec", NULL, &size, NULL, 0))
|
||||
goto error;
|
||||
@ -533,11 +519,14 @@ psutil_cpu_count_phys(PyObject *self, PyObject *args)
|
||||
if (sysctlbyname("kern.sched.topology_spec", topology, &size, NULL, 0))
|
||||
goto error;
|
||||
|
||||
return Py_BuildValue("s", topology);
|
||||
py_str = Py_BuildValue("s", topology);
|
||||
free(topology);
|
||||
return py_str;
|
||||
|
||||
error:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
if (topology != NULL)
|
||||
free(topology);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
@ -550,12 +539,10 @@ psutil_proc_create_time(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("d", TV2DOUBLE(kp.ki_start));
|
||||
}
|
||||
|
||||
@ -569,12 +556,10 @@ psutil_proc_io_counters(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
// there's apparently no way to determine bytes count, hence return -1.
|
||||
return Py_BuildValue("(llll)",
|
||||
kp.ki_rusage.ru_inblock,
|
||||
@ -592,12 +577,10 @@ psutil_proc_memory_info(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("(lllll)",
|
||||
ptoa(kp.ki_rssize), // rss
|
||||
(long)kp.ki_size, // vms
|
||||
@ -749,7 +732,10 @@ psutil_cpu_times(PyObject *self, PyObject *args)
|
||||
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000
|
||||
/*
|
||||
* Return files opened by process as a list of (path, fd) tuples
|
||||
* Return files opened by process as a list of (path, fd) tuples.
|
||||
* TODO: this is broken as it may report empty paths. 'procstat'
|
||||
* utility has the same problem see:
|
||||
* https://github.com/giampaolo/psutil/issues/595
|
||||
*/
|
||||
static PyObject *
|
||||
psutil_proc_open_files(PyObject *self, PyObject *args)
|
||||
@ -867,9 +853,8 @@ psutil_proc_cwd(PyObject *self, PyObject *args)
|
||||
* (lsof can't do that it either). Since this happens even
|
||||
* as root we return an empty string instead of AccessDenied.
|
||||
*/
|
||||
if (path == NULL) {
|
||||
if (path == NULL)
|
||||
path = Py_BuildValue("s", "");
|
||||
}
|
||||
free(freep);
|
||||
return path;
|
||||
|
||||
@ -887,7 +872,6 @@ psutil_fetch_tcplist(void)
|
||||
{
|
||||
char *buf;
|
||||
size_t len;
|
||||
int error;
|
||||
|
||||
for (;;) {
|
||||
if (sysctlbyname("net.inet.tcp.pcblist", NULL, &len, NULL, 0) < 0) {
|
||||
@ -917,7 +901,8 @@ psutil_sockaddr_port(int family, struct sockaddr_storage *ss)
|
||||
if (family == AF_INET) {
|
||||
sin = (struct sockaddr_in *)ss;
|
||||
return (sin->sin_port);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
sin6 = (struct sockaddr_in6 *)ss;
|
||||
return (sin6->sin6_port);
|
||||
}
|
||||
@ -932,7 +917,8 @@ psutil_sockaddr_addr(int family, struct sockaddr_storage *ss)
|
||||
if (family == AF_INET) {
|
||||
sin = (struct sockaddr_in *)ss;
|
||||
return (&sin->sin_addr);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
sin6 = (struct sockaddr_in6 *)ss;
|
||||
return (&sin6->sin6_addr);
|
||||
}
|
||||
@ -1030,12 +1016,10 @@ psutil_proc_connections(PyObject *self, PyObject *args)
|
||||
PyObject *_family = NULL;
|
||||
PyObject *_type = NULL;
|
||||
|
||||
if (retList == NULL) {
|
||||
if (retList == NULL)
|
||||
return NULL;
|
||||
}
|
||||
if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter)) {
|
||||
if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter))
|
||||
goto error;
|
||||
}
|
||||
if (!PySequence_Check(af_filter) || !PySequence_Check(type_filter)) {
|
||||
PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence");
|
||||
goto error;
|
||||
@ -1063,22 +1047,18 @@ psutil_proc_connections(PyObject *self, PyObject *args)
|
||||
raddr = NULL;
|
||||
|
||||
kif = &freep[i];
|
||||
if (kif->kf_type == KF_TYPE_SOCKET)
|
||||
{
|
||||
if (kif->kf_type == KF_TYPE_SOCKET) {
|
||||
// apply filters
|
||||
_family = PyLong_FromLong((long)kif->kf_sock_domain);
|
||||
inseq = PySequence_Contains(af_filter, _family);
|
||||
Py_DECREF(_family);
|
||||
if (inseq == 0) {
|
||||
if (inseq == 0)
|
||||
continue;
|
||||
}
|
||||
_type = PyLong_FromLong((long)kif->kf_sock_type);
|
||||
inseq = PySequence_Contains(type_filter, _type);
|
||||
Py_DECREF(_type);
|
||||
if (inseq == 0) {
|
||||
if (inseq == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
// IPv4 / IPv6 socket
|
||||
if ((kif->kf_sock_domain == AF_INET) ||
|
||||
(kif->kf_sock_domain == AF_INET6)) {
|
||||
@ -1112,12 +1092,10 @@ psutil_proc_connections(PyObject *self, PyObject *args)
|
||||
laddr = Py_BuildValue("(si)", lip, lport);
|
||||
if (!laddr)
|
||||
goto error;
|
||||
if (rport != 0) {
|
||||
if (rport != 0)
|
||||
raddr = Py_BuildValue("(si)", rip, rport);
|
||||
}
|
||||
else {
|
||||
else
|
||||
raddr = Py_BuildValue("()");
|
||||
}
|
||||
if (!raddr)
|
||||
goto error;
|
||||
tuple = Py_BuildValue("(iiiNNi)",
|
||||
@ -1140,7 +1118,7 @@ psutil_proc_connections(PyObject *self, PyObject *args)
|
||||
sun = (struct sockaddr_un *)&kif->kf_sa_local;
|
||||
snprintf(
|
||||
path, sizeof(path), "%.*s",
|
||||
(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))),
|
||||
(int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))),
|
||||
sun->sun_path);
|
||||
|
||||
tuple = Py_BuildValue("(iiisOi)",
|
||||
@ -1250,7 +1228,7 @@ void remove_spaces(char *str) {
|
||||
do
|
||||
while (*p2 == ' ')
|
||||
p2++;
|
||||
while (*p1++ = *p2++);
|
||||
while ((*p1++ = *p2++));
|
||||
}
|
||||
|
||||
|
||||
@ -1264,7 +1242,7 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args)
|
||||
long pid;
|
||||
int ptrwidth;
|
||||
int i, cnt;
|
||||
char addr[30];
|
||||
char addr[1000];
|
||||
char perms[4];
|
||||
const char *path;
|
||||
struct kinfo_proc kp;
|
||||
@ -1274,15 +1252,12 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args)
|
||||
PyObject *pytuple = NULL;
|
||||
PyObject *retlist = PyList_New(0);
|
||||
|
||||
if (retlist == NULL) {
|
||||
if (retlist == NULL)
|
||||
return NULL;
|
||||
}
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
goto error;
|
||||
}
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_kinfo_proc(pid, &kp) == -1)
|
||||
goto error;
|
||||
}
|
||||
|
||||
freep = kinfo_getvmmap(pid, &cnt);
|
||||
if (freep == NULL) {
|
||||
@ -1306,36 +1281,36 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args)
|
||||
|
||||
if (strlen(kve->kve_path) == 0) {
|
||||
switch (kve->kve_type) {
|
||||
case KVME_TYPE_NONE:
|
||||
path = "[none]";
|
||||
break;
|
||||
case KVME_TYPE_DEFAULT:
|
||||
path = "[default]";
|
||||
break;
|
||||
case KVME_TYPE_VNODE:
|
||||
path = "[vnode]";
|
||||
break;
|
||||
case KVME_TYPE_SWAP:
|
||||
path = "[swap]";
|
||||
break;
|
||||
case KVME_TYPE_DEVICE:
|
||||
path = "[device]";
|
||||
break;
|
||||
case KVME_TYPE_PHYS:
|
||||
path = "[phys]";
|
||||
break;
|
||||
case KVME_TYPE_DEAD:
|
||||
path = "[dead]";
|
||||
break;
|
||||
case KVME_TYPE_SG:
|
||||
path = "[sg]";
|
||||
break;
|
||||
case KVME_TYPE_UNKNOWN:
|
||||
path = "[unknown]";
|
||||
break;
|
||||
default:
|
||||
path = "[?]";
|
||||
break;
|
||||
case KVME_TYPE_NONE:
|
||||
path = "[none]";
|
||||
break;
|
||||
case KVME_TYPE_DEFAULT:
|
||||
path = "[default]";
|
||||
break;
|
||||
case KVME_TYPE_VNODE:
|
||||
path = "[vnode]";
|
||||
break;
|
||||
case KVME_TYPE_SWAP:
|
||||
path = "[swap]";
|
||||
break;
|
||||
case KVME_TYPE_DEVICE:
|
||||
path = "[device]";
|
||||
break;
|
||||
case KVME_TYPE_PHYS:
|
||||
path = "[phys]";
|
||||
break;
|
||||
case KVME_TYPE_DEAD:
|
||||
path = "[dead]";
|
||||
break;
|
||||
case KVME_TYPE_SG:
|
||||
path = "[sg]";
|
||||
break;
|
||||
case KVME_TYPE_UNKNOWN:
|
||||
path = "[unknown]";
|
||||
break;
|
||||
default:
|
||||
path = "[?]";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -1489,9 +1464,9 @@ psutil_net_io_counters(PyObject *self, PyObject *args)
|
||||
size_t len;
|
||||
PyObject *py_retdict = PyDict_New();
|
||||
PyObject *py_ifc_info = NULL;
|
||||
|
||||
if (py_retdict == NULL)
|
||||
return NULL;
|
||||
|
||||
mib[0] = CTL_NET; // networking subsystem
|
||||
mib[1] = PF_ROUTE; // type of information
|
||||
mib[2] = 0; // protocol (IPPROTO_xxx)
|
||||
@ -1533,9 +1508,8 @@ psutil_net_io_counters(PyObject *self, PyObject *args)
|
||||
// http://lists.freebsd.org/pipermail/freebsd-current/
|
||||
// 2011-October/028752.html
|
||||
// 'ifconfig -a' doesn't show them, nor do we.
|
||||
if (strncmp(ifc_name, "usbus", 5) == 0) {
|
||||
if (strncmp(ifc_name, "usbus", 5) == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
py_ifc_info = Py_BuildValue("(kkkkkkki)",
|
||||
if2m->ifm_data.ifi_obytes,
|
||||
@ -1580,9 +1554,9 @@ psutil_disk_io_counters(PyObject *self, PyObject *args)
|
||||
|
||||
PyObject *py_retdict = PyDict_New();
|
||||
PyObject *py_disk_info = NULL;
|
||||
|
||||
if (py_retdict == NULL)
|
||||
return NULL;
|
||||
|
||||
if (devstat_checkversion(NULL) < 0) {
|
||||
PyErr_Format(PyExc_RuntimeError, "devstat_checkversion() failed");
|
||||
goto error;
|
||||
@ -1626,9 +1600,8 @@ psutil_disk_io_counters(PyObject *self, PyObject *args)
|
||||
Py_DECREF(py_disk_info);
|
||||
}
|
||||
|
||||
if (stats.dinfo->mem_ptr) {
|
||||
if (stats.dinfo->mem_ptr)
|
||||
free(stats.dinfo->mem_ptr);
|
||||
}
|
||||
free(stats.dinfo);
|
||||
return py_retdict;
|
||||
|
||||
@ -1766,14 +1739,16 @@ psutil_get_pid_from_sock(int sock_hash)
|
||||
if (xf->xf_data == NULL)
|
||||
continue;
|
||||
hash = (int)((uintptr_t)xf->xf_data % HASHSIZE);
|
||||
if (sock_hash == hash) {
|
||||
if (sock_hash == hash)
|
||||
return xf->xf_pid;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Reference:
|
||||
// https://gitorious.org/freebsd/freebsd/source/
|
||||
// f1d6f4778d2044502209708bc167c05f9aa48615:usr.bin/sockstat/sockstat.c
|
||||
int psutil_gather_inet(int proto, PyObject *py_retlist)
|
||||
{
|
||||
struct xinpgen *xig, *exig;
|
||||
@ -1781,25 +1756,26 @@ int psutil_gather_inet(int proto, PyObject *py_retlist)
|
||||
struct xtcpcb *xtp;
|
||||
struct inpcb *inp;
|
||||
struct xsocket *so;
|
||||
struct sock *sock;
|
||||
const char *varname;
|
||||
const char *varname = NULL;
|
||||
size_t len, bufsize;
|
||||
void *buf;
|
||||
int hash, retry, vflag, type;
|
||||
int hash;
|
||||
int retry;
|
||||
int type;
|
||||
|
||||
PyObject *tuple = NULL;
|
||||
PyObject *laddr = NULL;
|
||||
PyObject *raddr = NULL;
|
||||
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
varname = "net.inet.tcp.pcblist";
|
||||
type = SOCK_STREAM;
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
varname = "net.inet.udp.pcblist";
|
||||
type = SOCK_DGRAM;
|
||||
break;
|
||||
case IPPROTO_TCP:
|
||||
varname = "net.inet.tcp.pcblist";
|
||||
type = SOCK_STREAM;
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
varname = "net.inet.udp.pcblist";
|
||||
type = SOCK_DGRAM;
|
||||
break;
|
||||
}
|
||||
|
||||
buf = NULL;
|
||||
@ -1808,10 +1784,8 @@ int psutil_gather_inet(int proto, PyObject *py_retlist)
|
||||
do {
|
||||
for (;;) {
|
||||
buf = realloc(buf, bufsize);
|
||||
if (buf == NULL) {
|
||||
// XXX
|
||||
continue;
|
||||
}
|
||||
if (buf == NULL)
|
||||
continue; // XXX
|
||||
len = bufsize;
|
||||
if (sysctlbyname(varname, buf, &len, NULL, 0) == 0)
|
||||
break;
|
||||
@ -1831,33 +1805,41 @@ int psutil_gather_inet(int proto, PyObject *py_retlist)
|
||||
|
||||
|
||||
for (;;) {
|
||||
int lport, rport, pid, status, family;
|
||||
|
||||
xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len);
|
||||
if (xig >= exig)
|
||||
break;
|
||||
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
xtp = (struct xtcpcb *)xig;
|
||||
if (xtp->xt_len != sizeof *xtp) {
|
||||
PyErr_Format(PyExc_RuntimeError, "struct xtcpcb size mismatch");
|
||||
case IPPROTO_TCP:
|
||||
xtp = (struct xtcpcb *)xig;
|
||||
if (xtp->xt_len != sizeof *xtp) {
|
||||
PyErr_Format(PyExc_RuntimeError,
|
||||
"struct xtcpcb size mismatch");
|
||||
goto error;
|
||||
}
|
||||
inp = &xtp->xt_inp;
|
||||
so = &xtp->xt_socket;
|
||||
status = xtp->xt_tp.t_state;
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
xip = (struct xinpcb *)xig;
|
||||
if (xip->xi_len != sizeof *xip) {
|
||||
PyErr_Format(PyExc_RuntimeError,
|
||||
"struct xinpcb size mismatch");
|
||||
goto error;
|
||||
}
|
||||
inp = &xip->xi_inp;
|
||||
so = &xip->xi_socket;
|
||||
status = PSUTIL_CONN_NONE;
|
||||
break;
|
||||
default:
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid proto");
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
xip = (struct xinpcb *)xig;
|
||||
if (xip->xi_len != sizeof *xip) {
|
||||
PyErr_Format(PyExc_RuntimeError, "struct xinpcb size mismatch");
|
||||
goto error;
|
||||
}
|
||||
inp = &xip->xi_inp;
|
||||
so = &xip->xi_socket;
|
||||
break;
|
||||
}
|
||||
|
||||
inp = &xtp->xt_inp;
|
||||
so = &xtp->xt_socket;
|
||||
char lip[200], rip[200];
|
||||
int family, lport, rport, pid, status;
|
||||
|
||||
hash = (int)((uintptr_t)so->xso_so % HASHSIZE);
|
||||
pid = psutil_get_pid_from_sock(hash);
|
||||
@ -1865,7 +1847,6 @@ int psutil_gather_inet(int proto, PyObject *py_retlist)
|
||||
continue;
|
||||
lport = ntohs(inp->inp_lport);
|
||||
rport = ntohs(inp->inp_fport);
|
||||
status = xtp->xt_tp.t_state;
|
||||
|
||||
if (inp->inp_vflag & INP_IPV4) {
|
||||
family = AF_INET;
|
||||
@ -1882,12 +1863,10 @@ int psutil_gather_inet(int proto, PyObject *py_retlist)
|
||||
laddr = Py_BuildValue("(si)", lip, lport);
|
||||
if (!laddr)
|
||||
goto error;
|
||||
if (rport != 0) {
|
||||
if (rport != 0)
|
||||
raddr = Py_BuildValue("(si)", rip, rport);
|
||||
}
|
||||
else {
|
||||
else
|
||||
raddr = Py_BuildValue("()");
|
||||
}
|
||||
if (!raddr)
|
||||
goto error;
|
||||
tuple = Py_BuildValue("(iiiNNii)", -1, family, type, laddr, raddr,
|
||||
@ -1897,7 +1876,7 @@ int psutil_gather_inet(int proto, PyObject *py_retlist)
|
||||
if (PyList_Append(py_retlist, tuple))
|
||||
goto error;
|
||||
Py_DECREF(tuple);
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return 1;
|
||||
@ -1915,12 +1894,14 @@ int psutil_gather_unix(int proto, PyObject *py_retlist)
|
||||
{
|
||||
struct xunpgen *xug, *exug;
|
||||
struct xunpcb *xup;
|
||||
struct sock *sock;
|
||||
const char *varname, *protoname;
|
||||
size_t len, bufsize;
|
||||
const char *varname = NULL;
|
||||
const char *protoname = NULL;
|
||||
size_t len;
|
||||
size_t bufsize;
|
||||
void *buf;
|
||||
int hash, retry;
|
||||
int family, lport, rport, pid;
|
||||
int hash;
|
||||
int retry;
|
||||
int pid;
|
||||
struct sockaddr_un *sun;
|
||||
char path[PATH_MAX];
|
||||
|
||||
@ -1929,14 +1910,14 @@ int psutil_gather_unix(int proto, PyObject *py_retlist)
|
||||
PyObject *raddr = NULL;
|
||||
|
||||
switch (proto) {
|
||||
case SOCK_STREAM:
|
||||
varname = "net.local.stream.pcblist";
|
||||
protoname = "stream";
|
||||
break;
|
||||
case SOCK_DGRAM:
|
||||
varname = "net.local.dgram.pcblist";
|
||||
protoname = "dgram";
|
||||
break;
|
||||
case SOCK_STREAM:
|
||||
varname = "net.local.stream.pcblist";
|
||||
protoname = "stream";
|
||||
break;
|
||||
case SOCK_DGRAM:
|
||||
varname = "net.local.dgram.pcblist";
|
||||
protoname = "dgram";
|
||||
break;
|
||||
}
|
||||
|
||||
buf = NULL;
|
||||
@ -1973,10 +1954,8 @@ int psutil_gather_unix(int proto, PyObject *py_retlist)
|
||||
if (xug >= exug)
|
||||
break;
|
||||
xup = (struct xunpcb *)xug;
|
||||
if (xup->xu_len != sizeof *xup) {
|
||||
warnx("struct xunpgen size mismatch");
|
||||
if (xup->xu_len != sizeof *xup)
|
||||
goto error;
|
||||
}
|
||||
|
||||
hash = (int)((uintptr_t) xup->xu_socket.xso_so % HASHSIZE);
|
||||
pid = psutil_get_pid_from_sock(hash);
|
||||
@ -1985,7 +1964,7 @@ int psutil_gather_unix(int proto, PyObject *py_retlist)
|
||||
|
||||
sun = (struct sockaddr_un *)&xup->xu_addr;
|
||||
snprintf(path, sizeof(path), "%.*s",
|
||||
(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))),
|
||||
(int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))),
|
||||
sun->sun_path);
|
||||
|
||||
tuple = Py_BuildValue("(iiisOii)", -1, AF_UNIX, proto, path, Py_None,
|
||||
@ -2016,13 +1995,12 @@ error:
|
||||
static PyObject*
|
||||
psutil_net_connections(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject *af_filter = NULL;
|
||||
PyObject *type_filter = NULL;
|
||||
PyObject *py_retlist = PyList_New(0);
|
||||
|
||||
if (py_retlist == NULL)
|
||||
return NULL;
|
||||
if (psutil_populate_xfiles() != 1)
|
||||
goto error;
|
||||
|
||||
if (psutil_gather_inet(IPPROTO_TCP, py_retlist) == 0)
|
||||
goto error;
|
||||
if (psutil_gather_inet(IPPROTO_UDP, py_retlist) == 0)
|
||||
@ -2042,6 +2020,107 @@ error:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get process CPU affinity.
|
||||
* Reference: http://sources.freebsd.org/RELENG_9/src/usr.bin/cpuset/cpuset.c
|
||||
*/
|
||||
static PyObject*
|
||||
psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args)
|
||||
{
|
||||
long pid;
|
||||
int ret;
|
||||
int i;
|
||||
cpuset_t mask;
|
||||
PyObject* py_retlist;
|
||||
PyObject* py_cpu_num;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i", &pid))
|
||||
return NULL;
|
||||
ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, pid,
|
||||
sizeof(mask), &mask);
|
||||
if (ret != 0) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
py_retlist = PyList_New(0);
|
||||
if (py_retlist == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < CPU_SETSIZE; i++) {
|
||||
if (CPU_ISSET(i, &mask)) {
|
||||
py_cpu_num = Py_BuildValue("i", i);
|
||||
if (py_cpu_num == NULL)
|
||||
goto error;
|
||||
if (PyList_Append(py_retlist, py_cpu_num))
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
return py_retlist;
|
||||
|
||||
error:
|
||||
Py_XDECREF(py_cpu_num);
|
||||
Py_DECREF(py_retlist);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set process CPU affinity.
|
||||
* Reference: http://sources.freebsd.org/RELENG_9/src/usr.bin/cpuset/cpuset.c
|
||||
*/
|
||||
static PyObject *
|
||||
psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
int i;
|
||||
int seq_len;
|
||||
int ret;
|
||||
cpuset_t cpu_set;
|
||||
PyObject *py_cpu_set;
|
||||
PyObject *py_cpu_seq = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "lO", &pid, &py_cpu_set))
|
||||
return NULL;
|
||||
|
||||
py_cpu_seq = PySequence_Fast(py_cpu_set, "expected a sequence or integer");
|
||||
if (!py_cpu_seq)
|
||||
return NULL;
|
||||
seq_len = PySequence_Fast_GET_SIZE(py_cpu_seq);
|
||||
|
||||
// calculate the mask
|
||||
CPU_ZERO(&cpu_set);
|
||||
for (i = 0; i < seq_len; i++) {
|
||||
PyObject *item = PySequence_Fast_GET_ITEM(py_cpu_seq, i);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
long value = PyLong_AsLong(item);
|
||||
#else
|
||||
long value = PyInt_AsLong(item);
|
||||
#endif
|
||||
if (value == -1 && PyErr_Occurred())
|
||||
goto error;
|
||||
CPU_SET(value, &cpu_set);
|
||||
}
|
||||
|
||||
// set affinity
|
||||
ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, pid,
|
||||
sizeof(cpu_set), &cpu_set);
|
||||
if (ret != 0) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
goto error;
|
||||
}
|
||||
|
||||
Py_DECREF(py_cpu_seq);
|
||||
Py_RETURN_NONE;
|
||||
|
||||
error:
|
||||
if (py_cpu_seq != NULL)
|
||||
Py_DECREF(py_cpu_seq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* define the psutil C module methods and initialize the module.
|
||||
*/
|
||||
@ -2083,6 +2162,10 @@ PsutilMethods[] =
|
||||
"Return process IO counters"},
|
||||
{"proc_tty_nr", psutil_proc_tty_nr, METH_VARARGS,
|
||||
"Return process tty (terminal) number"},
|
||||
{"proc_cpu_affinity_get", psutil_proc_cpu_affinity_get, METH_VARARGS,
|
||||
"Return process CPU affinity."},
|
||||
{"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS,
|
||||
"Set process CPU affinity."},
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000
|
||||
{"proc_open_files", psutil_proc_open_files, METH_VARARGS,
|
||||
"Return files opened by process as a list of (path, fd) tuples"},
|
||||
@ -2181,6 +2264,8 @@ void init_psutil_bsd(void)
|
||||
#else
|
||||
PyObject *module = Py_InitModule("_psutil_bsd", PsutilMethods);
|
||||
#endif
|
||||
PyModule_AddIntConstant(module, "version", PSUTIL_VERSION);
|
||||
|
||||
// process status constants
|
||||
PyModule_AddIntConstant(module, "SSTOP", SSTOP);
|
||||
PyModule_AddIntConstant(module, "SSLEEP", SSLEEP);
|
||||
@ -2203,9 +2288,8 @@ void init_psutil_bsd(void)
|
||||
PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT);
|
||||
PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE);
|
||||
|
||||
if (module == NULL) {
|
||||
if (module == NULL)
|
||||
INITERROR;
|
||||
}
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return module;
|
||||
#endif
|
||||
|
@ -26,6 +26,8 @@ static PyObject* psutil_proc_status(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_threads(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_tty_nr(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_uids(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_cpu_affinity_set(PyObject* self, PyObject* args);
|
||||
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000
|
||||
static PyObject* psutil_proc_open_files(PyObject* self, PyObject* args);
|
||||
@ -48,4 +50,4 @@ static PyObject* psutil_virtual_mem(PyObject* self, PyObject* args);
|
||||
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000
|
||||
static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -19,6 +19,11 @@
|
||||
#include <linux/version.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/sockios.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/ethtool.h>
|
||||
|
||||
#include "_psutil_linux.h"
|
||||
|
||||
@ -46,6 +51,12 @@ enum {
|
||||
IOPRIO_WHO_PROCESS = 1,
|
||||
};
|
||||
|
||||
// May happen on old RedHat versions, see:
|
||||
// https://github.com/giampaolo/psutil/issues/607
|
||||
#ifndef DUPLEX_UNKNOWN
|
||||
#define DUPLEX_UNKNOWN 0xff
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
ioprio_get(int which, int who)
|
||||
{
|
||||
@ -74,13 +85,11 @@ psutil_proc_ioprio_get(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
int ioprio, ioclass, iodata;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid);
|
||||
if (ioprio == -1) {
|
||||
if (ioprio == -1)
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
ioclass = IOPRIO_PRIO_CLASS(ioprio);
|
||||
iodata = IOPRIO_PRIO_DATA(ioprio);
|
||||
return Py_BuildValue("ii", ioclass, iodata);
|
||||
@ -99,16 +108,13 @@ psutil_proc_ioprio_set(PyObject *self, PyObject *args)
|
||||
int ioprio, ioclass, iodata;
|
||||
int retval;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "lii", &pid, &ioclass, &iodata)) {
|
||||
if (! PyArg_ParseTuple(args, "lii", &pid, &ioclass, &iodata))
|
||||
return NULL;
|
||||
}
|
||||
ioprio = IOPRIO_PRIO_VALUE(ioclass, iodata);
|
||||
retval = ioprio_set(IOPRIO_WHO_PROCESS, pid, ioprio);
|
||||
if (retval == -1) {
|
||||
if (retval == -1)
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -129,9 +135,8 @@ psutil_linux_prlimit(PyObject *self, PyObject *args)
|
||||
PyObject *soft = NULL;
|
||||
PyObject *hard = NULL;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "li|OO", &pid, &resource, &soft, &hard)) {
|
||||
if (! PyArg_ParseTuple(args, "li|OO", &pid, &resource, &soft, &hard))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get
|
||||
if (soft == NULL && hard == NULL) {
|
||||
@ -169,8 +174,7 @@ psutil_linux_prlimit(PyObject *self, PyObject *args)
|
||||
ret = prlimit(pid, resource, newp, &old);
|
||||
if (ret == -1)
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -235,10 +239,9 @@ static PyObject *
|
||||
psutil_linux_sysinfo(PyObject *self, PyObject *args)
|
||||
{
|
||||
struct sysinfo info;
|
||||
if (sysinfo(&info) != 0) {
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
|
||||
if (sysinfo(&info) != 0)
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
// note: boot time might also be determined from here
|
||||
return Py_BuildValue(
|
||||
"(KKKKKK)",
|
||||
@ -268,10 +271,8 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args)
|
||||
cpu_set_t *mask = NULL;
|
||||
PyObject *res = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i", &pid)) {
|
||||
if (!PyArg_ParseTuple(args, "i", &pid))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ncpus = NCPUS_START;
|
||||
while (1) {
|
||||
setsize = CPU_ALLOC_SIZE(ncpus);
|
||||
@ -303,7 +304,6 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args)
|
||||
#else
|
||||
PyObject *cpu_num = PyInt_FromLong(cpu);
|
||||
#endif
|
||||
--count;
|
||||
if (cpu_num == NULL)
|
||||
goto error;
|
||||
if (PyList_Append(res, cpu_num)) {
|
||||
@ -311,6 +311,7 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args)
|
||||
goto error;
|
||||
}
|
||||
Py_DECREF(cpu_num);
|
||||
--count;
|
||||
}
|
||||
}
|
||||
CPU_FREE(mask);
|
||||
@ -325,33 +326,45 @@ error:
|
||||
#else
|
||||
|
||||
|
||||
/*
|
||||
* Alternative implementation in case CPU_ALLOC is not defined.
|
||||
*/
|
||||
static PyObject *
|
||||
psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args)
|
||||
{
|
||||
cpu_set_t cpuset;
|
||||
unsigned int len = sizeof(cpu_set_t);
|
||||
long pid;
|
||||
int i;
|
||||
PyObject* ret_list;
|
||||
int i;
|
||||
PyObject* py_retlist = NULL;
|
||||
PyObject *py_cpu_num = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i", &pid)) {
|
||||
if (!PyArg_ParseTuple(args, "i", &pid))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CPU_ZERO(&cpuset);
|
||||
if (sched_getaffinity(pid, len, &cpuset) < 0) {
|
||||
if (sched_getaffinity(pid, len, &cpuset) < 0)
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
|
||||
ret_list = PyList_New(0);
|
||||
|
||||
py_retlist = PyList_New(0);
|
||||
if (py_retlist == NULL)
|
||||
goto error;
|
||||
for (i = 0; i < CPU_SETSIZE; ++i) {
|
||||
if (CPU_ISSET(i, &cpuset)) {
|
||||
PyList_Append(ret_list, Py_BuildValue("i", i));
|
||||
py_cpu_num = Py_BuildValue("i", i);
|
||||
if (py_cpu_num == NULL)
|
||||
goto error;
|
||||
if (PyList_Append(py_retlist, py_cpu_num))
|
||||
goto error;
|
||||
Py_DECREF(py_cpu_num);
|
||||
}
|
||||
}
|
||||
|
||||
return ret_list;
|
||||
return py_retlist;
|
||||
|
||||
error:
|
||||
Py_XDECREF(py_cpu_num);
|
||||
Py_DECREF(py_retlist);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -368,22 +381,18 @@ psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args)
|
||||
PyObject *py_cpu_set;
|
||||
PyObject *py_cpu_seq = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "lO", &pid, &py_cpu_set)) {
|
||||
goto error;
|
||||
}
|
||||
if (!PyArg_ParseTuple(args, "lO", &pid, &py_cpu_set))
|
||||
return NULL;
|
||||
|
||||
if (!PySequence_Check(py_cpu_set)) {
|
||||
// does not work on Python 2.4
|
||||
// PyErr_Format(PyExc_TypeError, "sequence argument expected, got %s",
|
||||
// Py_TYPE(py_cpu_set)->tp_name);
|
||||
PyErr_Format(PyExc_TypeError, "sequence argument expected");
|
||||
PyErr_Format(PyExc_TypeError, "sequence argument expected, got %s",
|
||||
Py_TYPE(py_cpu_set)->tp_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
py_cpu_seq = PySequence_Fast(py_cpu_set, "expected a sequence or integer");
|
||||
if (!py_cpu_seq) {
|
||||
if (!py_cpu_seq)
|
||||
goto error;
|
||||
}
|
||||
seq_len = PySequence_Fast_GET_SIZE(py_cpu_seq);
|
||||
CPU_ZERO(&cpu_set);
|
||||
for (i = 0; i < seq_len; i++) {
|
||||
@ -393,9 +402,8 @@ psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args)
|
||||
#else
|
||||
long value = PyInt_AsLong(item);
|
||||
#endif
|
||||
if (value == -1 && PyErr_Occurred()) {
|
||||
if (value == -1 && PyErr_Occurred())
|
||||
goto error;
|
||||
}
|
||||
CPU_SET(value, &cpu_set);
|
||||
}
|
||||
|
||||
@ -406,14 +414,11 @@ psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args)
|
||||
}
|
||||
|
||||
Py_DECREF(py_cpu_seq);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
Py_RETURN_NONE;
|
||||
|
||||
error:
|
||||
if (py_cpu_seq != NULL) {
|
||||
if (py_cpu_seq != NULL)
|
||||
Py_DECREF(py_cpu_seq);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -465,6 +470,87 @@ error:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return stats about a particular network
|
||||
* interface. References:
|
||||
* https://github.com/dpaleino/wicd/blob/master/wicd/backends/be-ioctl.py
|
||||
* http://www.i-scream.org/libstatgrab/
|
||||
*/
|
||||
static PyObject*
|
||||
psutil_net_if_stats(PyObject* self, PyObject* args)
|
||||
{
|
||||
char *nic_name;
|
||||
int sock = 0;
|
||||
int ret;
|
||||
int duplex;
|
||||
int speed;
|
||||
int mtu;
|
||||
struct ifreq ifr;
|
||||
struct ethtool_cmd ethcmd;
|
||||
PyObject *py_is_up = NULL;
|
||||
PyObject *py_ret = NULL;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "s", &nic_name))
|
||||
return NULL;
|
||||
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock == -1)
|
||||
goto error;
|
||||
strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name));
|
||||
|
||||
// is up?
|
||||
ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
|
||||
if (ret == -1)
|
||||
goto error;
|
||||
if ((ifr.ifr_flags & IFF_UP) != 0)
|
||||
py_is_up = Py_True;
|
||||
else
|
||||
py_is_up = Py_False;
|
||||
Py_INCREF(py_is_up);
|
||||
|
||||
// MTU
|
||||
ret = ioctl(sock, SIOCGIFMTU, &ifr);
|
||||
if (ret == -1)
|
||||
goto error;
|
||||
mtu = ifr.ifr_mtu;
|
||||
|
||||
// duplex and speed
|
||||
memset(ðcmd, 0, sizeof ethcmd);
|
||||
ethcmd.cmd = ETHTOOL_GSET;
|
||||
ifr.ifr_data = (caddr_t)ðcmd;
|
||||
ret = ioctl(sock, SIOCETHTOOL, &ifr);
|
||||
|
||||
if (ret != -1) {
|
||||
duplex = ethcmd.duplex;
|
||||
speed = ethcmd.speed;
|
||||
}
|
||||
else {
|
||||
if (errno == EOPNOTSUPP) {
|
||||
// we typically get here in case of wi-fi cards
|
||||
duplex = DUPLEX_UNKNOWN;
|
||||
speed = 0;
|
||||
}
|
||||
else {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
close(sock);
|
||||
py_ret = Py_BuildValue("[Oiii]", py_is_up, duplex, speed, mtu);
|
||||
if (!py_ret)
|
||||
goto error;
|
||||
Py_DECREF(py_is_up);
|
||||
return py_ret;
|
||||
|
||||
error:
|
||||
Py_XDECREF(py_is_up);
|
||||
if (sock != 0)
|
||||
close(sock);
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Define the psutil C module methods and initialize the module.
|
||||
*/
|
||||
@ -491,6 +577,8 @@ PsutilMethods[] =
|
||||
"device, mount point and filesystem type"},
|
||||
{"users", psutil_users, METH_VARARGS,
|
||||
"Return currently connected users as a list of tuples"},
|
||||
{"net_if_stats", psutil_net_if_stats, METH_VARARGS,
|
||||
"Return NIC stats (isup, duplex, speed, mtu)"},
|
||||
|
||||
// --- linux specific
|
||||
|
||||
@ -559,6 +647,7 @@ void init_psutil_linux(void)
|
||||
#endif
|
||||
|
||||
|
||||
PyModule_AddIntConstant(module, "version", PSUTIL_VERSION);
|
||||
#if PSUTIL_HAVE_PRLIMIT
|
||||
PyModule_AddIntConstant(module, "RLIM_INFINITY", RLIM_INFINITY);
|
||||
PyModule_AddIntConstant(module, "RLIMIT_AS", RLIMIT_AS);
|
||||
@ -588,10 +677,12 @@ void init_psutil_linux(void)
|
||||
PyModule_AddIntConstant(module, "RLIMIT_SIGPENDING", RLIMIT_SIGPENDING);
|
||||
#endif
|
||||
#endif
|
||||
PyModule_AddIntConstant(module, "DUPLEX_HALF", DUPLEX_HALF);
|
||||
PyModule_AddIntConstant(module, "DUPLEX_FULL", DUPLEX_FULL);
|
||||
PyModule_AddIntConstant(module, "DUPLEX_UNKNOWN", DUPLEX_UNKNOWN);
|
||||
|
||||
if (module == NULL) {
|
||||
if (module == NULL)
|
||||
INITERROR;
|
||||
}
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return module;
|
||||
#endif
|
||||
|
@ -18,3 +18,4 @@ static PyObject* psutil_proc_ioprio_get(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_linux_sysinfo(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_users(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_net_if_stats(PyObject* self, PyObject* args);
|
||||
|
@ -120,12 +120,10 @@ psutil_proc_name(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("s", kp.kp_proc.p_comm);
|
||||
}
|
||||
|
||||
@ -139,9 +137,8 @@ psutil_proc_cwd(PyObject *self, PyObject *args)
|
||||
long pid;
|
||||
struct proc_vnodepathinfo pathinfo;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (! psutil_proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, &pathinfo,
|
||||
sizeof(pathinfo)))
|
||||
@ -162,17 +159,14 @@ psutil_proc_exe(PyObject *self, PyObject *args)
|
||||
char buf[PATH_MAX];
|
||||
int ret;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
ret = proc_pidpath(pid, &buf, sizeof(buf));
|
||||
if (ret == 0) {
|
||||
if (! psutil_pid_exists(pid)) {
|
||||
if (! psutil_pid_exists(pid))
|
||||
return NoSuchProcess();
|
||||
}
|
||||
else {
|
||||
else
|
||||
return AccessDenied();
|
||||
}
|
||||
}
|
||||
return Py_BuildValue("s", buf);
|
||||
}
|
||||
@ -187,9 +181,8 @@ psutil_proc_cmdline(PyObject *self, PyObject *args)
|
||||
long pid;
|
||||
PyObject *arglist = NULL;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the commandline, defined in arch/osx/process_info.c
|
||||
arglist = psutil_get_arg_list(pid);
|
||||
@ -205,12 +198,10 @@ psutil_proc_ppid(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("l", (long)kp.kp_eproc.e_ppid);
|
||||
}
|
||||
|
||||
@ -223,12 +214,10 @@ psutil_proc_uids(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("lll",
|
||||
(long)kp.kp_eproc.e_pcred.p_ruid,
|
||||
(long)kp.kp_eproc.e_ucred.cr_uid,
|
||||
@ -244,12 +233,10 @@ psutil_proc_gids(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("lll",
|
||||
(long)kp.kp_eproc.e_pcred.p_rgid,
|
||||
(long)kp.kp_eproc.e_ucred.cr_groups[0],
|
||||
@ -265,12 +252,10 @@ psutil_proc_tty_nr(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("i", kp.kp_eproc.e_tdev);
|
||||
}
|
||||
|
||||
@ -299,9 +284,8 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args)
|
||||
if (py_list == NULL)
|
||||
return NULL;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = task_for_pid(mach_task_self(), pid, &task);
|
||||
|
||||
@ -324,11 +308,8 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args)
|
||||
|
||||
err = vm_region_recurse_64(task, &address, &size, &depth,
|
||||
(vm_region_info_64_t)&info, &count);
|
||||
|
||||
if (err == KERN_INVALID_ADDRESS) {
|
||||
if (err == KERN_INVALID_ADDRESS)
|
||||
break;
|
||||
}
|
||||
|
||||
if (info.is_submap) {
|
||||
depth++;
|
||||
}
|
||||
@ -356,32 +337,30 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args)
|
||||
|
||||
if (strlen(buf) == 0) {
|
||||
switch (info.share_mode) {
|
||||
/*
|
||||
case SM_LARGE_PAGE:
|
||||
// Treat SM_LARGE_PAGE the same as SM_PRIVATE
|
||||
// since they are not shareable and are wired.
|
||||
*/
|
||||
case SM_COW:
|
||||
strcpy(buf, "[cow]");
|
||||
break;
|
||||
case SM_PRIVATE:
|
||||
strcpy(buf, "[prv]");
|
||||
break;
|
||||
case SM_EMPTY:
|
||||
strcpy(buf, "[nul]");
|
||||
break;
|
||||
case SM_SHARED:
|
||||
case SM_TRUESHARED:
|
||||
strcpy(buf, "[shm]");
|
||||
break;
|
||||
case SM_PRIVATE_ALIASED:
|
||||
strcpy(buf, "[ali]");
|
||||
break;
|
||||
case SM_SHARED_ALIASED:
|
||||
strcpy(buf, "[s/a]");
|
||||
break;
|
||||
default:
|
||||
strcpy(buf, "[???]");
|
||||
// case SM_LARGE_PAGE:
|
||||
// Treat SM_LARGE_PAGE the same as SM_PRIVATE
|
||||
// since they are not shareable and are wired.
|
||||
case SM_COW:
|
||||
strcpy(buf, "[cow]");
|
||||
break;
|
||||
case SM_PRIVATE:
|
||||
strcpy(buf, "[prv]");
|
||||
break;
|
||||
case SM_EMPTY:
|
||||
strcpy(buf, "[nul]");
|
||||
break;
|
||||
case SM_SHARED:
|
||||
case SM_TRUESHARED:
|
||||
strcpy(buf, "[shm]");
|
||||
break;
|
||||
case SM_PRIVATE_ALIASED:
|
||||
strcpy(buf, "[ali]");
|
||||
break;
|
||||
case SM_SHARED_ALIASED:
|
||||
strcpy(buf, "[s/a]");
|
||||
break;
|
||||
default:
|
||||
strcpy(buf, "[???]");
|
||||
}
|
||||
}
|
||||
|
||||
@ -432,19 +411,14 @@ psutil_cpu_count_logical(PyObject *self, PyObject *args)
|
||||
int mib[2];
|
||||
int ncpu;
|
||||
size_t len;
|
||||
|
||||
mib[0] = CTL_HW;
|
||||
mib[1] = HW_NCPU;
|
||||
len = sizeof(ncpu);
|
||||
|
||||
if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) {
|
||||
// mimic os.cpu_count()
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
else {
|
||||
if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1)
|
||||
Py_RETURN_NONE; // mimic os.cpu_count()
|
||||
else
|
||||
return Py_BuildValue("i", ncpu);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -456,12 +430,11 @@ psutil_cpu_count_phys(PyObject *self, PyObject *args)
|
||||
{
|
||||
int num;
|
||||
size_t size = sizeof(int);
|
||||
if (sysctlbyname("hw.physicalcpu", &num, &size, NULL, 0)) {
|
||||
// mimic os.cpu_count()
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
return Py_BuildValue("i", num);
|
||||
|
||||
if (sysctlbyname("hw.physicalcpu", &num, &size, NULL, 0))
|
||||
Py_RETURN_NONE; // mimic os.cpu_count()
|
||||
else
|
||||
return Py_BuildValue("i", num);
|
||||
}
|
||||
|
||||
|
||||
@ -475,12 +448,11 @@ psutil_proc_cpu_times(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct proc_taskinfo pti;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti))) {
|
||||
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti)))
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("(dd)",
|
||||
(float)pti.pti_total_user / 1000000000.0,
|
||||
(float)pti.pti_total_system / 1000000000.0);
|
||||
@ -496,12 +468,10 @@ psutil_proc_create_time(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("d", TV2DOUBLE(kp.kp_proc.p_starttime));
|
||||
}
|
||||
|
||||
@ -514,13 +484,11 @@ psutil_proc_memory_info(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct proc_taskinfo pti;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti)))
|
||||
return NULL;
|
||||
// Note: determining other memory stats on OSX is a mess:
|
||||
// http://www.opensource.apple.com/source/top/top-67/libtop.c?txt
|
||||
// I just give up...
|
||||
@ -544,12 +512,11 @@ psutil_proc_num_threads(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct proc_taskinfo pti;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti))) {
|
||||
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti)))
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("k", pti.pti_threadnum);
|
||||
}
|
||||
|
||||
@ -562,12 +529,11 @@ psutil_proc_num_ctx_switches(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct proc_taskinfo pti;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti))) {
|
||||
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti)))
|
||||
return NULL;
|
||||
}
|
||||
// unvoluntary value seems not to be available;
|
||||
// pti.pti_csw probably refers to the sum of the two (getrusage()
|
||||
// numbers seems to confirm this theory).
|
||||
@ -587,10 +553,10 @@ psutil_virtual_mem(PyObject *self, PyObject *args)
|
||||
size_t len = sizeof(total);
|
||||
vm_statistics_data_t vm;
|
||||
int pagesize = getpagesize();
|
||||
|
||||
// physical mem
|
||||
mib[0] = CTL_HW;
|
||||
mib[1] = HW_MEMSIZE;
|
||||
|
||||
if (sysctl(mib, 2, &total, &len, NULL, 0)) {
|
||||
if (errno != 0)
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
@ -600,9 +566,8 @@ psutil_virtual_mem(PyObject *self, PyObject *args)
|
||||
}
|
||||
|
||||
// vm
|
||||
if (!psutil_sys_vminfo(&vm)) {
|
||||
if (!psutil_sys_vminfo(&vm))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Py_BuildValue(
|
||||
"KKKKK",
|
||||
@ -637,9 +602,8 @@ psutil_swap_mem(PyObject *self, PyObject *args)
|
||||
PyErr_Format(PyExc_RuntimeError, "sysctl(VM_SWAPUSAGE) failed");
|
||||
return NULL;
|
||||
}
|
||||
if (!psutil_sys_vminfo(&vmstat)) {
|
||||
if (!psutil_sys_vminfo(&vmstat))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Py_BuildValue(
|
||||
"LLLKK",
|
||||
@ -664,11 +628,10 @@ psutil_cpu_times(PyObject *self, PyObject *args)
|
||||
mach_port_t host_port = mach_host_self();
|
||||
error = host_statistics(host_port, HOST_CPU_LOAD_INFO,
|
||||
(host_info_t)&r_load, &count);
|
||||
if (error != KERN_SUCCESS) {
|
||||
if (error != KERN_SUCCESS)
|
||||
return PyErr_Format(PyExc_RuntimeError,
|
||||
"Error in host_statistics(): %s",
|
||||
mach_error_string(error));
|
||||
}
|
||||
mach_port_deallocate(mach_task_self(), host_port);
|
||||
|
||||
return Py_BuildValue(
|
||||
@ -728,9 +691,8 @@ psutil_per_cpu_times(PyObject *self, PyObject *args)
|
||||
|
||||
ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array,
|
||||
info_count * sizeof(int));
|
||||
if (ret != KERN_SUCCESS) {
|
||||
if (ret != KERN_SUCCESS)
|
||||
PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2);
|
||||
}
|
||||
return py_retlist;
|
||||
|
||||
error:
|
||||
@ -739,9 +701,8 @@ error:
|
||||
if (cpu_load_info != NULL) {
|
||||
ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array,
|
||||
info_count * sizeof(int));
|
||||
if (ret != KERN_SUCCESS) {
|
||||
if (ret != KERN_SUCCESS)
|
||||
PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -900,12 +861,10 @@ psutil_proc_status(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc kp;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1)
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("i", (int)kp.kp_proc.p_stat);
|
||||
}
|
||||
|
||||
@ -934,19 +893,16 @@ psutil_proc_threads(PyObject *self, PyObject *args)
|
||||
return NULL;
|
||||
|
||||
// the argument passed should be a process id
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
goto error;
|
||||
}
|
||||
|
||||
// task_for_pid() requires special privileges
|
||||
err = task_for_pid(mach_task_self(), pid, &task);
|
||||
if (err != KERN_SUCCESS) {
|
||||
if (! psutil_pid_exists(pid)) {
|
||||
if (! psutil_pid_exists(pid))
|
||||
NoSuchProcess();
|
||||
}
|
||||
else {
|
||||
else
|
||||
AccessDenied();
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -999,9 +955,8 @@ psutil_proc_threads(PyObject *self, PyObject *args)
|
||||
|
||||
ret = vm_deallocate(task, (vm_address_t)thread_list,
|
||||
thread_count * sizeof(int));
|
||||
if (ret != KERN_SUCCESS) {
|
||||
if (ret != KERN_SUCCESS)
|
||||
PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2);
|
||||
}
|
||||
|
||||
mach_port_deallocate(mach_task_self(), task);
|
||||
|
||||
@ -1015,9 +970,8 @@ error:
|
||||
if (thread_list != NULL) {
|
||||
ret = vm_deallocate(task, (vm_address_t)thread_list,
|
||||
thread_count * sizeof(int));
|
||||
if (ret != KERN_SUCCESS) {
|
||||
if (ret != KERN_SUCCESS)
|
||||
PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -1048,9 +1002,8 @@ psutil_proc_open_files(PyObject *self, PyObject *args)
|
||||
if (retList == NULL)
|
||||
return NULL;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
goto error;
|
||||
}
|
||||
|
||||
pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
|
||||
if (pidinfo_result <= 0) {
|
||||
@ -1127,19 +1080,14 @@ psutil_proc_open_files(PyObject *self, PyObject *args)
|
||||
error:
|
||||
Py_XDECREF(tuple);
|
||||
Py_DECREF(retList);
|
||||
if (fds_pointer != NULL) {
|
||||
if (fds_pointer != NULL)
|
||||
free(fds_pointer);
|
||||
}
|
||||
if (errno != 0) {
|
||||
if (errno != 0)
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
else if (! psutil_pid_exists(pid)) {
|
||||
else if (! psutil_pid_exists(pid))
|
||||
return NoSuchProcess();
|
||||
}
|
||||
else {
|
||||
// exception has already been set earlier
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return NULL; // exception has already been set earlier
|
||||
}
|
||||
|
||||
|
||||
@ -1175,23 +1123,19 @@ psutil_proc_connections(PyObject *self, PyObject *args)
|
||||
if (retList == NULL)
|
||||
return NULL;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter)) {
|
||||
if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter))
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!PySequence_Check(af_filter) || !PySequence_Check(type_filter)) {
|
||||
PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
if (pid == 0)
|
||||
return retList;
|
||||
}
|
||||
|
||||
pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
|
||||
if (pidinfo_result <= 0) {
|
||||
if (pidinfo_result <= 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
fds_pointer = malloc(pidinfo_result);
|
||||
if (fds_pointer == NULL) {
|
||||
@ -1201,10 +1145,8 @@ psutil_proc_connections(PyObject *self, PyObject *args)
|
||||
pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer,
|
||||
pidinfo_result);
|
||||
|
||||
if (pidinfo_result <= 0) {
|
||||
if (pidinfo_result <= 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE);
|
||||
|
||||
for (i = 0; i < iterations; i++) {
|
||||
@ -1225,14 +1167,12 @@ psutil_proc_connections(PyObject *self, PyObject *args)
|
||||
// let's assume socket has been closed
|
||||
continue;
|
||||
}
|
||||
if (errno != 0) {
|
||||
if (errno != 0)
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
else {
|
||||
else
|
||||
PyErr_Format(
|
||||
PyExc_RuntimeError,
|
||||
"proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed");
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
if (nb < sizeof(si)) {
|
||||
@ -1258,15 +1198,13 @@ psutil_proc_connections(PyObject *self, PyObject *args)
|
||||
_family = PyLong_FromLong((long)family);
|
||||
inseq = PySequence_Contains(af_filter, _family);
|
||||
Py_DECREF(_family);
|
||||
if (inseq == 0) {
|
||||
if (inseq == 0)
|
||||
continue;
|
||||
}
|
||||
_type = PyLong_FromLong((long)type);
|
||||
inseq = PySequence_Contains(type_filter, _type);
|
||||
Py_DECREF(_type);
|
||||
if (inseq == 0) {
|
||||
if (inseq == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (errno != 0) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
@ -1305,22 +1243,18 @@ psutil_proc_connections(PyObject *self, PyObject *args)
|
||||
|
||||
lport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport);
|
||||
rport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_fport);
|
||||
if (type == SOCK_STREAM) {
|
||||
if (type == SOCK_STREAM)
|
||||
state = (int)si.psi.soi_proto.pri_tcp.tcpsi_state;
|
||||
}
|
||||
else {
|
||||
else
|
||||
state = PSUTIL_CONN_NONE;
|
||||
}
|
||||
|
||||
laddr = Py_BuildValue("(si)", lip, lport);
|
||||
if (!laddr)
|
||||
goto error;
|
||||
if (rport != 0) {
|
||||
if (rport != 0)
|
||||
raddr = Py_BuildValue("(si)", rip, rport);
|
||||
}
|
||||
else {
|
||||
else
|
||||
raddr = Py_BuildValue("()");
|
||||
}
|
||||
if (!raddr)
|
||||
goto error;
|
||||
|
||||
@ -1359,19 +1293,15 @@ error:
|
||||
Py_XDECREF(raddr);
|
||||
Py_DECREF(retList);
|
||||
|
||||
if (fds_pointer != NULL) {
|
||||
if (fds_pointer != NULL)
|
||||
free(fds_pointer);
|
||||
}
|
||||
if (errno != 0) {
|
||||
if (errno != 0)
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
else if (! psutil_pid_exists(pid) ) {
|
||||
else if (! psutil_pid_exists(pid))
|
||||
return NoSuchProcess();
|
||||
}
|
||||
else {
|
||||
else
|
||||
return PyErr_Format(PyExc_RuntimeError,
|
||||
"proc_pidinfo(PROC_PIDLISTFDS) failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1386,19 +1316,16 @@ psutil_proc_num_fds(PyObject *self, PyObject *args)
|
||||
int num;
|
||||
struct proc_fdinfo *fds_pointer;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
|
||||
if (pidinfo_result <= 0) {
|
||||
if (pidinfo_result <= 0)
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
|
||||
fds_pointer = malloc(pidinfo_result);
|
||||
if (fds_pointer == NULL) {
|
||||
if (fds_pointer == NULL)
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer,
|
||||
pidinfo_result);
|
||||
if (pidinfo_result <= 0) {
|
||||
@ -1851,6 +1778,7 @@ init_psutil_osx(void)
|
||||
#else
|
||||
PyObject *module = Py_InitModule("_psutil_osx", PsutilMethods);
|
||||
#endif
|
||||
PyModule_AddIntConstant(module, "version", PSUTIL_VERSION);
|
||||
// process status constants, defined in:
|
||||
// http://fxr.watson.org/fxr/source/bsd/sys/proc.h?v=xnu-792.6.70#L149
|
||||
PyModule_AddIntConstant(module, "SIDL", SIDL);
|
||||
@ -1872,9 +1800,8 @@ init_psutil_osx(void)
|
||||
PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT);
|
||||
PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE);
|
||||
|
||||
if (module == NULL) {
|
||||
if (module == NULL)
|
||||
INITERROR;
|
||||
}
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return module;
|
||||
#endif
|
||||
|
@ -10,6 +10,24 @@
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
#ifdef __linux
|
||||
#include <netdb.h>
|
||||
#include <linux/if_packet.h>
|
||||
#endif // end linux
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if_dl.h>
|
||||
#endif
|
||||
|
||||
#if defined(__sun)
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include "_psutil_posix.h"
|
||||
|
||||
@ -23,13 +41,12 @@ psutil_posix_getpriority(PyObject *self, PyObject *args)
|
||||
long pid;
|
||||
int priority;
|
||||
errno = 0;
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
}
|
||||
priority = getpriority(PRIO_PROCESS, pid);
|
||||
if (errno != 0) {
|
||||
if (errno != 0)
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
return Py_BuildValue("i", priority);
|
||||
}
|
||||
|
||||
@ -43,18 +60,394 @@ psutil_posix_setpriority(PyObject *self, PyObject *args)
|
||||
long pid;
|
||||
int priority;
|
||||
int retval;
|
||||
if (! PyArg_ParseTuple(args, "li", &pid, &priority)) {
|
||||
|
||||
if (! PyArg_ParseTuple(args, "li", &pid, &priority))
|
||||
return NULL;
|
||||
}
|
||||
retval = setpriority(PRIO_PROCESS, pid, priority);
|
||||
if (retval == -1) {
|
||||
if (retval == -1)
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Translate a sockaddr struct into a Python string.
|
||||
* Return None if address family is not AF_INET* or AF_PACKET.
|
||||
*/
|
||||
static PyObject *
|
||||
psutil_convert_ipaddr(struct sockaddr *addr, int family)
|
||||
{
|
||||
char buf[NI_MAXHOST];
|
||||
int err;
|
||||
int addrlen;
|
||||
int n;
|
||||
size_t len;
|
||||
const char *data;
|
||||
char *ptr;
|
||||
|
||||
if (addr == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
else if (family == AF_INET || family == AF_INET6) {
|
||||
if (family == AF_INET)
|
||||
addrlen = sizeof(struct sockaddr_in);
|
||||
else
|
||||
addrlen = sizeof(struct sockaddr_in6);
|
||||
err = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0,
|
||||
NI_NUMERICHOST);
|
||||
if (err != 0) {
|
||||
// XXX we get here on FreeBSD when processing 'lo' / AF_INET6
|
||||
// broadcast. Not sure what to do other than returning None.
|
||||
// ifconfig does not show anything BTW.
|
||||
//PyErr_Format(PyExc_RuntimeError, gai_strerror(err));
|
||||
//return NULL;
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
else {
|
||||
return Py_BuildValue("s", buf);
|
||||
}
|
||||
}
|
||||
#ifdef __linux
|
||||
else if (family == AF_PACKET) {
|
||||
struct sockaddr_ll *lladdr = (struct sockaddr_ll *)addr;
|
||||
len = lladdr->sll_halen;
|
||||
data = (const char *)lladdr->sll_addr;
|
||||
}
|
||||
#endif
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
else if (addr->sa_family == AF_LINK) {
|
||||
// Note: prior to Python 3.4 socket module does not expose
|
||||
// AF_LINK so we'll do.
|
||||
struct sockaddr_dl *dladdr = (struct sockaddr_dl *)addr;
|
||||
len = dladdr->sdl_alen;
|
||||
data = LLADDR(dladdr);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
// unknown family
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
// AF_PACKET or AF_LINK
|
||||
if (len > 0) {
|
||||
ptr = buf;
|
||||
for (n = 0; n < len; ++n) {
|
||||
sprintf(ptr, "%02x:", data[n] & 0xff);
|
||||
ptr += 3;
|
||||
}
|
||||
*--ptr = '\0';
|
||||
return Py_BuildValue("s", buf);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return NICs information a-la ifconfig as a list of tuples.
|
||||
* TODO: on Solaris we won't get any MAC address.
|
||||
*/
|
||||
static PyObject*
|
||||
psutil_net_if_addrs(PyObject* self, PyObject* args)
|
||||
{
|
||||
struct ifaddrs *ifaddr, *ifa;
|
||||
int family;
|
||||
|
||||
PyObject *py_retlist = PyList_New(0);
|
||||
PyObject *py_tuple = NULL;
|
||||
PyObject *py_address = NULL;
|
||||
PyObject *py_netmask = NULL;
|
||||
PyObject *py_broadcast = NULL;
|
||||
|
||||
if (py_retlist == NULL)
|
||||
return NULL;
|
||||
if (getifaddrs(&ifaddr) == -1) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (!ifa->ifa_addr)
|
||||
continue;
|
||||
family = ifa->ifa_addr->sa_family;
|
||||
py_address = psutil_convert_ipaddr(ifa->ifa_addr, family);
|
||||
// If the primary address can't be determined just skip it.
|
||||
// I've never seen this happen on Linux but I did on FreeBSD.
|
||||
if (py_address == Py_None)
|
||||
continue;
|
||||
if (py_address == NULL)
|
||||
goto error;
|
||||
py_netmask = psutil_convert_ipaddr(ifa->ifa_netmask, family);
|
||||
if (py_netmask == NULL)
|
||||
goto error;
|
||||
#ifdef __linux
|
||||
py_broadcast = psutil_convert_ipaddr(ifa->ifa_ifu.ifu_broadaddr, family);
|
||||
#else
|
||||
py_broadcast = psutil_convert_ipaddr(ifa->ifa_broadaddr, family);
|
||||
#endif
|
||||
if (py_broadcast == NULL)
|
||||
goto error;
|
||||
py_tuple = Py_BuildValue(
|
||||
"(siOOO)",
|
||||
ifa->ifa_name,
|
||||
family,
|
||||
py_address,
|
||||
py_netmask,
|
||||
py_broadcast
|
||||
);
|
||||
|
||||
if (! py_tuple)
|
||||
goto error;
|
||||
if (PyList_Append(py_retlist, py_tuple))
|
||||
goto error;
|
||||
Py_DECREF(py_tuple);
|
||||
Py_DECREF(py_address);
|
||||
Py_DECREF(py_netmask);
|
||||
Py_DECREF(py_broadcast);
|
||||
}
|
||||
|
||||
freeifaddrs(ifaddr);
|
||||
return py_retlist;
|
||||
|
||||
error:
|
||||
if (ifaddr != NULL)
|
||||
freeifaddrs(ifaddr);
|
||||
Py_DECREF(py_retlist);
|
||||
Py_XDECREF(py_tuple);
|
||||
Py_XDECREF(py_address);
|
||||
Py_XDECREF(py_netmask);
|
||||
Py_XDECREF(py_broadcast);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* net_if_stats() implementation. This is here because it is common
|
||||
* to both OSX and FreeBSD and I didn't know where else to put it.
|
||||
*/
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
|
||||
#include <sys/sockio.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if.h>
|
||||
|
||||
int psutil_get_nic_speed(int ifm_active) {
|
||||
// Determine NIC speed. Taken from:
|
||||
// http://www.i-scream.org/libstatgrab/
|
||||
// Assuming only ETHER devices
|
||||
switch(IFM_TYPE(ifm_active)) {
|
||||
case IFM_ETHER:
|
||||
switch(IFM_SUBTYPE(ifm_active)) {
|
||||
#if defined(IFM_HPNA_1) && ((!defined(IFM_10G_LR)) \
|
||||
|| (IFM_10G_LR != IFM_HPNA_1))
|
||||
// HomePNA 1.0 (1Mb/s)
|
||||
case(IFM_HPNA_1):
|
||||
return 1;
|
||||
#endif
|
||||
// 10 Mbit
|
||||
case(IFM_10_T): // 10BaseT - RJ45
|
||||
case(IFM_10_2): // 10Base2 - Thinnet
|
||||
case(IFM_10_5): // 10Base5 - AUI
|
||||
case(IFM_10_STP): // 10BaseT over shielded TP
|
||||
case(IFM_10_FL): // 10baseFL - Fiber
|
||||
return 10;
|
||||
// 100 Mbit
|
||||
case(IFM_100_TX): // 100BaseTX - RJ45
|
||||
case(IFM_100_FX): // 100BaseFX - Fiber
|
||||
case(IFM_100_T4): // 100BaseT4 - 4 pair cat 3
|
||||
case(IFM_100_VG): // 100VG-AnyLAN
|
||||
case(IFM_100_T2): // 100BaseT2
|
||||
return 100;
|
||||
// 1000 Mbit
|
||||
case(IFM_1000_SX): // 1000BaseSX - multi-mode fiber
|
||||
case(IFM_1000_LX): // 1000baseLX - single-mode fiber
|
||||
case(IFM_1000_CX): // 1000baseCX - 150ohm STP
|
||||
#if defined(IFM_1000_TX) && !defined(OPENBSD)
|
||||
// FreeBSD 4 and others (but NOT OpenBSD)?
|
||||
case(IFM_1000_TX):
|
||||
#endif
|
||||
#ifdef IFM_1000_FX
|
||||
case(IFM_1000_FX):
|
||||
#endif
|
||||
#ifdef IFM_1000_T
|
||||
case(IFM_1000_T):
|
||||
#endif
|
||||
return 1000;
|
||||
#if defined(IFM_10G_SR) || defined(IFM_10G_LR) || defined(IFM_10G_CX4) \
|
||||
|| defined(IFM_10G_T)
|
||||
#ifdef IFM_10G_SR
|
||||
case(IFM_10G_SR):
|
||||
#endif
|
||||
#ifdef IFM_10G_LR
|
||||
case(IFM_10G_LR):
|
||||
#endif
|
||||
#ifdef IFM_10G_CX4
|
||||
case(IFM_10G_CX4):
|
||||
#endif
|
||||
#ifdef IFM_10G_TWINAX
|
||||
case(IFM_10G_TWINAX):
|
||||
#endif
|
||||
#ifdef IFM_10G_TWINAX_LONG
|
||||
case(IFM_10G_TWINAX_LONG):
|
||||
#endif
|
||||
#ifdef IFM_10G_T
|
||||
case(IFM_10G_T):
|
||||
#endif
|
||||
return 10000;
|
||||
#endif
|
||||
#if defined(IFM_2500_SX)
|
||||
#ifdef IFM_2500_SX
|
||||
case(IFM_2500_SX):
|
||||
#endif
|
||||
return 2500;
|
||||
#endif // any 2.5GBit stuff...
|
||||
// We don't know what it is
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef IFM_TOKEN
|
||||
case IFM_TOKEN:
|
||||
switch(IFM_SUBTYPE(ifm_active)) {
|
||||
case IFM_TOK_STP4: // Shielded twisted pair 4m - DB9
|
||||
case IFM_TOK_UTP4: // Unshielded twisted pair 4m - RJ45
|
||||
return 4;
|
||||
case IFM_TOK_STP16: // Shielded twisted pair 16m - DB9
|
||||
case IFM_TOK_UTP16: // Unshielded twisted pair 16m - RJ45
|
||||
return 16;
|
||||
#if defined(IFM_TOK_STP100) || defined(IFM_TOK_UTP100)
|
||||
#ifdef IFM_TOK_STP100
|
||||
case IFM_TOK_STP100: // Shielded twisted pair 100m - DB9
|
||||
#endif
|
||||
#ifdef IFM_TOK_UTP100
|
||||
case IFM_TOK_UTP100: // Unshielded twisted pair 100m - RJ45
|
||||
#endif
|
||||
return 100;
|
||||
#endif
|
||||
// We don't know what it is
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef IFM_FDDI
|
||||
case IFM_FDDI:
|
||||
switch(IFM_SUBTYPE(ifm_active)) {
|
||||
// We don't know what it is
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case IFM_IEEE80211:
|
||||
switch(IFM_SUBTYPE(ifm_active)) {
|
||||
case IFM_IEEE80211_FH1: // Frequency Hopping 1Mbps
|
||||
case IFM_IEEE80211_DS1: // Direct Sequence 1Mbps
|
||||
return 1;
|
||||
case IFM_IEEE80211_FH2: // Frequency Hopping 2Mbps
|
||||
case IFM_IEEE80211_DS2: // Direct Sequence 2Mbps
|
||||
return 2;
|
||||
case IFM_IEEE80211_DS5: // Direct Sequence 5Mbps
|
||||
return 5;
|
||||
case IFM_IEEE80211_DS11: // Direct Sequence 11Mbps
|
||||
return 11;
|
||||
case IFM_IEEE80211_DS22: // Direct Sequence 22Mbps
|
||||
return 22;
|
||||
// We don't know what it is
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return stats about a particular network interface.
|
||||
* References:
|
||||
* http://www.i-scream.org/libstatgrab/
|
||||
*/
|
||||
static PyObject *
|
||||
psutil_net_if_stats(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *nic_name;
|
||||
int sock = 0;
|
||||
int ret;
|
||||
int duplex;
|
||||
int speed;
|
||||
int mtu;
|
||||
struct ifreq ifr;
|
||||
struct ifmediareq ifmed;
|
||||
|
||||
PyObject *py_is_up = NULL;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "s", &nic_name))
|
||||
return NULL;
|
||||
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock == -1)
|
||||
goto error;
|
||||
strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name));
|
||||
|
||||
// is up?
|
||||
ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
|
||||
if (ret == -1)
|
||||
goto error;
|
||||
if ((ifr.ifr_flags & IFF_UP) != 0)
|
||||
py_is_up = Py_True;
|
||||
else
|
||||
py_is_up = Py_False;
|
||||
Py_INCREF(py_is_up);
|
||||
|
||||
// MTU
|
||||
ret = ioctl(sock, SIOCGIFMTU, &ifr);
|
||||
if (ret == -1)
|
||||
goto error;
|
||||
mtu = ifr.ifr_mtu;
|
||||
|
||||
// speed / duplex
|
||||
memset(&ifmed, 0, sizeof(struct ifmediareq));
|
||||
strlcpy(ifmed.ifm_name, nic_name, sizeof(ifmed.ifm_name));
|
||||
ret = ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmed);
|
||||
if (ret == -1) {
|
||||
speed = 0;
|
||||
duplex = 0;
|
||||
}
|
||||
else {
|
||||
speed = psutil_get_nic_speed(ifmed.ifm_active);
|
||||
if ((ifmed.ifm_active | IFM_FDX) == ifmed.ifm_active)
|
||||
duplex = 2;
|
||||
else if ((ifmed.ifm_active | IFM_HDX) == ifmed.ifm_active)
|
||||
duplex = 1;
|
||||
else
|
||||
duplex = 0;
|
||||
}
|
||||
|
||||
close(sock);
|
||||
Py_DECREF(py_is_up);
|
||||
|
||||
return Py_BuildValue("[Oiii]", py_is_up, duplex, speed, mtu);
|
||||
|
||||
error:
|
||||
Py_XDECREF(py_is_up);
|
||||
if (sock != 0)
|
||||
close(sock);
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
return NULL;
|
||||
}
|
||||
#endif // net_if_stats() implementation
|
||||
|
||||
|
||||
/*
|
||||
* define the psutil C module methods and initialize the module.
|
||||
*/
|
||||
@ -65,6 +458,12 @@ PsutilMethods[] =
|
||||
"Return process priority"},
|
||||
{"setpriority", psutil_posix_setpriority, METH_VARARGS,
|
||||
"Set process priority"},
|
||||
{"net_if_addrs", psutil_net_if_addrs, METH_VARARGS,
|
||||
"Retrieve NICs information"},
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
{"net_if_stats", psutil_net_if_stats, METH_VARARGS,
|
||||
"Return NIC stats."},
|
||||
#endif
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
@ -119,9 +518,13 @@ void init_psutil_posix(void)
|
||||
#else
|
||||
PyObject *module = Py_InitModule("_psutil_posix", PsutilMethods);
|
||||
#endif
|
||||
if (module == NULL) {
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__sun)
|
||||
PyModule_AddIntConstant(module, "AF_LINK", AF_LINK);
|
||||
#endif
|
||||
|
||||
if (module == NULL)
|
||||
INITERROR;
|
||||
}
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return module;
|
||||
#endif
|
||||
|
@ -6,5 +6,10 @@
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
static PyObject* psutil_net_if_addrs(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_posix_getpriority(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_posix_setpriority(PyObject* self, PyObject* args);
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
static PyObject* psutil_net_if_stats(PyObject* self, PyObject* args);
|
||||
#endif
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <sys/mntent.h> // for MNTTAB
|
||||
#include <sys/mnttab.h>
|
||||
#include <sys/procfs.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
#include <utmpx.h>
|
||||
#include <kstat.h>
|
||||
@ -38,6 +40,7 @@
|
||||
#include <stropts.h>
|
||||
#include <inet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include "_psutil_sunos.h"
|
||||
|
||||
@ -201,13 +204,11 @@ proc_io_counters(PyObject* self, PyObject* args)
|
||||
char path[100];
|
||||
prusage_t info;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "i", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "i", &pid))
|
||||
return NULL;
|
||||
}
|
||||
sprintf(path, "/proc/%i/usage", pid);
|
||||
if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) {
|
||||
if (! psutil_file_to_struct(path, (void *)&info, sizeof(info)))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// On Solaris we only have 'pr_ioch' which accounts for bytes read
|
||||
// *and* written.
|
||||
@ -315,9 +316,8 @@ psutil_swap_mem(PyObject *self, PyObject *args)
|
||||
uint_t sout = 0;
|
||||
|
||||
kc = kstat_open();
|
||||
if (kc == NULL) {
|
||||
if (kc == NULL)
|
||||
return PyErr_SetFromErrno(PyExc_OSError);;
|
||||
}
|
||||
|
||||
k = kc->kc_chain;
|
||||
while (k != NULL) {
|
||||
@ -442,8 +442,6 @@ psutil_per_cpu_times(PyObject *self, PyObject *args)
|
||||
kstat_ctl_t *kc;
|
||||
kstat_t *ksp;
|
||||
cpu_stat_t cs;
|
||||
int numcpus;
|
||||
int i;
|
||||
PyObject *py_retlist = PyList_New(0);
|
||||
PyObject *py_cputime = NULL;
|
||||
|
||||
@ -456,29 +454,24 @@ psutil_per_cpu_times(PyObject *self, PyObject *args)
|
||||
goto error;
|
||||
}
|
||||
|
||||
numcpus = sysconf(_SC_NPROCESSORS_ONLN) - 1;
|
||||
for (i = 0; i <= numcpus; i++) {
|
||||
ksp = kstat_lookup(kc, "cpu_stat", i, NULL);
|
||||
if (ksp == NULL) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
goto error;
|
||||
for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
|
||||
if (strcmp(ksp->ks_module, "cpu_stat") == 0) {
|
||||
if (kstat_read(kc, ksp, &cs) == -1) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
goto error;
|
||||
}
|
||||
py_cputime = Py_BuildValue("ffff",
|
||||
(float)cs.cpu_sysinfo.cpu[CPU_USER],
|
||||
(float)cs.cpu_sysinfo.cpu[CPU_KERNEL],
|
||||
(float)cs.cpu_sysinfo.cpu[CPU_IDLE],
|
||||
(float)cs.cpu_sysinfo.cpu[CPU_WAIT]);
|
||||
if (py_cputime == NULL)
|
||||
goto error;
|
||||
if (PyList_Append(py_retlist, py_cputime))
|
||||
goto error;
|
||||
Py_DECREF(py_cputime);
|
||||
py_cputime = NULL;
|
||||
}
|
||||
if (kstat_read(kc, ksp, &cs) == -1) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
goto error;
|
||||
}
|
||||
|
||||
py_cputime = Py_BuildValue("ffff",
|
||||
(float)cs.cpu_sysinfo.cpu[CPU_USER],
|
||||
(float)cs.cpu_sysinfo.cpu[CPU_KERNEL],
|
||||
(float)cs.cpu_sysinfo.cpu[CPU_IDLE],
|
||||
(float)cs.cpu_sysinfo.cpu[CPU_WAIT]);
|
||||
if (py_cputime == NULL)
|
||||
goto error;
|
||||
if (PyList_Append(py_retlist, py_cputime))
|
||||
goto error;
|
||||
Py_DECREF(py_cputime);
|
||||
|
||||
}
|
||||
|
||||
kstat_close(kc);
|
||||
@ -576,17 +569,14 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args)
|
||||
PyObject *pytuple = NULL;
|
||||
PyObject *py_retlist = PyList_New(0);
|
||||
|
||||
if (py_retlist == NULL) {
|
||||
if (py_retlist == NULL)
|
||||
return NULL;
|
||||
}
|
||||
if (! PyArg_ParseTuple(args, "i", &pid)) {
|
||||
if (! PyArg_ParseTuple(args, "i", &pid))
|
||||
goto error;
|
||||
}
|
||||
|
||||
sprintf(path, "/proc/%i/status", pid);
|
||||
if (! psutil_file_to_struct(path, (void *)&status, sizeof(status))) {
|
||||
if (! psutil_file_to_struct(path, (void *)&status, sizeof(status)))
|
||||
goto error;
|
||||
}
|
||||
|
||||
sprintf(path, "/proc/%i/xmap", pid);
|
||||
if (stat(path, &st) == -1) {
|
||||
@ -722,9 +712,8 @@ psutil_net_io_counters(PyObject *self, PyObject *args)
|
||||
(strcmp(ksp->ks_module, "lo") != 0)) {
|
||||
goto skip;
|
||||
*/
|
||||
if ((strcmp(ksp->ks_module, "link") != 0)) {
|
||||
if ((strcmp(ksp->ks_module, "link") != 0))
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (kstat_read(kc, ksp, NULL) == -1) {
|
||||
errno = 0;
|
||||
@ -747,18 +736,18 @@ psutil_net_io_counters(PyObject *self, PyObject *args)
|
||||
|
||||
#if defined(_INT64_TYPE)
|
||||
py_ifc_info = Py_BuildValue("(KKKKkkii)",
|
||||
rbytes->value.ui64,
|
||||
wbytes->value.ui64,
|
||||
rpkts->value.ui64,
|
||||
rbytes->value.ui64,
|
||||
wpkts->value.ui64,
|
||||
rpkts->value.ui64,
|
||||
ierrs->value.ui32,
|
||||
oerrs->value.ui32,
|
||||
#else
|
||||
py_ifc_info = Py_BuildValue("(kkkkkkii)",
|
||||
rbytes->value.ui32,
|
||||
wbytes->value.ui32,
|
||||
rpkts->value.ui32,
|
||||
rbytes->value.ui32,
|
||||
wpkts->value.ui32,
|
||||
rpkts->value.ui32,
|
||||
ierrs->value.ui32,
|
||||
oerrs->value.ui32,
|
||||
#endif
|
||||
@ -810,7 +799,7 @@ static PyObject *
|
||||
psutil_net_connections(PyObject *self, PyObject *args)
|
||||
{
|
||||
long pid;
|
||||
int sd = NULL;
|
||||
int sd = 0;
|
||||
mib2_tcpConnEntry_t *tp = NULL;
|
||||
mib2_udpEntry_t *ude;
|
||||
#if defined(AF_INET6)
|
||||
@ -822,6 +811,7 @@ psutil_net_connections(PyObject *self, PyObject *args)
|
||||
char lip[200], rip[200];
|
||||
int lport, rport;
|
||||
int processed_pid;
|
||||
int databuf_init = 0;
|
||||
struct strbuf ctlbuf, databuf;
|
||||
struct T_optmgmt_req *tor = (struct T_optmgmt_req *)buf;
|
||||
struct T_optmgmt_ack *toa = (struct T_optmgmt_ack *)buf;
|
||||
@ -922,6 +912,7 @@ psutil_net_connections(PyObject *self, PyObject *args)
|
||||
PyErr_NoMemory();
|
||||
goto error;
|
||||
}
|
||||
databuf_init = 1;
|
||||
|
||||
flags = 0;
|
||||
getcode = getmsg(sd, (struct strbuf *)0, &databuf, &flags);
|
||||
@ -948,9 +939,8 @@ psutil_net_connections(PyObject *self, PyObject *args)
|
||||
py_laddr = Py_BuildValue("(si)", lip, lport);
|
||||
if (!py_laddr)
|
||||
goto error;
|
||||
if (rport != 0) {
|
||||
if (rport != 0)
|
||||
py_raddr = Py_BuildValue("(si)", rip, rport);
|
||||
}
|
||||
else {
|
||||
py_raddr = Py_BuildValue("()");
|
||||
}
|
||||
@ -962,9 +952,8 @@ psutil_net_connections(PyObject *self, PyObject *args)
|
||||
py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET, SOCK_STREAM,
|
||||
py_laddr, py_raddr, state,
|
||||
processed_pid);
|
||||
if (!py_tuple) {
|
||||
if (!py_tuple)
|
||||
goto error;
|
||||
}
|
||||
if (PyList_Append(py_retlist, py_tuple))
|
||||
goto error;
|
||||
Py_DECREF(py_tuple);
|
||||
@ -991,12 +980,10 @@ psutil_net_connections(PyObject *self, PyObject *args)
|
||||
py_laddr = Py_BuildValue("(si)", lip, lport);
|
||||
if (!py_laddr)
|
||||
goto error;
|
||||
if (rport != 0) {
|
||||
if (rport != 0)
|
||||
py_raddr = Py_BuildValue("(si)", rip, rport);
|
||||
}
|
||||
else {
|
||||
else
|
||||
py_raddr = Py_BuildValue("()");
|
||||
}
|
||||
if (!py_raddr)
|
||||
goto error;
|
||||
state = tp6->tcp6ConnEntryInfo.ce_state;
|
||||
@ -1004,9 +991,8 @@ psutil_net_connections(PyObject *self, PyObject *args)
|
||||
// add item
|
||||
py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET6, SOCK_STREAM,
|
||||
py_laddr, py_raddr, state, processed_pid);
|
||||
if (!py_tuple) {
|
||||
if (!py_tuple)
|
||||
goto error;
|
||||
}
|
||||
if (PyList_Append(py_retlist, py_tuple))
|
||||
goto error;
|
||||
Py_DECREF(py_tuple);
|
||||
@ -1039,9 +1025,8 @@ psutil_net_connections(PyObject *self, PyObject *args)
|
||||
py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET, SOCK_DGRAM,
|
||||
py_laddr, py_raddr, PSUTIL_CONN_NONE,
|
||||
processed_pid);
|
||||
if (!py_tuple) {
|
||||
if (!py_tuple)
|
||||
goto error;
|
||||
}
|
||||
if (PyList_Append(py_retlist, py_tuple))
|
||||
goto error;
|
||||
Py_DECREF(py_tuple);
|
||||
@ -1049,7 +1034,9 @@ psutil_net_connections(PyObject *self, PyObject *args)
|
||||
}
|
||||
#if defined(AF_INET6)
|
||||
// UDPv6
|
||||
else if (mibhdr->level == MIB2_UDP6 || mibhdr->level == MIB2_UDP6_ENTRY) {
|
||||
else if (mibhdr->level == MIB2_UDP6 ||
|
||||
mibhdr->level == MIB2_UDP6_ENTRY)
|
||||
{
|
||||
ude6 = (mib2_udp6Entry_t *)databuf.buf;
|
||||
num_ent = mibhdr->len / sizeof(mib2_udp6Entry_t);
|
||||
for (i = 0; i < num_ent; i++, ude6++) {
|
||||
@ -1067,9 +1054,8 @@ psutil_net_connections(PyObject *self, PyObject *args)
|
||||
py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET6, SOCK_DGRAM,
|
||||
py_laddr, py_raddr, PSUTIL_CONN_NONE,
|
||||
processed_pid);
|
||||
if (!py_tuple) {
|
||||
if (!py_tuple)
|
||||
goto error;
|
||||
}
|
||||
if (PyList_Append(py_retlist, py_tuple))
|
||||
goto error;
|
||||
Py_DECREF(py_tuple);
|
||||
@ -1087,8 +1073,9 @@ error:
|
||||
Py_XDECREF(py_laddr);
|
||||
Py_XDECREF(py_raddr);
|
||||
Py_DECREF(py_retlist);
|
||||
// TODO : free databuf
|
||||
if (sd != NULL)
|
||||
if (databuf_init == 1)
|
||||
free(databuf.buf);
|
||||
if (sd != 0)
|
||||
close(sd);
|
||||
return NULL;
|
||||
}
|
||||
@ -1137,7 +1124,7 @@ psutil_cpu_count_phys(PyObject *self, PyObject *args)
|
||||
for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
|
||||
if (strcmp(ksp->ks_module, "cpu_info") != 0)
|
||||
continue;
|
||||
if (kstat_read(kc, ksp, NULL) == NULL)
|
||||
if (kstat_read(kc, ksp, NULL) == -1)
|
||||
goto error;
|
||||
ncpus += 1;
|
||||
}
|
||||
@ -1152,8 +1139,117 @@ error:
|
||||
// mimic os.cpu_count()
|
||||
if (kc != NULL)
|
||||
kstat_close(kc);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return stats about a particular network
|
||||
* interface. References:
|
||||
* https://github.com/dpaleino/wicd/blob/master/wicd/backends/be-ioctl.py
|
||||
* http://www.i-scream.org/libstatgrab/
|
||||
*/
|
||||
static PyObject*
|
||||
psutil_net_if_stats(PyObject* self, PyObject* args)
|
||||
{
|
||||
kstat_ctl_t *kc = NULL;
|
||||
kstat_t *ksp;
|
||||
kstat_named_t *knp;
|
||||
int ret;
|
||||
int sock = 0;
|
||||
int duplex;
|
||||
int speed;
|
||||
|
||||
PyObject *py_retdict = PyDict_New();
|
||||
PyObject *py_ifc_info = NULL;
|
||||
PyObject *py_is_up = NULL;
|
||||
|
||||
if (py_retdict == NULL)
|
||||
return NULL;
|
||||
kc = kstat_open();
|
||||
if (kc == NULL)
|
||||
goto error;
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock == -1)
|
||||
goto error;
|
||||
|
||||
for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
|
||||
if (strcmp(ksp->ks_class, "net") == 0) {
|
||||
struct ifreq ifr;
|
||||
|
||||
kstat_read(kc, ksp, NULL);
|
||||
if (ksp->ks_type != KSTAT_TYPE_NAMED)
|
||||
continue;
|
||||
if (strcmp(ksp->ks_class, "net") != 0)
|
||||
continue;
|
||||
|
||||
strncpy(ifr.ifr_name, ksp->ks_name, sizeof(ifr.ifr_name));
|
||||
ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
|
||||
if (ret == -1)
|
||||
continue; // not a network interface
|
||||
|
||||
// is up?
|
||||
if ((ifr.ifr_flags & IFF_UP) != 0) {
|
||||
if ((knp = kstat_data_lookup(ksp, "link_up")) != NULL) {
|
||||
if (knp->value.ui32 != 0u)
|
||||
py_is_up = Py_True;
|
||||
else
|
||||
py_is_up = Py_False;
|
||||
}
|
||||
else {
|
||||
py_is_up = Py_True;
|
||||
}
|
||||
}
|
||||
else {
|
||||
py_is_up = Py_False;
|
||||
}
|
||||
Py_INCREF(py_is_up);
|
||||
|
||||
// duplex
|
||||
duplex = 0; // unknown
|
||||
if ((knp = kstat_data_lookup(ksp, "link_duplex")) != NULL) {
|
||||
if (knp->value.ui32 == 1)
|
||||
duplex = 1; // half
|
||||
else if (knp->value.ui32 == 2)
|
||||
duplex = 2; // full
|
||||
}
|
||||
|
||||
// speed
|
||||
if ((knp = kstat_data_lookup(ksp, "ifspeed")) != NULL)
|
||||
// expressed in bits per sec, we want mega bits per sec
|
||||
speed = (int)knp->value.ui64 / 1000000;
|
||||
else
|
||||
speed = 0;
|
||||
|
||||
// mtu
|
||||
ret = ioctl(sock, SIOCGIFMTU, &ifr);
|
||||
if (ret == -1)
|
||||
goto error;
|
||||
|
||||
py_ifc_info = Py_BuildValue("(Oiii)", py_is_up, duplex, speed,
|
||||
ifr.ifr_mtu);
|
||||
if (!py_ifc_info)
|
||||
goto error;
|
||||
if (PyDict_SetItemString(py_retdict, ksp->ks_name, py_ifc_info))
|
||||
goto error;
|
||||
Py_DECREF(py_ifc_info);
|
||||
}
|
||||
}
|
||||
|
||||
close(sock);
|
||||
kstat_close(kc);
|
||||
return py_retdict;
|
||||
|
||||
error:
|
||||
Py_XDECREF(py_is_up);
|
||||
Py_XDECREF(py_ifc_info);
|
||||
Py_DECREF(py_retdict);
|
||||
if (sock != 0)
|
||||
close(sock);
|
||||
if (kc != NULL)
|
||||
kstat_close(kc);
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -1198,6 +1294,8 @@ PsutilMethods[] =
|
||||
"Return the number of physical CPUs on the system."},
|
||||
{"net_connections", psutil_net_connections, METH_VARARGS,
|
||||
"Return TCP and UDP syste-wide open connections."},
|
||||
{"net_if_stats", psutil_net_if_stats, METH_VARARGS,
|
||||
"Return NIC stats (isup, duplex, speed, mtu)"},
|
||||
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
@ -1254,6 +1352,8 @@ void init_psutil_sunos(void)
|
||||
#else
|
||||
PyObject *module = Py_InitModule("_psutil_sunos", PsutilMethods);
|
||||
#endif
|
||||
PyModule_AddIntConstant(module, "version", PSUTIL_VERSION);
|
||||
|
||||
PyModule_AddIntConstant(module, "SSLEEP", SSLEEP);
|
||||
PyModule_AddIntConstant(module, "SRUN", SRUN);
|
||||
PyModule_AddIntConstant(module, "SZOMB", SZOMB);
|
||||
@ -1281,9 +1381,8 @@ void init_psutil_sunos(void)
|
||||
PyModule_AddIntConstant(module, "TCPS_BOUND", TCPS_BOUND);
|
||||
PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE);
|
||||
|
||||
if (module == NULL) {
|
||||
if (module == NULL)
|
||||
INITERROR;
|
||||
}
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return module;
|
||||
#endif
|
||||
|
@ -25,3 +25,4 @@ static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_swap_mem(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_users(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_net_connections(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_net_if_stats(PyObject* self, PyObject* args);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,22 +13,18 @@ static PyObject* psutil_proc_cmdline(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_cpu_affinity_set(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_cpu_times(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_cpu_times_2(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_create_time(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_create_time_2(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_cwd(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_exe(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_info(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_io_counters(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_io_counters_2(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_is_suspended(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_kill(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_memory_info(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_memory_info_2(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_num_ctx_switches(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_name(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_num_handles(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_num_handles_2(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_open_files(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_priority_get(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_proc_priority_set(PyObject* self, PyObject* args);
|
||||
@ -60,6 +56,8 @@ static PyObject* psutil_pids(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_ppid_map(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_users(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_virtual_mem(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_net_if_addrs(PyObject* self, PyObject* args);
|
||||
static PyObject* psutil_net_if_stats(PyObject* self, PyObject* args);
|
||||
|
||||
// --- windows API bindings
|
||||
|
||||
|
@ -7,21 +7,35 @@
|
||||
"""Windows platform implementation."""
|
||||
|
||||
import errno
|
||||
import functools
|
||||
import os
|
||||
import sys
|
||||
from collections import namedtuple
|
||||
|
||||
from psutil import _common
|
||||
from psutil._common import conn_tmap, usage_percent, isfile_strict
|
||||
from psutil._compat import PY3, xrange, wraps, lru_cache, namedtuple
|
||||
import _psutil_windows as cext
|
||||
from . import _common
|
||||
from . import _psutil_windows as cext
|
||||
from ._common import conn_tmap, usage_percent, isfile_strict
|
||||
from ._common import sockfam_to_enum, socktype_to_enum
|
||||
from ._compat import PY3, xrange, lru_cache, long
|
||||
from ._psutil_windows import (ABOVE_NORMAL_PRIORITY_CLASS,
|
||||
BELOW_NORMAL_PRIORITY_CLASS,
|
||||
HIGH_PRIORITY_CLASS,
|
||||
IDLE_PRIORITY_CLASS,
|
||||
NORMAL_PRIORITY_CLASS,
|
||||
REALTIME_PRIORITY_CLASS)
|
||||
|
||||
if sys.version_info >= (3, 4):
|
||||
import enum
|
||||
else:
|
||||
enum = None
|
||||
|
||||
# process priority constants, import from __init__.py:
|
||||
# http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx
|
||||
__extra__all__ = ["ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS",
|
||||
"HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS",
|
||||
"NORMAL_PRIORITY_CLASS", "REALTIME_PRIORITY_CLASS",
|
||||
#
|
||||
"CONN_DELETE_TCB",
|
||||
"AF_LINK",
|
||||
]
|
||||
|
||||
# --- module level constants (gets pushed up to psutil module)
|
||||
@ -30,6 +44,11 @@ CONN_DELETE_TCB = "DELETE_TCB"
|
||||
WAIT_TIMEOUT = 0x00000102 # 258 in decimal
|
||||
ACCESS_DENIED_SET = frozenset([errno.EPERM, errno.EACCES,
|
||||
cext.ERROR_ACCESS_DENIED])
|
||||
if enum is None:
|
||||
AF_LINK = -1
|
||||
else:
|
||||
AddressFamily = enum.IntEnum('AddressFamily', {'AF_LINK': -1})
|
||||
AF_LINK = AddressFamily.AF_LINK
|
||||
|
||||
TCP_STATUSES = {
|
||||
cext.MIB_TCP_STATE_ESTAB: _common.CONN_ESTABLISHED,
|
||||
@ -47,6 +66,16 @@ TCP_STATUSES = {
|
||||
cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
|
||||
}
|
||||
|
||||
if enum is not None:
|
||||
class Priority(enum.IntEnum):
|
||||
ABOVE_NORMAL_PRIORITY_CLASS = ABOVE_NORMAL_PRIORITY_CLASS
|
||||
BELOW_NORMAL_PRIORITY_CLASS = BELOW_NORMAL_PRIORITY_CLASS
|
||||
HIGH_PRIORITY_CLASS = HIGH_PRIORITY_CLASS
|
||||
IDLE_PRIORITY_CLASS = IDLE_PRIORITY_CLASS
|
||||
NORMAL_PRIORITY_CLASS = NORMAL_PRIORITY_CLASS
|
||||
REALTIME_PRIORITY_CLASS = REALTIME_PRIORITY_CLASS
|
||||
|
||||
globals().update(Priority.__members__)
|
||||
|
||||
scputimes = namedtuple('scputimes', ['user', 'system', 'idle'])
|
||||
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
|
||||
@ -57,6 +86,10 @@ pextmem = namedtuple(
|
||||
pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss'])
|
||||
pmmap_ext = namedtuple(
|
||||
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
|
||||
ntpinfo = namedtuple(
|
||||
'ntpinfo', ['num_handles', 'ctx_switches', 'user_time', 'kernel_time',
|
||||
'create_time', 'num_threads', 'io_rcount', 'io_wcount',
|
||||
'io_rbytes', 'io_wbytes'])
|
||||
|
||||
# set later from __init__.py
|
||||
NoSuchProcess = None
|
||||
@ -166,15 +199,27 @@ def net_connections(kind, _pid=-1):
|
||||
% (kind, ', '.join([repr(x) for x in conn_tmap])))
|
||||
families, types = conn_tmap[kind]
|
||||
rawlist = cext.net_connections(_pid, families, types)
|
||||
ret = []
|
||||
ret = set()
|
||||
for item in rawlist:
|
||||
fd, fam, type, laddr, raddr, status, pid = item
|
||||
status = TCP_STATUSES[status]
|
||||
fam = sockfam_to_enum(fam)
|
||||
type = socktype_to_enum(type)
|
||||
if _pid == -1:
|
||||
nt = _common.sconn(fd, fam, type, laddr, raddr, status, pid)
|
||||
else:
|
||||
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
|
||||
ret.append(nt)
|
||||
ret.add(nt)
|
||||
return list(ret)
|
||||
|
||||
|
||||
def net_if_stats():
|
||||
ret = cext.net_if_stats()
|
||||
for name, items in ret.items():
|
||||
isup, duplex, speed, mtu = items
|
||||
if hasattr(_common, 'NicDuplex'):
|
||||
duplex = _common.NicDuplex(duplex)
|
||||
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
|
||||
return ret
|
||||
|
||||
|
||||
@ -194,21 +239,21 @@ pid_exists = cext.pid_exists
|
||||
net_io_counters = cext.net_io_counters
|
||||
disk_io_counters = cext.disk_io_counters
|
||||
ppid_map = cext.ppid_map # not meant to be public
|
||||
net_if_addrs = cext.net_if_addrs
|
||||
|
||||
|
||||
def wrap_exceptions(fun):
|
||||
"""Decorator which translates bare OSError and WindowsError
|
||||
exceptions into NoSuchProcess and AccessDenied.
|
||||
"""
|
||||
@wraps(fun)
|
||||
@functools.wraps(fun)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
return fun(self, *args, **kwargs)
|
||||
except OSError:
|
||||
except OSError as err:
|
||||
# support for private module import
|
||||
if NoSuchProcess is None or AccessDenied is None:
|
||||
raise
|
||||
err = sys.exc_info()[1]
|
||||
if err.errno in ACCESS_DENIED_SET:
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
if err.errno == errno.ESRCH:
|
||||
@ -220,11 +265,12 @@ def wrap_exceptions(fun):
|
||||
class Process(object):
|
||||
"""Wrapper class around underlying C implementation."""
|
||||
|
||||
__slots__ = ["pid", "_name"]
|
||||
__slots__ = ["pid", "_name", "_ppid"]
|
||||
|
||||
def __init__(self, pid):
|
||||
self.pid = pid
|
||||
self._name = None
|
||||
self._ppid = None
|
||||
|
||||
@wrap_exceptions
|
||||
def name(self):
|
||||
@ -238,7 +284,12 @@ class Process(object):
|
||||
elif self.pid == 4:
|
||||
return "System"
|
||||
else:
|
||||
return os.path.basename(self.exe())
|
||||
try:
|
||||
# Note: this will fail with AD for most PIDs owned
|
||||
# by another user but it's faster.
|
||||
return os.path.basename(self.exe())
|
||||
except AccessDenied:
|
||||
return cext.proc_name(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def exe(self):
|
||||
@ -265,9 +316,10 @@ class Process(object):
|
||||
def _get_raw_meminfo(self):
|
||||
try:
|
||||
return cext.proc_memory_info(self.pid)
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
except OSError as err:
|
||||
if err.errno in ACCESS_DENIED_SET:
|
||||
# TODO: the C ext can probably be refactored in order
|
||||
# to get this from cext.proc_info()
|
||||
return cext.proc_memory_info_2(self.pid)
|
||||
raise
|
||||
|
||||
@ -287,10 +339,9 @@ class Process(object):
|
||||
def memory_maps(self):
|
||||
try:
|
||||
raw = cext.proc_memory_maps(self.pid)
|
||||
except OSError:
|
||||
except OSError as err:
|
||||
# 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 ACCESS_DENIED_SET:
|
||||
raise AccessDenied(self.pid, self._name)
|
||||
if err.errno == errno.ESRCH:
|
||||
@ -334,15 +385,14 @@ class Process(object):
|
||||
return boot_time()
|
||||
try:
|
||||
return cext.proc_create_time(self.pid)
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
except OSError as err:
|
||||
if err.errno in ACCESS_DENIED_SET:
|
||||
return cext.proc_create_time_2(self.pid)
|
||||
return ntpinfo(*cext.proc_info(self.pid)).create_time
|
||||
raise
|
||||
|
||||
@wrap_exceptions
|
||||
def num_threads(self):
|
||||
return cext.proc_num_threads(self.pid)
|
||||
return ntpinfo(*cext.proc_info(self.pid)).num_threads
|
||||
|
||||
@wrap_exceptions
|
||||
def threads(self):
|
||||
@ -357,10 +407,10 @@ class Process(object):
|
||||
def cpu_times(self):
|
||||
try:
|
||||
ret = cext.proc_cpu_times(self.pid)
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
except OSError as err:
|
||||
if err.errno in ACCESS_DENIED_SET:
|
||||
ret = cext.proc_cpu_times_2(self.pid)
|
||||
nt = ntpinfo(*cext.proc_info(self.pid))
|
||||
ret = (nt.user_time, nt.kernel_time)
|
||||
else:
|
||||
raise
|
||||
return _common.pcputimes(*ret)
|
||||
@ -392,10 +442,10 @@ class Process(object):
|
||||
# Convert the first part in the corresponding drive letter
|
||||
# (e.g. "C:\") by using Windows's QueryDosDevice()
|
||||
raw_file_names = cext.proc_open_files(self.pid)
|
||||
for file in raw_file_names:
|
||||
file = _convert_raw_path(file)
|
||||
if isfile_strict(file) and file not in retlist:
|
||||
ntuple = _common.popenfile(file, -1)
|
||||
for _file in raw_file_names:
|
||||
_file = _convert_raw_path(_file)
|
||||
if isfile_strict(_file) and _file not in retlist:
|
||||
ntuple = _common.popenfile(_file, -1)
|
||||
retlist.append(ntuple)
|
||||
return retlist
|
||||
|
||||
@ -405,7 +455,10 @@ class Process(object):
|
||||
|
||||
@wrap_exceptions
|
||||
def nice_get(self):
|
||||
return cext.proc_priority_get(self.pid)
|
||||
value = cext.proc_priority_get(self.pid)
|
||||
if enum is not None:
|
||||
value = Priority(value)
|
||||
return value
|
||||
|
||||
@wrap_exceptions
|
||||
def nice_set(self, value):
|
||||
@ -431,10 +484,10 @@ class Process(object):
|
||||
def io_counters(self):
|
||||
try:
|
||||
ret = cext.proc_io_counters(self.pid)
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
except OSError as err:
|
||||
if err.errno in ACCESS_DENIED_SET:
|
||||
ret = cext.proc_io_counters_2(self.pid)
|
||||
nt = ntpinfo(*cext.proc_info(self.pid))
|
||||
ret = (nt.io_rcount, nt.io_wcount, nt.io_rbytes, nt.io_wbytes)
|
||||
else:
|
||||
raise
|
||||
return _common.pio(*ret)
|
||||
@ -449,7 +502,8 @@ class Process(object):
|
||||
|
||||
@wrap_exceptions
|
||||
def cpu_affinity_get(self):
|
||||
from_bitmask = lambda x: [i for i in xrange(64) if (1 << i) & x]
|
||||
def from_bitmask(x):
|
||||
return [i for i in xrange(64) if (1 << i) & x]
|
||||
bitmask = cext.proc_cpu_affinity_get(self.pid)
|
||||
return from_bitmask(bitmask)
|
||||
|
||||
@ -469,7 +523,11 @@ class Process(object):
|
||||
allcpus = list(range(len(per_cpu_times())))
|
||||
for cpu in value:
|
||||
if cpu not in allcpus:
|
||||
raise ValueError("invalid CPU %r" % cpu)
|
||||
if not isinstance(cpu, (int, long)):
|
||||
raise TypeError(
|
||||
"invalid CPU %r; an integer is required" % cpu)
|
||||
else:
|
||||
raise ValueError("invalid CPU %r" % cpu)
|
||||
|
||||
bitmask = to_bitmask(value)
|
||||
cext.proc_cpu_affinity_set(self.pid, bitmask)
|
||||
@ -478,13 +536,13 @@ class Process(object):
|
||||
def num_handles(self):
|
||||
try:
|
||||
return cext.proc_num_handles(self.pid)
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
except OSError as err:
|
||||
if err.errno in ACCESS_DENIED_SET:
|
||||
return cext.proc_num_handles_2(self.pid)
|
||||
return ntpinfo(*cext.proc_info(self.pid)).num_handles
|
||||
raise
|
||||
|
||||
@wrap_exceptions
|
||||
def num_ctx_switches(self):
|
||||
tupl = cext.proc_num_ctx_switches(self.pid)
|
||||
return _common.pctxsw(*tupl)
|
||||
ctx_switches = ntpinfo(*cext.proc_info(self.pid)).ctx_switches
|
||||
# only voluntary ctx switches are supported
|
||||
return _common.pctxsw(ctx_switches, 0)
|
||||
|
@ -128,9 +128,8 @@ char
|
||||
mib[3] = pid;
|
||||
|
||||
// call with a null buffer first to determine if we need a buffer
|
||||
if (sysctl(mib, 4, NULL, &size, NULL, 0) == -1) {
|
||||
if (sysctl(mib, 4, NULL, &size, NULL, 0) == -1)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path = malloc(size);
|
||||
if (path == NULL) {
|
||||
@ -213,14 +212,11 @@ psutil_get_arg_list(long pid)
|
||||
PyObject *retlist = Py_BuildValue("[]");
|
||||
PyObject *item = NULL;
|
||||
|
||||
if (pid < 0) {
|
||||
if (pid < 0)
|
||||
return retlist;
|
||||
}
|
||||
|
||||
argstr = psutil_get_cmd_args(pid, &argsize);
|
||||
if (argstr == NULL) {
|
||||
if (argstr == NULL)
|
||||
goto error;
|
||||
}
|
||||
|
||||
// args are returned as a flattened string with \0 separators between
|
||||
// arguments add each string to the list then step forward to the next
|
||||
@ -256,30 +252,14 @@ int
|
||||
psutil_pid_exists(long pid)
|
||||
{
|
||||
int kill_ret;
|
||||
if (pid < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pid < 0)
|
||||
return 0;
|
||||
// if kill returns success of permission denied we know it's a valid PID
|
||||
kill_ret = kill(pid , 0);
|
||||
if ((0 == kill_ret) || (EPERM == errno)) {
|
||||
if ((0 == kill_ret) || (EPERM == errno))
|
||||
return 1;
|
||||
}
|
||||
|
||||
// otherwise return 0 for PID not found
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set exception to AccessDenied if pid exists else NoSuchProcess.
|
||||
*/
|
||||
int
|
||||
psutil_raise_ad_or_nsp(pid) {
|
||||
if (psutil_pid_exists(pid) == 0) {
|
||||
NoSuchProcess();
|
||||
}
|
||||
else {
|
||||
AccessDenied();
|
||||
}
|
||||
}
|
||||
|
@ -32,15 +32,12 @@ psutil_pid_exists(long pid)
|
||||
int kill_ret;
|
||||
|
||||
// save some time if it's an invalid PID
|
||||
if (pid < 0) {
|
||||
if (pid < 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if kill returns success of permission denied we know it's a valid PID
|
||||
kill_ret = kill(pid , 0);
|
||||
if ( (0 == kill_ret) || (EPERM == errno) ) {
|
||||
if ( (0 == kill_ret) || (EPERM == errno))
|
||||
return 1;
|
||||
}
|
||||
|
||||
// otherwise return 0 for PID not found
|
||||
return 0;
|
||||
@ -85,34 +82,29 @@ psutil_get_proc_list(kinfo_proc **procList, size_t *procCount)
|
||||
*/
|
||||
while (lim-- > 0) {
|
||||
size = 0;
|
||||
if (sysctl((int *)mib3, 3, NULL, &size, NULL, 0) == -1) {
|
||||
if (sysctl((int *)mib3, 3, NULL, &size, NULL, 0) == -1)
|
||||
return errno;
|
||||
}
|
||||
|
||||
size2 = size + (size >> 3); // add some
|
||||
if (size2 > size) {
|
||||
ptr = malloc(size2);
|
||||
if (ptr == NULL) {
|
||||
if (ptr == NULL)
|
||||
ptr = malloc(size);
|
||||
} else {
|
||||
else
|
||||
size = size2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ptr = malloc(size);
|
||||
}
|
||||
if (ptr == NULL) {
|
||||
if (ptr == NULL)
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if (sysctl((int *)mib3, 3, ptr, &size, NULL, 0) == -1) {
|
||||
err = errno;
|
||||
free(ptr);
|
||||
if (err != ENOMEM) {
|
||||
if (err != ENOMEM)
|
||||
return err;
|
||||
}
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
*procList = (kinfo_proc *)ptr;
|
||||
*procCount = size / sizeof(kinfo_proc);
|
||||
return 0;
|
||||
@ -130,9 +122,8 @@ psutil_get_argmax()
|
||||
int mib[] = { CTL_KERN, KERN_ARGMAX };
|
||||
size_t size = sizeof(argmax);
|
||||
|
||||
if (sysctl(mib, 2, &argmax, &size, NULL, 0) == 0) {
|
||||
if (sysctl(mib, 2, &argmax, &size, NULL, 0) == 0)
|
||||
return argmax;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -153,9 +144,8 @@ psutil_get_arg_list(long pid)
|
||||
PyObject *arglist = NULL;
|
||||
|
||||
// special case for PID 0 (kernel_task) where cmdline cannot be fetched
|
||||
if (pid == 0) {
|
||||
if (pid == 0)
|
||||
return Py_BuildValue("[]");
|
||||
}
|
||||
|
||||
// read argmax and allocate memory for argument space.
|
||||
argmax = psutil_get_argmax();
|
||||
@ -177,11 +167,10 @@ psutil_get_arg_list(long pid)
|
||||
if (sysctl(mib, 3, procargs, &argmax, NULL, 0) < 0) {
|
||||
if (EINVAL == errno) {
|
||||
// EINVAL == access denied OR nonexistent PID
|
||||
if ( psutil_pid_exists(pid) ) {
|
||||
if (psutil_pid_exists(pid))
|
||||
AccessDenied();
|
||||
} else {
|
||||
else
|
||||
NoSuchProcess();
|
||||
}
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
@ -201,9 +190,8 @@ psutil_get_arg_list(long pid)
|
||||
|
||||
// skip ahead to the first argument
|
||||
for (; arg_ptr < arg_end; arg_ptr++) {
|
||||
if (*arg_ptr != '\0') {
|
||||
if (*arg_ptr != '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// iterate through arguments
|
||||
|
41
python/psutil/psutil/arch/windows/inet_ntop.c
Normal file
41
python/psutil/psutil/arch/windows/inet_ntop.c
Normal file
@ -0,0 +1,41 @@
|
||||
#include "inet_ntop.h"
|
||||
|
||||
// From: https://memset.wordpress.com/2010/10/09/inet_ntop-for-win32/
|
||||
PCSTR
|
||||
WSAAPI
|
||||
inet_ntop(
|
||||
__in INT Family,
|
||||
__in PVOID pAddr,
|
||||
__out_ecount(StringBufSize) PSTR pStringBuf,
|
||||
__in size_t StringBufSize
|
||||
)
|
||||
{
|
||||
DWORD dwAddressLength = 0;
|
||||
struct sockaddr_storage srcaddr;
|
||||
struct sockaddr_in *srcaddr4 = (struct sockaddr_in*) &srcaddr;
|
||||
struct sockaddr_in6 *srcaddr6 = (struct sockaddr_in6*) &srcaddr;
|
||||
|
||||
memset(&srcaddr, 0, sizeof(struct sockaddr_storage));
|
||||
srcaddr.ss_family = Family;
|
||||
|
||||
if (Family == AF_INET)
|
||||
{
|
||||
dwAddressLength = sizeof(struct sockaddr_in);
|
||||
memcpy(&(srcaddr4->sin_addr), pAddr, sizeof(struct in_addr));
|
||||
} else if (Family == AF_INET6)
|
||||
{
|
||||
dwAddressLength = sizeof(struct sockaddr_in6);
|
||||
memcpy(&(srcaddr6->sin6_addr), pAddr, sizeof(struct in6_addr));
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (WSAAddressToString((LPSOCKADDR) &srcaddr,
|
||||
dwAddressLength,
|
||||
0,
|
||||
pStringBuf,
|
||||
(LPDWORD) &StringBufSize) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
return pStringBuf;
|
||||
}
|
10
python/psutil/psutil/arch/windows/inet_ntop.h
Normal file
10
python/psutil/psutil/arch/windows/inet_ntop.h
Normal file
@ -0,0 +1,10 @@
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
PCSTR
|
||||
WSAAPI
|
||||
inet_ntop(
|
||||
__in INT Family,
|
||||
__in PVOID pAddr,
|
||||
__out_ecount(StringBufSize) PSTR pStringBuf,
|
||||
__in size_t StringBufSize
|
||||
);
|
@ -3,6 +3,9 @@
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#if !defined(__NTEXTAPI_H__)
|
||||
#define __NTEXTAPI_H__
|
||||
#include <winternl.h>
|
||||
|
||||
typedef enum _KTHREAD_STATE {
|
||||
Initialized,
|
||||
@ -63,23 +66,6 @@ typedef struct _CLIENT_ID {
|
||||
HANDLE UniqueThread;
|
||||
} CLIENT_ID, *PCLIENT_ID;
|
||||
|
||||
|
||||
typedef struct _UNICODE_STRING {
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR Buffer;
|
||||
} UNICODE_STRING, *PUNICODE_STRING;
|
||||
|
||||
typedef struct _SYSTEM_TIMEOFDAY_INFORMATION {
|
||||
LARGE_INTEGER BootTime;
|
||||
LARGE_INTEGER CurrentTime;
|
||||
LARGE_INTEGER TimeZoneBias;
|
||||
ULONG TimeZoneId;
|
||||
ULONG Reserved;
|
||||
ULONGLONG BootTimeBias;
|
||||
ULONGLONG SleepTimeBias;
|
||||
} SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION;
|
||||
|
||||
typedef struct _SYSTEM_THREAD_INFORMATION {
|
||||
LARGE_INTEGER KernelTime;
|
||||
LARGE_INTEGER UserTime;
|
||||
@ -108,7 +94,7 @@ typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION {
|
||||
ULONG_PTR Reserved4;
|
||||
} SYSTEM_EXTENDED_THREAD_INFORMATION, *PSYSTEM_EXTENDED_THREAD_INFORMATION;
|
||||
|
||||
typedef struct _SYSTEM_PROCESS_INFORMATION {
|
||||
typedef struct _SYSTEM_PROCESS_INFORMATION2 {
|
||||
ULONG NextEntryOffset;
|
||||
ULONG NumberOfThreads;
|
||||
LARGE_INTEGER SpareLi1;
|
||||
@ -143,31 +129,10 @@ typedef struct _SYSTEM_PROCESS_INFORMATION {
|
||||
LARGE_INTEGER WriteTransferCount;
|
||||
LARGE_INTEGER OtherTransferCount;
|
||||
SYSTEM_THREAD_INFORMATION Threads[1];
|
||||
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
|
||||
} SYSTEM_PROCESS_INFORMATION2, *PSYSTEM_PROCESS_INFORMATION2;
|
||||
|
||||
|
||||
// structures and enums from winternl.h (not available under mingw)
|
||||
typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
|
||||
LARGE_INTEGER IdleTime;
|
||||
LARGE_INTEGER KernelTime;
|
||||
LARGE_INTEGER UserTime;
|
||||
LARGE_INTEGER Reserved1[2];
|
||||
ULONG Reserved2;
|
||||
} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION,
|
||||
*PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
|
||||
|
||||
|
||||
typedef enum _SYSTEM_INFORMATION_CLASS {
|
||||
SystemBasicInformation = 0,
|
||||
SystemPerformanceInformation = 2,
|
||||
SystemTimeOfDayInformation = 3,
|
||||
SystemProcessInformation = 5,
|
||||
SystemProcessorPerformanceInformation = 8,
|
||||
SystemInterruptInformation = 23,
|
||||
SystemExceptionInformation = 33,
|
||||
SystemRegistryQuotaInformation = 37,
|
||||
SystemLookasideInformation = 45
|
||||
} SYSTEM_INFORMATION_CLASS;
|
||||
#define SYSTEM_PROCESS_INFORMATION SYSTEM_PROCESS_INFORMATION2
|
||||
#define PSYSTEM_PROCESS_INFORMATION PSYSTEM_PROCESS_INFORMATION2
|
||||
|
||||
|
||||
// ================================================
|
||||
@ -186,32 +151,9 @@ typedef struct _WINSTATION_INFO {
|
||||
FILETIME CurrentTime;
|
||||
} WINSTATION_INFO, *PWINSTATION_INFO;
|
||||
|
||||
typedef enum _WINSTATIONINFOCLASS {
|
||||
WinStationInformation = 8
|
||||
} WINSTATIONINFOCLASS;
|
||||
|
||||
typedef BOOLEAN (WINAPI * PWINSTATIONQUERYINFORMATIONW)
|
||||
(HANDLE,ULONG,WINSTATIONINFOCLASS,PVOID,ULONG,PULONG);
|
||||
|
||||
typedef struct _WINSTATIONINFORMATIONW {
|
||||
BYTE Reserved2[70];
|
||||
ULONG LogonId;
|
||||
BYTE Reserved3[1140];
|
||||
} WINSTATIONINFORMATIONW, *PWINSTATIONINFORMATIONW;
|
||||
|
||||
// mingw support:
|
||||
// http://www.koders.com/c/fid7C02CAE627C526914CDEB427405B51DF393A5EFA.aspx
|
||||
#ifndef _INC_WTSAPI
|
||||
typedef struct _WTS_CLIENT_ADDRESS {
|
||||
DWORD AddressFamily; // AF_INET, AF_IPX, AF_NETBIOS, AF_UNSPEC
|
||||
BYTE Address[20]; // client network address
|
||||
} WTS_CLIENT_ADDRESS, * PWTS_CLIENT_ADDRESS;
|
||||
|
||||
HANDLE WINAPI WTSOpenServerA(IN LPSTR pServerName);
|
||||
|
||||
VOID WINAPI WTSCloseServer(IN HANDLE hServer);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* NtQueryInformationProcess code taken from
|
||||
@ -235,16 +177,9 @@ typedef NTSTATUS (NTAPI *_NtSetInformationProcess)(
|
||||
DWORD ProcessInformationLength
|
||||
);
|
||||
|
||||
typedef struct _PROCESS_BASIC_INFORMATION {
|
||||
PVOID Reserved1;
|
||||
PVOID PebBaseAddress;
|
||||
PVOID Reserved2[2];
|
||||
ULONG_PTR UniqueProcessId;
|
||||
PVOID Reserved3;
|
||||
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
|
||||
|
||||
typedef enum _PROCESSINFOCLASS {
|
||||
ProcessBasicInformation,
|
||||
typedef enum _PROCESSINFOCLASS2 {
|
||||
_ProcessBasicInformation,
|
||||
ProcessQuotaLimits,
|
||||
ProcessIoCounters,
|
||||
ProcessVmCounters,
|
||||
@ -270,7 +205,7 @@ typedef enum _PROCESSINFOCLASS {
|
||||
ProcessDeviceMap,
|
||||
ProcessSessionInformation,
|
||||
ProcessForegroundInformation,
|
||||
ProcessWow64Information,
|
||||
_ProcessWow64Information,
|
||||
/* added after XP+ */
|
||||
ProcessImageFileName,
|
||||
ProcessLUIDDeviceMapsEnabled,
|
||||
@ -284,4 +219,10 @@ typedef enum _PROCESSINFOCLASS {
|
||||
ProcessCookie,
|
||||
ProcessImageInformation,
|
||||
MaxProcessInfoClass
|
||||
} PROCESSINFOCLASS;
|
||||
} PROCESSINFOCLASS2;
|
||||
|
||||
#define PROCESSINFOCLASS PROCESSINFOCLASS2
|
||||
#define ProcessBasicInformation _ProcessBasicInformation
|
||||
#define ProcessWow64Information _ProcessWow64Information
|
||||
|
||||
#endif // __NTEXTAPI_H__
|
||||
|
@ -4,108 +4,22 @@
|
||||
* found in the LICENSE file.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif
|
||||
|
||||
#include <Python.h>
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include "process_handles.h"
|
||||
|
||||
#ifndef NT_SUCCESS
|
||||
#define NT_SUCCESS(x) ((x) >= 0)
|
||||
#endif
|
||||
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
|
||||
static _NtQuerySystemInformation __NtQuerySystemInformation = NULL;
|
||||
static _NtQueryObject __NtQueryObject = NULL;
|
||||
|
||||
#define SystemHandleInformation 16
|
||||
#define ObjectBasicInformation 0
|
||||
#define ObjectNameInformation 1
|
||||
#define ObjectTypeInformation 2
|
||||
|
||||
|
||||
typedef LONG NTSTATUS;
|
||||
|
||||
typedef struct _UNICODE_STRING {
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR Buffer;
|
||||
} UNICODE_STRING, *PUNICODE_STRING;
|
||||
|
||||
typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
|
||||
ULONG SystemInformationClass,
|
||||
PVOID SystemInformation,
|
||||
ULONG SystemInformationLength,
|
||||
PULONG ReturnLength
|
||||
);
|
||||
|
||||
typedef NTSTATUS (NTAPI *_NtDuplicateObject)(
|
||||
HANDLE SourceProcessHandle,
|
||||
HANDLE SourceHandle,
|
||||
HANDLE TargetProcessHandle,
|
||||
PHANDLE TargetHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
ULONG Attributes,
|
||||
ULONG Options
|
||||
);
|
||||
|
||||
typedef NTSTATUS (NTAPI *_NtQueryObject)(
|
||||
HANDLE ObjectHandle,
|
||||
ULONG ObjectInformationClass,
|
||||
PVOID ObjectInformation,
|
||||
ULONG ObjectInformationLength,
|
||||
PULONG ReturnLength
|
||||
);
|
||||
|
||||
typedef struct _SYSTEM_HANDLE {
|
||||
ULONG ProcessId;
|
||||
BYTE ObjectTypeNumber;
|
||||
BYTE Flags;
|
||||
USHORT Handle;
|
||||
PVOID Object;
|
||||
ACCESS_MASK GrantedAccess;
|
||||
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
|
||||
|
||||
typedef struct _SYSTEM_HANDLE_INFORMATION {
|
||||
ULONG HandleCount;
|
||||
SYSTEM_HANDLE Handles[1];
|
||||
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
|
||||
|
||||
typedef enum _POOL_TYPE {
|
||||
NonPagedPool,
|
||||
PagedPool,
|
||||
NonPagedPoolMustSucceed,
|
||||
DontUseThisType,
|
||||
NonPagedPoolCacheAligned,
|
||||
PagedPoolCacheAligned,
|
||||
NonPagedPoolCacheAlignedMustS
|
||||
} POOL_TYPE, *PPOOL_TYPE;
|
||||
|
||||
typedef struct _OBJECT_TYPE_INFORMATION {
|
||||
UNICODE_STRING Name;
|
||||
ULONG TotalNumberOfObjects;
|
||||
ULONG TotalNumberOfHandles;
|
||||
ULONG TotalPagedPoolUsage;
|
||||
ULONG TotalNonPagedPoolUsage;
|
||||
ULONG TotalNamePoolUsage;
|
||||
ULONG TotalHandleTableUsage;
|
||||
ULONG HighWaterNumberOfObjects;
|
||||
ULONG HighWaterNumberOfHandles;
|
||||
ULONG HighWaterPagedPoolUsage;
|
||||
ULONG HighWaterNonPagedPoolUsage;
|
||||
ULONG HighWaterNamePoolUsage;
|
||||
ULONG HighWaterHandleTableUsage;
|
||||
ULONG InvalidAttributes;
|
||||
GENERIC_MAPPING GenericMapping;
|
||||
ULONG ValidAccess;
|
||||
BOOLEAN SecurityRequired;
|
||||
BOOLEAN MaintainHandleCount;
|
||||
USHORT MaintainTypeList;
|
||||
POOL_TYPE PoolType;
|
||||
ULONG PagedPoolUsage;
|
||||
ULONG NonPagedPoolUsage;
|
||||
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
|
||||
CRITICAL_SECTION g_cs;
|
||||
BOOL g_initialized = FALSE;
|
||||
NTSTATUS g_status;
|
||||
HANDLE g_hFile = NULL;
|
||||
HANDLE g_hEvtStart = NULL;
|
||||
HANDLE g_hEvtFinish = NULL;
|
||||
HANDLE g_hThread = NULL;
|
||||
PUNICODE_STRING g_pNameBuffer = NULL;
|
||||
ULONG g_dwSize = 0;
|
||||
ULONG g_dwLength = 0;
|
||||
PVOID g_fiber = NULL;
|
||||
|
||||
|
||||
PVOID
|
||||
@ -114,224 +28,506 @@ GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName)
|
||||
return GetProcAddress(GetModuleHandleA(LibraryName), ProcName);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
psutil_get_open_files(long dwPid, HANDLE hProcess)
|
||||
{
|
||||
OSVERSIONINFO osvi;
|
||||
|
||||
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&osvi);
|
||||
|
||||
// Threaded version only works for Vista+
|
||||
if (osvi.dwMajorVersion >= 6)
|
||||
return psutil_get_open_files_ntqueryobject(dwPid, hProcess);
|
||||
else
|
||||
return psutil_get_open_files_getmappedfilename(dwPid, hProcess);
|
||||
}
|
||||
|
||||
VOID
|
||||
psutil_get_open_files_init(BOOL threaded)
|
||||
{
|
||||
if (g_initialized == TRUE)
|
||||
return;
|
||||
|
||||
// Resolve the Windows API calls
|
||||
__NtQuerySystemInformation =
|
||||
GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");
|
||||
__NtQueryObject = GetLibraryProcAddress("ntdll.dll", "NtQueryObject");
|
||||
|
||||
// Create events for signalling work between threads
|
||||
if (threaded == TRUE) {
|
||||
g_hEvtStart = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
g_hEvtFinish = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
InitializeCriticalSection(&g_cs);
|
||||
}
|
||||
|
||||
g_initialized = TRUE;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
psutil_get_open_files(long pid, HANDLE processHandle)
|
||||
psutil_get_open_files_ntqueryobject(long dwPid, HANDLE hProcess)
|
||||
{
|
||||
_NtQuerySystemInformation NtQuerySystemInformation =
|
||||
GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");
|
||||
_NtQueryObject NtQueryObject =
|
||||
GetLibraryProcAddress("ntdll.dll", "NtQueryObject");
|
||||
NTSTATUS status;
|
||||
PSYSTEM_HANDLE_INFORMATION_EX pHandleInfo = NULL;
|
||||
DWORD dwInfoSize = 0x10000;
|
||||
DWORD dwRet = 0;
|
||||
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX hHandle = NULL;
|
||||
DWORD i = 0;
|
||||
BOOLEAN error = FALSE;
|
||||
PyObject* pyListFiles = NULL;
|
||||
PyObject* pyFilePath = NULL;
|
||||
DWORD dwWait = 0;
|
||||
|
||||
NTSTATUS status;
|
||||
PSYSTEM_HANDLE_INFORMATION handleInfo;
|
||||
ULONG handleInfoSize = 0x10000;
|
||||
ULONG i;
|
||||
ULONG fileNameLength;
|
||||
PyObject *filesList = Py_BuildValue("[]");
|
||||
PyObject *arg = NULL;
|
||||
PyObject *fileFromWchar = NULL;
|
||||
if (g_initialized == FALSE)
|
||||
psutil_get_open_files_init(TRUE);
|
||||
|
||||
if (filesList == NULL)
|
||||
return NULL;
|
||||
// Due to the use of global variables, ensure only 1 call
|
||||
// to psutil_get_open_files() is running
|
||||
EnterCriticalSection(&g_cs);
|
||||
|
||||
handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize);
|
||||
if (handleInfo == NULL) {
|
||||
Py_DECREF(filesList);
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
if (__NtQuerySystemInformation == NULL ||
|
||||
__NtQueryObject == NULL ||
|
||||
g_hEvtStart == NULL ||
|
||||
g_hEvtFinish == NULL)
|
||||
|
||||
// NtQuerySystemInformation won't give us the correct buffer size,
|
||||
// so we guess by doubling the buffer size.
|
||||
while ((status = NtQuerySystemInformation(
|
||||
SystemHandleInformation,
|
||||
handleInfo,
|
||||
handleInfoSize,
|
||||
NULL
|
||||
)) == STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
handleInfo = (PSYSTEM_HANDLE_INFORMATION) \
|
||||
realloc(handleInfo, handleInfoSize *= 2);
|
||||
PyErr_SetFromWindowsErr(0);
|
||||
error = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Py_BuildValue raises an exception if NULL is returned
|
||||
pyListFiles = PyList_New(0);
|
||||
if (pyListFiles == NULL) {
|
||||
error = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
do {
|
||||
if (pHandleInfo != NULL) {
|
||||
HeapFree(GetProcessHeap(), 0, pHandleInfo);
|
||||
pHandleInfo = NULL;
|
||||
}
|
||||
|
||||
// NtQuerySystemInformation won't give us the correct buffer size,
|
||||
// so we guess by doubling the buffer size.
|
||||
dwInfoSize *= 2;
|
||||
pHandleInfo = HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
dwInfoSize);
|
||||
|
||||
if (pHandleInfo == NULL) {
|
||||
PyErr_NoMemory();
|
||||
error = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
} while ((status = __NtQuerySystemInformation(
|
||||
SystemExtendedHandleInformation,
|
||||
pHandleInfo,
|
||||
dwInfoSize,
|
||||
&dwRet)) == STATUS_INFO_LENGTH_MISMATCH);
|
||||
|
||||
// NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH
|
||||
if (!NT_SUCCESS(status)) {
|
||||
Py_DECREF(filesList);
|
||||
free(handleInfo);
|
||||
return NULL;
|
||||
PyErr_SetFromWindowsErr(HRESULT_FROM_NT(status));
|
||||
error = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (i = 0; i < handleInfo->HandleCount; i++) {
|
||||
SYSTEM_HANDLE handle = handleInfo->Handles[i];
|
||||
HANDLE dupHandle = NULL;
|
||||
HANDLE mapHandle = NULL;
|
||||
POBJECT_TYPE_INFORMATION objectTypeInfo = NULL;
|
||||
PVOID objectNameInfo;
|
||||
UNICODE_STRING objectName;
|
||||
ULONG returnLength;
|
||||
DWORD error = 0;
|
||||
fileFromWchar = NULL;
|
||||
arg = NULL;
|
||||
for (i = 0; i < pHandleInfo->NumberOfHandles; i++) {
|
||||
hHandle = &pHandleInfo->Handles[i];
|
||||
|
||||
// Check if this handle belongs to the PID the user specified.
|
||||
if (handle.ProcessId != pid)
|
||||
continue;
|
||||
// Check if this hHandle belongs to the PID the user specified.
|
||||
if (hHandle->UniqueProcessId != (HANDLE)dwPid ||
|
||||
hHandle->ObjectTypeIndex != HANDLE_TYPE_FILE)
|
||||
goto loop_cleanup;
|
||||
|
||||
// Skip handles with the following access codes as the next call
|
||||
// to NtDuplicateObject() or NtQueryObject() might hang forever.
|
||||
if ((handle.GrantedAccess == 0x0012019f)
|
||||
|| (handle.GrantedAccess == 0x001a019f)
|
||||
|| (handle.GrantedAccess == 0x00120189)
|
||||
|| (handle.GrantedAccess == 0x00100000)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!DuplicateHandle(processHandle,
|
||||
handle.Handle,
|
||||
if (!DuplicateHandle(hProcess,
|
||||
hHandle->HandleValue,
|
||||
GetCurrentProcess(),
|
||||
&dupHandle,
|
||||
&g_hFile,
|
||||
0,
|
||||
TRUE,
|
||||
DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
//printf("[%#x] Error: %d \n", handle.Handle, GetLastError());
|
||||
continue;
|
||||
}
|
||||
{
|
||||
/*
|
||||
printf("[%d] DuplicateHandle (%#x): %#x \n",
|
||||
dwPid,
|
||||
hHandle->HandleValue,
|
||||
GetLastError());
|
||||
*/
|
||||
goto loop_cleanup;
|
||||
}
|
||||
|
||||
// Guess buffer size is MAX_PATH + 1
|
||||
g_dwLength = (MAX_PATH+1) * sizeof(WCHAR);
|
||||
|
||||
mapHandle = CreateFileMapping(dupHandle,
|
||||
NULL,
|
||||
PAGE_READONLY,
|
||||
0,
|
||||
0,
|
||||
NULL);
|
||||
if (mapHandle == NULL) {
|
||||
error = GetLastError();
|
||||
if (error == ERROR_INVALID_HANDLE || error == ERROR_BAD_EXE_FORMAT) {
|
||||
CloseHandle(dupHandle);
|
||||
//printf("CreateFileMapping Error: %d\n", error);
|
||||
continue;
|
||||
do {
|
||||
// Release any previously allocated buffer
|
||||
if (g_pNameBuffer != NULL) {
|
||||
HeapFree(GetProcessHeap(), 0, g_pNameBuffer);
|
||||
g_pNameBuffer = NULL;
|
||||
g_dwSize = 0;
|
||||
}
|
||||
}
|
||||
CloseHandle(mapHandle);
|
||||
|
||||
// Query the object type.
|
||||
objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000);
|
||||
if (!NT_SUCCESS(NtQueryObject(
|
||||
dupHandle,
|
||||
ObjectTypeInformation,
|
||||
objectTypeInfo,
|
||||
0x1000,
|
||||
NULL
|
||||
)))
|
||||
{
|
||||
free(objectTypeInfo);
|
||||
CloseHandle(dupHandle);
|
||||
continue;
|
||||
}
|
||||
// NtQueryObject puts the required buffer size in g_dwLength
|
||||
// WinXP edge case puts g_dwLength == 0, just skip this handle
|
||||
if (g_dwLength == 0)
|
||||
goto loop_cleanup;
|
||||
|
||||
objectNameInfo = malloc(0x1000);
|
||||
if (!NT_SUCCESS(NtQueryObject(
|
||||
dupHandle,
|
||||
ObjectNameInformation,
|
||||
objectNameInfo,
|
||||
0x1000,
|
||||
&returnLength
|
||||
)))
|
||||
{
|
||||
// Reallocate the buffer and try again.
|
||||
objectNameInfo = realloc(objectNameInfo, returnLength);
|
||||
if (!NT_SUCCESS(NtQueryObject(
|
||||
dupHandle,
|
||||
ObjectNameInformation,
|
||||
objectNameInfo,
|
||||
returnLength,
|
||||
NULL
|
||||
)))
|
||||
{
|
||||
// We have the type name, so just display that.
|
||||
g_dwSize = g_dwLength;
|
||||
if (g_dwSize > 0) {
|
||||
g_pNameBuffer = HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
g_dwSize);
|
||||
|
||||
if (g_pNameBuffer == NULL)
|
||||
goto loop_cleanup;
|
||||
}
|
||||
|
||||
dwWait = psutil_NtQueryObject();
|
||||
|
||||
// If the call does not return, skip this handle
|
||||
if (dwWait != WAIT_OBJECT_0)
|
||||
goto loop_cleanup;
|
||||
|
||||
} while (g_status == STATUS_INFO_LENGTH_MISMATCH);
|
||||
|
||||
// NtQueryObject stopped returning STATUS_INFO_LENGTH_MISMATCH
|
||||
if (!NT_SUCCESS(g_status))
|
||||
goto loop_cleanup;
|
||||
|
||||
// Convert to PyUnicode and append it to the return list
|
||||
if (g_pNameBuffer->Length > 0) {
|
||||
/*
|
||||
printf("[%d] Filename (%#x) %#d bytes: %S\n",
|
||||
dwPid,
|
||||
hHandle->HandleValue,
|
||||
g_pNameBuffer->Length,
|
||||
g_pNameBuffer->Buffer);
|
||||
*/
|
||||
|
||||
pyFilePath = PyUnicode_FromWideChar(g_pNameBuffer->Buffer,
|
||||
g_pNameBuffer->Length/2);
|
||||
if (pyFilePath == NULL) {
|
||||
/*
|
||||
printf(
|
||||
"[%#x] %.*S: (could not get name)\n",
|
||||
handle.Handle,
|
||||
objectTypeInfo->Name.Length / 2,
|
||||
objectTypeInfo->Name.Buffer
|
||||
);
|
||||
printf("[%d] PyUnicode_FromWideChar (%#x): %#x \n",
|
||||
dwPid,
|
||||
hHandle->HandleValue,
|
||||
GetLastError());
|
||||
*/
|
||||
free(objectTypeInfo);
|
||||
free(objectNameInfo);
|
||||
CloseHandle(dupHandle);
|
||||
continue;
|
||||
error = TRUE;
|
||||
goto loop_cleanup;
|
||||
}
|
||||
|
||||
if (PyList_Append(pyListFiles, pyFilePath)) {
|
||||
/*
|
||||
printf("[%d] PyList_Append (%#x): %#x \n",
|
||||
dwPid,
|
||||
hHandle->HandleValue,
|
||||
GetLastError());
|
||||
*/
|
||||
error = TRUE;
|
||||
goto loop_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
// Cast our buffer into an UNICODE_STRING.
|
||||
objectName = *(PUNICODE_STRING)objectNameInfo;
|
||||
loop_cleanup:
|
||||
Py_XDECREF(pyFilePath);
|
||||
pyFilePath = NULL;
|
||||
|
||||
// Print the information!
|
||||
if (objectName.Length)
|
||||
{
|
||||
// The object has a name. Make sure it is a file otherwise
|
||||
// ignore it
|
||||
fileNameLength = objectName.Length / 2;
|
||||
if (wcscmp(objectTypeInfo->Name.Buffer, L"File") == 0) {
|
||||
// printf("%.*S\n", objectName.Length / 2, objectName.Buffer);
|
||||
fileFromWchar = PyUnicode_FromWideChar(objectName.Buffer,
|
||||
fileNameLength);
|
||||
if (fileFromWchar == NULL)
|
||||
goto error_py_fun;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
arg = Py_BuildValue("N",
|
||||
PyUnicode_AsUTF8String(fileFromWchar));
|
||||
#else
|
||||
arg = Py_BuildValue("N",
|
||||
PyUnicode_FromObject(fileFromWchar));
|
||||
#endif
|
||||
if (!arg)
|
||||
goto error_py_fun;
|
||||
Py_XDECREF(fileFromWchar);
|
||||
fileFromWchar = NULL;
|
||||
if (PyList_Append(filesList, arg))
|
||||
goto error_py_fun;
|
||||
Py_XDECREF(arg);
|
||||
}
|
||||
/*
|
||||
printf(
|
||||
"[%#x] %.*S: %.*S\n",
|
||||
handle.Handle,
|
||||
objectTypeInfo->Name.Length / 2,
|
||||
objectTypeInfo->Name.Buffer,
|
||||
objectName.Length / 2,
|
||||
objectName.Buffer
|
||||
);
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
// Print something else.
|
||||
/*
|
||||
printf(
|
||||
"[%#x] %.*S: (unnamed)\n",
|
||||
handle.Handle,
|
||||
objectTypeInfo->Name.Length / 2,
|
||||
objectTypeInfo->Name.Buffer
|
||||
);
|
||||
*/
|
||||
;;
|
||||
}
|
||||
free(objectTypeInfo);
|
||||
free(objectNameInfo);
|
||||
CloseHandle(dupHandle);
|
||||
if (g_pNameBuffer != NULL)
|
||||
HeapFree(GetProcessHeap(), 0, g_pNameBuffer);
|
||||
g_pNameBuffer = NULL;
|
||||
g_dwSize = 0;
|
||||
g_dwLength = 0;
|
||||
|
||||
if (g_hFile != NULL)
|
||||
CloseHandle(g_hFile);
|
||||
g_hFile = NULL;
|
||||
}
|
||||
free(handleInfo);
|
||||
CloseHandle(processHandle);
|
||||
return filesList;
|
||||
|
||||
error_py_fun:
|
||||
Py_XDECREF(arg);
|
||||
Py_XDECREF(fileFromWchar);
|
||||
Py_DECREF(filesList);
|
||||
return NULL;
|
||||
cleanup:
|
||||
if (g_pNameBuffer != NULL)
|
||||
HeapFree(GetProcessHeap(), 0, g_pNameBuffer);
|
||||
g_pNameBuffer = NULL;
|
||||
g_dwSize = 0;
|
||||
g_dwLength = 0;
|
||||
|
||||
if (g_hFile != NULL)
|
||||
CloseHandle(g_hFile);
|
||||
g_hFile = NULL;
|
||||
|
||||
if (pHandleInfo != NULL)
|
||||
HeapFree(GetProcessHeap(), 0, pHandleInfo);
|
||||
pHandleInfo = NULL;
|
||||
|
||||
if (error) {
|
||||
Py_XDECREF(pyListFiles);
|
||||
pyListFiles = NULL;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&g_cs);
|
||||
|
||||
return pyListFiles;
|
||||
}
|
||||
|
||||
DWORD
|
||||
psutil_NtQueryObject()
|
||||
{
|
||||
DWORD dwWait = 0;
|
||||
|
||||
if (g_hThread == NULL)
|
||||
g_hThread = CreateThread(NULL,
|
||||
0,
|
||||
(LPTHREAD_START_ROUTINE)psutil_NtQueryObjectThread,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
if (g_hThread == NULL)
|
||||
return GetLastError();
|
||||
|
||||
// Signal the worker thread to start
|
||||
SetEvent(g_hEvtStart);
|
||||
|
||||
// Wait for the worker thread to finish
|
||||
dwWait = WaitForSingleObject(g_hEvtFinish, NTQO_TIMEOUT);
|
||||
|
||||
// If the thread hangs, kill it and cleanup
|
||||
if (dwWait == WAIT_TIMEOUT) {
|
||||
SuspendThread(g_hThread);
|
||||
TerminateThread(g_hThread, 1);
|
||||
WaitForSingleObject(g_hThread, INFINITE);
|
||||
CloseHandle(g_hThread);
|
||||
|
||||
// Cleanup Fiber
|
||||
if (g_fiber != NULL)
|
||||
DeleteFiber(g_fiber);
|
||||
g_fiber = NULL;
|
||||
|
||||
g_hThread = NULL;
|
||||
}
|
||||
|
||||
return dwWait;
|
||||
}
|
||||
|
||||
void
|
||||
psutil_NtQueryObjectThread()
|
||||
{
|
||||
// Prevent the thread stack from leaking when this
|
||||
// thread gets terminated due to NTQueryObject hanging
|
||||
g_fiber = ConvertThreadToFiber(NULL);
|
||||
|
||||
// Loop infinitely waiting for work
|
||||
while (TRUE) {
|
||||
WaitForSingleObject(g_hEvtStart, INFINITE);
|
||||
|
||||
g_status = __NtQueryObject(g_hFile,
|
||||
ObjectNameInformation,
|
||||
g_pNameBuffer,
|
||||
g_dwSize,
|
||||
&g_dwLength);
|
||||
SetEvent(g_hEvtFinish);
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *
|
||||
psutil_get_open_files_getmappedfilename(long dwPid, HANDLE hProcess)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PSYSTEM_HANDLE_INFORMATION_EX pHandleInfo = NULL;
|
||||
DWORD dwInfoSize = 0x10000;
|
||||
DWORD dwRet = 0;
|
||||
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX hHandle = NULL;
|
||||
HANDLE hFile = NULL;
|
||||
HANDLE hMap = NULL;
|
||||
DWORD i = 0;
|
||||
BOOLEAN error = FALSE;
|
||||
PyObject* pyListFiles = NULL;
|
||||
PyObject* pyFilePath = NULL;
|
||||
ULONG dwSize = 0;
|
||||
LPVOID pMem = NULL;
|
||||
TCHAR pszFilename[MAX_PATH+1];
|
||||
|
||||
if (g_initialized == FALSE)
|
||||
psutil_get_open_files_init(FALSE);
|
||||
|
||||
if (__NtQuerySystemInformation == NULL || __NtQueryObject == NULL) {
|
||||
PyErr_SetFromWindowsErr(0);
|
||||
error = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Py_BuildValue raises an exception if NULL is returned
|
||||
pyListFiles = PyList_New(0);
|
||||
if (pyListFiles == NULL) {
|
||||
error = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
do {
|
||||
if (pHandleInfo != NULL) {
|
||||
HeapFree(GetProcessHeap(), 0, pHandleInfo);
|
||||
pHandleInfo = NULL;
|
||||
}
|
||||
|
||||
// NtQuerySystemInformation won't give us the correct buffer size,
|
||||
// so we guess by doubling the buffer size.
|
||||
dwInfoSize *= 2;
|
||||
pHandleInfo = HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
dwInfoSize);
|
||||
|
||||
if (pHandleInfo == NULL) {
|
||||
PyErr_NoMemory();
|
||||
error = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
} while ((status = __NtQuerySystemInformation(
|
||||
SystemExtendedHandleInformation,
|
||||
pHandleInfo,
|
||||
dwInfoSize,
|
||||
&dwRet)) == STATUS_INFO_LENGTH_MISMATCH);
|
||||
|
||||
// NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH
|
||||
if (!NT_SUCCESS(status)) {
|
||||
PyErr_SetFromWindowsErr(HRESULT_FROM_NT(status));
|
||||
error = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (i = 0; i < pHandleInfo->NumberOfHandles; i++) {
|
||||
hHandle = &pHandleInfo->Handles[i];
|
||||
|
||||
// Check if this hHandle belongs to the PID the user specified.
|
||||
if (hHandle->UniqueProcessId != (HANDLE)dwPid ||
|
||||
hHandle->ObjectTypeIndex != HANDLE_TYPE_FILE)
|
||||
goto loop_cleanup;
|
||||
|
||||
if (!DuplicateHandle(hProcess,
|
||||
hHandle->HandleValue,
|
||||
GetCurrentProcess(),
|
||||
&hFile,
|
||||
0,
|
||||
TRUE,
|
||||
DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
/*
|
||||
printf("[%d] DuplicateHandle (%#x): %#x \n",
|
||||
dwPid,
|
||||
hHandle->HandleValue,
|
||||
GetLastError());
|
||||
*/
|
||||
goto loop_cleanup;
|
||||
}
|
||||
|
||||
hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (hMap == NULL) {
|
||||
/*
|
||||
printf("[%d] CreateFileMapping (%#x): %#x \n",
|
||||
dwPid,
|
||||
hHandle->HandleValue,
|
||||
GetLastError());
|
||||
*/
|
||||
goto loop_cleanup;
|
||||
}
|
||||
|
||||
pMem = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 1);
|
||||
|
||||
if (pMem == NULL) {
|
||||
/*
|
||||
printf("[%d] MapViewOfFile (%#x): %#x \n",
|
||||
dwPid,
|
||||
hHandle->HandleValue,
|
||||
GetLastError());
|
||||
*/
|
||||
goto loop_cleanup;
|
||||
}
|
||||
|
||||
dwSize = GetMappedFileName(GetCurrentProcess(), pMem, pszFilename, MAX_PATH);
|
||||
if (dwSize == 0) {
|
||||
/*
|
||||
printf("[%d] GetMappedFileName (%#x): %#x \n",
|
||||
dwPid,
|
||||
hHandle->HandleValue,
|
||||
GetLastError());
|
||||
*/
|
||||
goto loop_cleanup;
|
||||
}
|
||||
|
||||
pszFilename[dwSize] = '\0';
|
||||
/*
|
||||
printf("[%d] Filename (%#x) %#d bytes: %S\n",
|
||||
dwPid,
|
||||
hHandle->HandleValue,
|
||||
dwSize,
|
||||
pszFilename);
|
||||
*/
|
||||
|
||||
pyFilePath = PyUnicode_FromWideChar(pszFilename, dwSize);
|
||||
if (pyFilePath == NULL) {
|
||||
/*
|
||||
printf("[%d] PyUnicode_FromStringAndSize (%#x): %#x \n",
|
||||
dwPid,
|
||||
hHandle->HandleValue,
|
||||
GetLastError());
|
||||
*/
|
||||
error = TRUE;
|
||||
goto loop_cleanup;
|
||||
}
|
||||
|
||||
if (PyList_Append(pyListFiles, pyFilePath)) {
|
||||
/*
|
||||
printf("[%d] PyList_Append (%#x): %#x \n",
|
||||
dwPid,
|
||||
hHandle->HandleValue,
|
||||
GetLastError());
|
||||
*/
|
||||
error = TRUE;
|
||||
goto loop_cleanup;
|
||||
}
|
||||
|
||||
loop_cleanup:
|
||||
Py_XDECREF(pyFilePath);
|
||||
pyFilePath = NULL;
|
||||
|
||||
if (pMem != NULL)
|
||||
UnmapViewOfFile(pMem);
|
||||
pMem = NULL;
|
||||
|
||||
if (hMap != NULL)
|
||||
CloseHandle(hMap);
|
||||
hMap = NULL;
|
||||
|
||||
if (hFile != NULL)
|
||||
CloseHandle(hFile);
|
||||
hFile = NULL;
|
||||
|
||||
dwSize = 0;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (pMem != NULL)
|
||||
UnmapViewOfFile(pMem);
|
||||
pMem = NULL;
|
||||
|
||||
if (hMap != NULL)
|
||||
CloseHandle(hMap);
|
||||
hMap = NULL;
|
||||
|
||||
if (hFile != NULL)
|
||||
CloseHandle(hFile);
|
||||
hFile = NULL;
|
||||
|
||||
if (pHandleInfo != NULL)
|
||||
HeapFree(GetProcessHeap(), 0, pHandleInfo);
|
||||
pHandleInfo = NULL;
|
||||
|
||||
if (error) {
|
||||
Py_XDECREF(pyListFiles);
|
||||
pyListFiles = NULL;
|
||||
}
|
||||
|
||||
return pyListFiles;
|
||||
}
|
||||
|
@ -4,7 +4,110 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
#include <windows.h>
|
||||
#ifndef __PROCESS_HANDLES_H__
|
||||
#define __PROCESS_HANDLES_H__
|
||||
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif
|
||||
|
||||
#include <Python.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <strsafe.h>
|
||||
#include <winternl.h>
|
||||
#include <psapi.h>
|
||||
|
||||
|
||||
#ifndef NT_SUCCESS
|
||||
#define NT_SUCCESS(x) ((x) >= 0)
|
||||
#endif
|
||||
|
||||
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
|
||||
#define ObjectBasicInformation 0
|
||||
#define ObjectNameInformation 1
|
||||
#define ObjectTypeInformation 2
|
||||
#define HANDLE_TYPE_FILE 28
|
||||
#define NTQO_TIMEOUT 100
|
||||
|
||||
typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
|
||||
ULONG SystemInformationClass,
|
||||
PVOID SystemInformation,
|
||||
ULONG SystemInformationLength,
|
||||
PULONG ReturnLength
|
||||
);
|
||||
|
||||
typedef NTSTATUS (NTAPI *_NtQueryObject)(
|
||||
HANDLE ObjectHandle,
|
||||
ULONG ObjectInformationClass,
|
||||
PVOID ObjectInformation,
|
||||
ULONG ObjectInformationLength,
|
||||
PULONG ReturnLength
|
||||
);
|
||||
|
||||
// Undocumented FILE_INFORMATION_CLASS: FileNameInformation
|
||||
static const SYSTEM_INFORMATION_CLASS SystemExtendedHandleInformation = (SYSTEM_INFORMATION_CLASS)64;
|
||||
|
||||
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
|
||||
{
|
||||
PVOID Object;
|
||||
HANDLE UniqueProcessId;
|
||||
HANDLE HandleValue;
|
||||
ULONG GrantedAccess;
|
||||
USHORT CreatorBackTraceIndex;
|
||||
USHORT ObjectTypeIndex;
|
||||
ULONG HandleAttributes;
|
||||
ULONG Reserved;
|
||||
} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX;
|
||||
|
||||
typedef struct _SYSTEM_HANDLE_INFORMATION_EX
|
||||
{
|
||||
ULONG_PTR NumberOfHandles;
|
||||
ULONG_PTR Reserved;
|
||||
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1];
|
||||
} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
|
||||
|
||||
typedef enum _POOL_TYPE {
|
||||
NonPagedPool,
|
||||
PagedPool,
|
||||
NonPagedPoolMustSucceed,
|
||||
DontUseThisType,
|
||||
NonPagedPoolCacheAligned,
|
||||
PagedPoolCacheAligned,
|
||||
NonPagedPoolCacheAlignedMustS
|
||||
} POOL_TYPE, *PPOOL_TYPE;
|
||||
|
||||
typedef struct _OBJECT_TYPE_INFORMATION {
|
||||
UNICODE_STRING Name;
|
||||
ULONG TotalNumberOfObjects;
|
||||
ULONG TotalNumberOfHandles;
|
||||
ULONG TotalPagedPoolUsage;
|
||||
ULONG TotalNonPagedPoolUsage;
|
||||
ULONG TotalNamePoolUsage;
|
||||
ULONG TotalHandleTableUsage;
|
||||
ULONG HighWaterNumberOfObjects;
|
||||
ULONG HighWaterNumberOfHandles;
|
||||
ULONG HighWaterPagedPoolUsage;
|
||||
ULONG HighWaterNonPagedPoolUsage;
|
||||
ULONG HighWaterNamePoolUsage;
|
||||
ULONG HighWaterHandleTableUsage;
|
||||
ULONG InvalidAttributes;
|
||||
GENERIC_MAPPING GenericMapping;
|
||||
ULONG ValidAccess;
|
||||
BOOLEAN SecurityRequired;
|
||||
BOOLEAN MaintainHandleCount;
|
||||
USHORT MaintainTypeList;
|
||||
POOL_TYPE PoolType;
|
||||
ULONG PagedPoolUsage;
|
||||
ULONG NonPagedPoolUsage;
|
||||
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
|
||||
|
||||
PVOID GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName);
|
||||
VOID psutil_get_open_files_init(BOOL threaded);
|
||||
PyObject* psutil_get_open_files(long pid, HANDLE processHandle);
|
||||
PyObject* psutil_get_open_files_ntqueryobject(long dwPid, HANDLE hProcess);
|
||||
PyObject* psutil_get_open_files_getmappedfilename(long dwPid, HANDLE hProcess);
|
||||
DWORD psutil_NtQueryObject(void);
|
||||
void psutil_NtQueryObjectThread(void);
|
||||
|
||||
#endif // __PROCESS_HANDLES_H__
|
||||
|
@ -38,12 +38,10 @@ psutil_handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess)
|
||||
|
||||
hProcess = OpenProcess(dwDesiredAccess, FALSE, pid);
|
||||
if (hProcess == NULL) {
|
||||
if (GetLastError() == ERROR_INVALID_PARAMETER) {
|
||||
if (GetLastError() == ERROR_INVALID_PARAMETER)
|
||||
NoSuchProcess();
|
||||
}
|
||||
else {
|
||||
else
|
||||
PyErr_SetFromWindowsErr(0);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -129,13 +127,10 @@ psutil_pid_is_running(DWORD pid)
|
||||
DWORD exitCode;
|
||||
|
||||
// Special case for PID 0 System Idle Process
|
||||
if (pid == 0) {
|
||||
if (pid == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pid < 0) {
|
||||
if (pid < 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
|
||||
FALSE, pid);
|
||||
@ -183,10 +178,8 @@ psutil_pid_in_proclist(DWORD pid)
|
||||
DWORD i;
|
||||
|
||||
proclist = psutil_get_pids(&numberOfReturnedPIDs);
|
||||
if (NULL == proclist) {
|
||||
if (proclist == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < numberOfReturnedPIDs; i++) {
|
||||
if (pid == proclist[i]) {
|
||||
free(proclist);
|
||||
@ -205,13 +198,12 @@ int
|
||||
handlep_is_running(HANDLE hProcess)
|
||||
{
|
||||
DWORD dwCode;
|
||||
if (NULL == hProcess) {
|
||||
|
||||
if (NULL == hProcess)
|
||||
return 0;
|
||||
}
|
||||
if (GetExitCodeProcess(hProcess, &dwCode)) {
|
||||
if (dwCode == STILL_ACTIVE) {
|
||||
if (dwCode == STILL_ACTIVE)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -236,10 +228,8 @@ psutil_get_arg_list(long pid)
|
||||
PyObject *argList = NULL;
|
||||
|
||||
hProcess = psutil_handle_from_pid(pid);
|
||||
if (hProcess == NULL) {
|
||||
if (hProcess == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pebAddress = psutil_get_peb_address(hProcess);
|
||||
|
||||
// get the address of ProcessParameters
|
||||
@ -367,7 +357,10 @@ const int STATUS_BUFFER_TOO_SMALL = 0xC0000023L;
|
||||
|
||||
/*
|
||||
* Given a process PID and a PSYSTEM_PROCESS_INFORMATION structure
|
||||
* fills the structure with process information.
|
||||
* fills the structure with various process information by using
|
||||
* NtQuerySystemInformation.
|
||||
* We use this as a fallback when faster functions fail with access
|
||||
* denied. This is slower because it iterates over all processes.
|
||||
* On success return 1, else 0 with Python exception already set.
|
||||
*/
|
||||
int
|
||||
@ -419,9 +412,8 @@ psutil_get_proc_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess,
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (bufferSize <= 0x20000) {
|
||||
if (bufferSize <= 0x20000)
|
||||
initialBufferSize = bufferSize;
|
||||
}
|
||||
|
||||
process = PH_FIRST_PROCESS(buffer);
|
||||
do {
|
||||
|
@ -4,8 +4,13 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#if !defined(__PROCESS_INFO_H)
|
||||
#define __PROCESS_INFO_H
|
||||
|
||||
#include <Python.h>
|
||||
#include <windows.h>
|
||||
#include "security.h"
|
||||
#include "ntextapi.h"
|
||||
|
||||
DWORD* psutil_get_pids(DWORD *numberOfReturnedPIDs);
|
||||
HANDLE psutil_handle_from_pid(DWORD pid);
|
||||
@ -15,3 +20,7 @@ int psutil_pid_in_proclist(DWORD pid);
|
||||
int psutil_pid_is_running(DWORD pid);
|
||||
PVOID psutil_get_peb_address(HANDLE ProcessHandle);
|
||||
PyObject* psutil_get_arg_list(long pid);
|
||||
int psutil_get_proc_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess,
|
||||
PVOID *retBuffer);
|
||||
|
||||
#endif
|
||||
|
@ -18,9 +18,8 @@ HANDLE
|
||||
psutil_token_from_handle(HANDLE hProcess) {
|
||||
HANDLE hToken = NULL;
|
||||
|
||||
if (! OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) {
|
||||
if (! OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
|
||||
return PyErr_SetFromWindowsErr(0);
|
||||
}
|
||||
return hToken;
|
||||
}
|
||||
|
||||
@ -50,10 +49,8 @@ psutil_has_system_privilege(HANDLE hProcess) {
|
||||
TOKEN_PRIVILEGES *tp = NULL;
|
||||
HANDLE hToken = psutil_token_from_handle(hProcess);
|
||||
|
||||
if (NULL == hToken) {
|
||||
if (NULL == hToken)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// call GetTokenInformation first to get the buffer size
|
||||
if (! GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwSize)) {
|
||||
dwRetval = GetLastError();
|
||||
@ -140,14 +137,11 @@ psutil_set_privilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege)
|
||||
tpPrevious.PrivilegeCount = 1;
|
||||
tpPrevious.Privileges[0].Luid = luid;
|
||||
|
||||
if (bEnablePrivilege) {
|
||||
if (bEnablePrivilege)
|
||||
tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
|
||||
}
|
||||
|
||||
else {
|
||||
else
|
||||
tpPrevious.Privileges[0].Attributes ^=
|
||||
(SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes);
|
||||
}
|
||||
|
||||
AdjustTokenPrivileges(
|
||||
hToken,
|
||||
@ -213,15 +207,12 @@ psutil_unset_se_debug()
|
||||
&hToken)
|
||||
) {
|
||||
if (GetLastError() == ERROR_NO_TOKEN) {
|
||||
if (! ImpersonateSelf(SecurityImpersonation)) {
|
||||
if (! ImpersonateSelf(SecurityImpersonation))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!OpenThreadToken(GetCurrentThread(),
|
||||
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
||||
FALSE,
|
||||
&hToken)
|
||||
)
|
||||
&hToken))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -229,9 +220,8 @@ psutil_unset_se_debug()
|
||||
}
|
||||
|
||||
// now disable SeDebug
|
||||
if (! psutil_set_privilege(hToken, SE_DEBUG_NAME, FALSE)) {
|
||||
if (! psutil_set_privilege(hToken, SE_DEBUG_NAME, FALSE))
|
||||
return 0;
|
||||
}
|
||||
|
||||
CloseHandle(hToken);
|
||||
return 1;
|
||||
|
@ -22,8 +22,7 @@ HERE = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
def get_version():
|
||||
INIT = os.path.join(HERE, 'psutil/__init__.py')
|
||||
f = open(INIT, 'r')
|
||||
try:
|
||||
with open(INIT, 'r') as f:
|
||||
for line in f:
|
||||
if line.startswith('__version__'):
|
||||
ret = eval(line.strip().split(' = ')[1])
|
||||
@ -33,24 +32,28 @@ def get_version():
|
||||
return ret
|
||||
else:
|
||||
raise ValueError("couldn't find version string")
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
|
||||
def get_description():
|
||||
README = os.path.join(HERE, 'README.rst')
|
||||
f = open(README, 'r')
|
||||
try:
|
||||
with open(README, 'r') as f:
|
||||
return f.read()
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
|
||||
VERSION = get_version()
|
||||
VERSION_MACRO = ('PSUTIL_VERSION', int(VERSION.replace('.', '')))
|
||||
|
||||
|
||||
# POSIX
|
||||
if os.name == 'posix':
|
||||
libraries = []
|
||||
if sys.platform.startswith("sunos"):
|
||||
libraries.append('socket')
|
||||
|
||||
posix_extension = Extension(
|
||||
'_psutil_posix',
|
||||
'psutil._psutil_posix',
|
||||
sources=['psutil/_psutil_posix.c'],
|
||||
libraries=libraries,
|
||||
)
|
||||
# Windows
|
||||
if sys.platform.startswith("win32"):
|
||||
@ -60,25 +63,28 @@ if sys.platform.startswith("win32"):
|
||||
return '0x0%s' % ((maj * 100) + min)
|
||||
|
||||
extensions = [Extension(
|
||||
'_psutil_windows',
|
||||
'psutil._psutil_windows',
|
||||
sources=[
|
||||
'psutil/_psutil_windows.c',
|
||||
'psutil/_psutil_common.c',
|
||||
'psutil/arch/windows/process_info.c',
|
||||
'psutil/arch/windows/process_handles.c',
|
||||
'psutil/arch/windows/security.c',
|
||||
'psutil/arch/windows/inet_ntop.c',
|
||||
],
|
||||
define_macros=[
|
||||
VERSION_MACRO,
|
||||
# be nice to mingw, see:
|
||||
# http://www.mingw.org/wiki/Use_more_recent_defined_functions
|
||||
('_WIN32_WINNT', get_winver()),
|
||||
('_AVAIL_WINVER_', get_winver()),
|
||||
('_CRT_SECURE_NO_WARNINGS', None),
|
||||
# see: https://github.com/giampaolo/psutil/issues/348
|
||||
('PSAPI_VERSION', 1),
|
||||
],
|
||||
libraries=[
|
||||
"psapi", "kernel32", "advapi32", "shell32", "netapi32", "iphlpapi",
|
||||
"wtsapi32",
|
||||
"wtsapi32", "ws2_32",
|
||||
],
|
||||
# extra_compile_args=["/Z7"],
|
||||
# extra_link_args=["/DEBUG"]
|
||||
@ -86,12 +92,13 @@ if sys.platform.startswith("win32"):
|
||||
# OS X
|
||||
elif sys.platform.startswith("darwin"):
|
||||
extensions = [Extension(
|
||||
'_psutil_osx',
|
||||
'psutil._psutil_osx',
|
||||
sources=[
|
||||
'psutil/_psutil_osx.c',
|
||||
'psutil/_psutil_common.c',
|
||||
'psutil/arch/osx/process_info.c'
|
||||
],
|
||||
define_macros=[VERSION_MACRO],
|
||||
extra_link_args=[
|
||||
'-framework', 'CoreFoundation', '-framework', 'IOKit'
|
||||
],
|
||||
@ -101,28 +108,31 @@ elif sys.platform.startswith("darwin"):
|
||||
# FreeBSD
|
||||
elif sys.platform.startswith("freebsd"):
|
||||
extensions = [Extension(
|
||||
'_psutil_bsd',
|
||||
'psutil._psutil_bsd',
|
||||
sources=[
|
||||
'psutil/_psutil_bsd.c',
|
||||
'psutil/_psutil_common.c',
|
||||
'psutil/arch/bsd/process_info.c'
|
||||
],
|
||||
define_macros=[VERSION_MACRO],
|
||||
libraries=["devstat"]),
|
||||
posix_extension,
|
||||
]
|
||||
# Linux
|
||||
elif sys.platform.startswith("linux"):
|
||||
extensions = [Extension(
|
||||
'_psutil_linux',
|
||||
sources=['psutil/_psutil_linux.c']),
|
||||
'psutil._psutil_linux',
|
||||
sources=['psutil/_psutil_linux.c'],
|
||||
define_macros=[VERSION_MACRO]),
|
||||
posix_extension,
|
||||
]
|
||||
# Solaris
|
||||
elif sys.platform.lower().startswith('sunos'):
|
||||
extensions = [Extension(
|
||||
'_psutil_sunos',
|
||||
'psutil._psutil_sunos',
|
||||
sources=['psutil/_psutil_sunos.c'],
|
||||
libraries=['kstat', 'nsl'],),
|
||||
define_macros=[VERSION_MACRO],
|
||||
libraries=['kstat', 'nsl', 'socket']),
|
||||
posix_extension,
|
||||
]
|
||||
else:
|
||||
@ -132,14 +142,14 @@ else:
|
||||
def main():
|
||||
setup_args = dict(
|
||||
name='psutil',
|
||||
version=get_version(),
|
||||
version=VERSION,
|
||||
description=__doc__.replace('\n', '').strip(),
|
||||
long_description=get_description(),
|
||||
keywords=[
|
||||
'ps', 'top', 'kill', 'free', 'lsof', 'netstat', 'nice',
|
||||
'tty', 'ionice', 'uptime', 'taskmgr', 'process', 'df',
|
||||
'iotop', 'iostat', 'ifconfig', 'taskset', 'who', 'pidof',
|
||||
'pmap', 'smem', 'monitoring', 'ulimit', 'prlimit',
|
||||
'ps', 'top', 'kill', 'free', 'lsof', 'netstat', 'nice', 'tty',
|
||||
'ionice', 'uptime', 'taskmgr', 'process', 'df', 'iotop', 'iostat',
|
||||
'ifconfig', 'taskset', 'who', 'pidof', 'pmap', 'smem', 'pstree',
|
||||
'monitoring', 'ulimit', 'prlimit',
|
||||
],
|
||||
author='Giampaolo Rodola',
|
||||
author_email='g.rodola <at> gmail <dot> com',
|
||||
@ -166,8 +176,6 @@ def main():
|
||||
'Operating System :: POSIX',
|
||||
'Programming Language :: C',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.4',
|
||||
'Programming Language :: Python :: 2.5',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
|
@ -1,15 +0,0 @@
|
||||
- The recommended way to run tests (also on Windows) is to cd into parent
|
||||
directory and run:
|
||||
|
||||
make test
|
||||
|
||||
- If you're on Python < 2.7 unittest2 module must be installed first:
|
||||
https://pypi.python.org/pypi/unittest2
|
||||
|
||||
- The main test script is test_psutil.py, which also imports platform-specific
|
||||
_*.py scripts (which should be ignored).
|
||||
|
||||
- test_memory_leaks.py looks for memory leaks into C extension modules and must
|
||||
be run separately with:
|
||||
|
||||
make memtest
|
21
python/psutil/test/README.rst
Normal file
21
python/psutil/test/README.rst
Normal file
@ -0,0 +1,21 @@
|
||||
- The recommended way to run tests (also on Windows) is to cd into parent
|
||||
directory and run ``make test``
|
||||
|
||||
- Dependencies for running tests:
|
||||
- python 2.6: ipaddress, mock, unittest2
|
||||
- python 2.7: ipaddress, mock
|
||||
- python 3.2: ipaddress, mock
|
||||
- python 3.3: ipaddress
|
||||
- python >= 3.4: no deps required
|
||||
|
||||
- The main test script is ``test_psutil.py``, which also imports platform-specific
|
||||
``_*.py`` scripts (which should be ignored).
|
||||
|
||||
- ``test_memory_leaks.py`` looks for memory leaks into C extension modules and must
|
||||
be run separately with ``make test-memleaks``.
|
||||
|
||||
- To run tests on all supported Python version install tox (pip install tox)
|
||||
then run ``tox``.
|
||||
|
||||
- Every time a commit is pushed tests are automatically run on Travis:
|
||||
https://travis-ci.org/giampaolo/psutil/
|
@ -8,15 +8,15 @@
|
||||
|
||||
"""BSD specific tests. These are implicitly run by test_psutil.py."""
|
||||
|
||||
import subprocess
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
import psutil
|
||||
|
||||
from psutil._compat import PY3
|
||||
from test_psutil import (TOLERANCE, sh, get_test_subprocess, which,
|
||||
from test_psutil import (TOLERANCE, BSD, sh, get_test_subprocess, which,
|
||||
retry_before_failing, reap_children, unittest)
|
||||
|
||||
|
||||
@ -50,6 +50,7 @@ def muse(field):
|
||||
return int(line.split()[1])
|
||||
|
||||
|
||||
@unittest.skipUnless(BSD, "not a BSD system")
|
||||
class BSDSpecificTestCase(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
@ -106,6 +107,7 @@ class BSDSpecificTestCase(unittest.TestCase):
|
||||
if abs(usage.used - used) > 10 * 1024 * 1024:
|
||||
self.fail("psutil=%s, df=%s" % (usage.used, used))
|
||||
|
||||
@retry_before_failing()
|
||||
def test_memory_maps(self):
|
||||
out = sh('procstat -v %s' % self.pid)
|
||||
maps = psutil.Process(self.pid).memory_maps(grouped=False)
|
||||
@ -120,6 +122,29 @@ class BSDSpecificTestCase(unittest.TestCase):
|
||||
if not map.path.startswith('['):
|
||||
self.assertEqual(fields[10], map.path)
|
||||
|
||||
def test_exe(self):
|
||||
out = sh('procstat -b %s' % self.pid)
|
||||
self.assertEqual(psutil.Process(self.pid).exe(),
|
||||
out.split('\n')[1].split()[-1])
|
||||
|
||||
def test_cmdline(self):
|
||||
out = sh('procstat -c %s' % self.pid)
|
||||
self.assertEqual(' '.join(psutil.Process(self.pid).cmdline()),
|
||||
' '.join(out.split('\n')[1].split()[2:]))
|
||||
|
||||
def test_uids_gids(self):
|
||||
out = sh('procstat -s %s' % self.pid)
|
||||
euid, ruid, suid, egid, rgid, sgid = out.split('\n')[1].split()[2:8]
|
||||
p = psutil.Process(self.pid)
|
||||
uids = p.uids()
|
||||
gids = p.gids()
|
||||
self.assertEqual(uids.real, int(ruid))
|
||||
self.assertEqual(uids.effective, int(euid))
|
||||
self.assertEqual(uids.saved, int(suid))
|
||||
self.assertEqual(gids.real, int(rgid))
|
||||
self.assertEqual(gids.effective, int(egid))
|
||||
self.assertEqual(gids.saved, int(sgid))
|
||||
|
||||
# --- virtual_memory(); tests against sysctl
|
||||
|
||||
def test_vmem_total(self):
|
||||
@ -162,6 +187,10 @@ class BSDSpecificTestCase(unittest.TestCase):
|
||||
self.assertAlmostEqual(psutil.virtual_memory().buffers, syst,
|
||||
delta=TOLERANCE)
|
||||
|
||||
def test_cpu_count_logical(self):
|
||||
syst = sysctl("hw.ncpu")
|
||||
self.assertEqual(psutil.cpu_count(logical=True), syst)
|
||||
|
||||
# --- virtual_memory(); tests against muse
|
||||
|
||||
@unittest.skipUnless(MUSE_AVAILABLE, "muse cmdline tool is not available")
|
||||
@ -212,12 +241,12 @@ class BSDSpecificTestCase(unittest.TestCase):
|
||||
delta=TOLERANCE)
|
||||
|
||||
|
||||
def test_main():
|
||||
def main():
|
||||
test_suite = unittest.TestSuite()
|
||||
test_suite.addTest(unittest.makeSuite(BSDSpecificTestCase))
|
||||
result = unittest.TextTestRunner(verbosity=2).run(test_suite)
|
||||
return result.wasSuccessful()
|
||||
|
||||
if __name__ == '__main__':
|
||||
if not test_main():
|
||||
if not main():
|
||||
sys.exit(1)
|
||||
|
@ -7,18 +7,70 @@
|
||||
"""Linux specific tests. These are implicitly run by test_psutil.py."""
|
||||
|
||||
from __future__ import division
|
||||
import contextlib
|
||||
import errno
|
||||
import fcntl
|
||||
import io
|
||||
import os
|
||||
import pprint
|
||||
import re
|
||||
import socket
|
||||
import struct
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import warnings
|
||||
|
||||
from test_psutil import POSIX, TOLERANCE, TRAVIS
|
||||
try:
|
||||
from unittest import mock # py3
|
||||
except ImportError:
|
||||
import mock # requires "pip install mock"
|
||||
|
||||
from test_psutil import POSIX, TOLERANCE, TRAVIS, LINUX
|
||||
from test_psutil import (skip_on_not_implemented, sh, get_test_subprocess,
|
||||
retry_before_failing, get_kernel_version, unittest)
|
||||
retry_before_failing, get_kernel_version, unittest,
|
||||
which, call_until)
|
||||
|
||||
import psutil
|
||||
import psutil._pslinux
|
||||
from psutil._compat import PY3, u
|
||||
|
||||
|
||||
SIOCGIFADDR = 0x8915
|
||||
SIOCGIFCONF = 0x8912
|
||||
SIOCGIFHWADDR = 0x8927
|
||||
|
||||
|
||||
def get_ipv4_address(ifname):
|
||||
ifname = ifname[:15]
|
||||
if PY3:
|
||||
ifname = bytes(ifname, 'ascii')
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
with contextlib.closing(s):
|
||||
return socket.inet_ntoa(
|
||||
fcntl.ioctl(s.fileno(),
|
||||
SIOCGIFADDR,
|
||||
struct.pack('256s', ifname))[20:24])
|
||||
|
||||
|
||||
def get_mac_address(ifname):
|
||||
ifname = ifname[:15]
|
||||
if PY3:
|
||||
ifname = bytes(ifname, 'ascii')
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
with contextlib.closing(s):
|
||||
info = fcntl.ioctl(
|
||||
s.fileno(), SIOCGIFHWADDR, struct.pack('256s', ifname))
|
||||
if PY3:
|
||||
def ord(x):
|
||||
return x
|
||||
else:
|
||||
import __builtin__
|
||||
ord = __builtin__.ord
|
||||
return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1]
|
||||
|
||||
|
||||
@unittest.skipUnless(LINUX, "not a Linux system")
|
||||
class LinuxSpecificTestCase(unittest.TestCase):
|
||||
|
||||
@unittest.skipIf(
|
||||
@ -139,6 +191,241 @@ class LinuxSpecificTestCase(unittest.TestCase):
|
||||
else:
|
||||
self.assertNotIn('guest_nice', fields)
|
||||
|
||||
def test_net_if_addrs_ips(self):
|
||||
for name, addrs in psutil.net_if_addrs().items():
|
||||
for addr in addrs:
|
||||
if addr.family == psutil.AF_LINK:
|
||||
self.assertEqual(addr.address, get_mac_address(name))
|
||||
elif addr.family == socket.AF_INET:
|
||||
self.assertEqual(addr.address, get_ipv4_address(name))
|
||||
# TODO: test for AF_INET6 family
|
||||
|
||||
@unittest.skipUnless(which('ip'), "'ip' utility not available")
|
||||
@unittest.skipIf(TRAVIS, "skipped on Travis")
|
||||
def test_net_if_names(self):
|
||||
out = sh("ip addr").strip()
|
||||
nics = psutil.net_if_addrs()
|
||||
found = 0
|
||||
for line in out.split('\n'):
|
||||
line = line.strip()
|
||||
if re.search("^\d+:", line):
|
||||
found += 1
|
||||
name = line.split(':')[1].strip()
|
||||
self.assertIn(name, nics.keys())
|
||||
self.assertEqual(len(nics), found, msg="%s\n---\n%s" % (
|
||||
pprint.pformat(nics), out))
|
||||
|
||||
@unittest.skipUnless(which("nproc"), "nproc utility not available")
|
||||
def test_cpu_count_logical_w_nproc(self):
|
||||
num = int(sh("nproc --all"))
|
||||
self.assertEqual(psutil.cpu_count(logical=True), num)
|
||||
|
||||
@unittest.skipUnless(which("lscpu"), "lscpu utility not available")
|
||||
def test_cpu_count_logical_w_lscpu(self):
|
||||
out = sh("lscpu -p")
|
||||
num = len([x for x in out.split('\n') if not x.startswith('#')])
|
||||
self.assertEqual(psutil.cpu_count(logical=True), num)
|
||||
|
||||
# --- mocked tests
|
||||
|
||||
def test_virtual_memory_mocked_warnings(self):
|
||||
with mock.patch('psutil._pslinux.open', create=True) as m:
|
||||
with warnings.catch_warnings(record=True) as ws:
|
||||
warnings.simplefilter("always")
|
||||
ret = psutil._pslinux.virtual_memory()
|
||||
assert m.called
|
||||
self.assertEqual(len(ws), 1)
|
||||
w = ws[0]
|
||||
self.assertTrue(w.filename.endswith('psutil/_pslinux.py'))
|
||||
self.assertIn(
|
||||
"'cached', 'active' and 'inactive' memory stats couldn't "
|
||||
"be determined", str(w.message))
|
||||
self.assertEqual(ret.cached, 0)
|
||||
self.assertEqual(ret.active, 0)
|
||||
self.assertEqual(ret.inactive, 0)
|
||||
|
||||
def test_swap_memory_mocked_warnings(self):
|
||||
with mock.patch('psutil._pslinux.open', create=True) as m:
|
||||
with warnings.catch_warnings(record=True) as ws:
|
||||
warnings.simplefilter("always")
|
||||
ret = psutil._pslinux.swap_memory()
|
||||
assert m.called
|
||||
self.assertEqual(len(ws), 1)
|
||||
w = ws[0]
|
||||
self.assertTrue(w.filename.endswith('psutil/_pslinux.py'))
|
||||
self.assertIn(
|
||||
"'sin' and 'sout' swap memory stats couldn't "
|
||||
"be determined", str(w.message))
|
||||
self.assertEqual(ret.sin, 0)
|
||||
self.assertEqual(ret.sout, 0)
|
||||
|
||||
def test_cpu_count_logical_mocked(self):
|
||||
import psutil._pslinux
|
||||
original = psutil._pslinux.cpu_count_logical()
|
||||
# Here we want to mock os.sysconf("SC_NPROCESSORS_ONLN") in
|
||||
# order to cause the parsing of /proc/cpuinfo and /proc/stat.
|
||||
with mock.patch(
|
||||
'psutil._pslinux.os.sysconf', side_effect=ValueError) as m:
|
||||
self.assertEqual(psutil._pslinux.cpu_count_logical(), original)
|
||||
assert m.called
|
||||
|
||||
# Let's have open() return emtpy data and make sure None is
|
||||
# returned ('cause we mimick os.cpu_count()).
|
||||
with mock.patch('psutil._pslinux.open', create=True) as m:
|
||||
self.assertIsNone(psutil._pslinux.cpu_count_logical())
|
||||
self.assertEqual(m.call_count, 2)
|
||||
# /proc/stat should be the last one
|
||||
self.assertEqual(m.call_args[0][0], '/proc/stat')
|
||||
|
||||
# Let's push this a bit further and make sure /proc/cpuinfo
|
||||
# parsing works as expected.
|
||||
with open('/proc/cpuinfo', 'rb') as f:
|
||||
cpuinfo_data = f.read()
|
||||
fake_file = io.BytesIO(cpuinfo_data)
|
||||
with mock.patch('psutil._pslinux.open',
|
||||
return_value=fake_file, create=True) as m:
|
||||
self.assertEqual(psutil._pslinux.cpu_count_logical(), original)
|
||||
|
||||
def test_cpu_count_physical_mocked(self):
|
||||
# Have open() return emtpy data and make sure None is returned
|
||||
# ('cause we want to mimick os.cpu_count())
|
||||
with mock.patch('psutil._pslinux.open', create=True) as m:
|
||||
self.assertIsNone(psutil._pslinux.cpu_count_physical())
|
||||
assert m.called
|
||||
|
||||
def test_proc_open_files_file_gone(self):
|
||||
# simulates a file which gets deleted during open_files()
|
||||
# execution
|
||||
p = psutil.Process()
|
||||
files = p.open_files()
|
||||
with tempfile.NamedTemporaryFile():
|
||||
# give the kernel some time to see the new file
|
||||
call_until(p.open_files, "len(ret) != %i" % len(files))
|
||||
with mock.patch('psutil._pslinux.os.readlink',
|
||||
side_effect=OSError(errno.ENOENT, "")) as m:
|
||||
files = p.open_files()
|
||||
assert not files
|
||||
assert m.called
|
||||
# also simulate the case where os.readlink() returns EINVAL
|
||||
# in which case psutil is supposed to 'continue'
|
||||
with mock.patch('psutil._pslinux.os.readlink',
|
||||
side_effect=OSError(errno.EINVAL, "")) as m:
|
||||
self.assertEqual(p.open_files(), [])
|
||||
assert m.called
|
||||
|
||||
def test_proc_terminal_mocked(self):
|
||||
with mock.patch('psutil._pslinux._psposix._get_terminal_map',
|
||||
return_value={}) as m:
|
||||
self.assertIsNone(psutil._pslinux.Process(os.getpid()).terminal())
|
||||
assert m.called
|
||||
|
||||
def test_proc_num_ctx_switches_mocked(self):
|
||||
with mock.patch('psutil._pslinux.open', create=True) as m:
|
||||
self.assertRaises(
|
||||
NotImplementedError,
|
||||
psutil._pslinux.Process(os.getpid()).num_ctx_switches)
|
||||
assert m.called
|
||||
|
||||
def test_proc_num_threads_mocked(self):
|
||||
with mock.patch('psutil._pslinux.open', create=True) as m:
|
||||
self.assertRaises(
|
||||
NotImplementedError,
|
||||
psutil._pslinux.Process(os.getpid()).num_threads)
|
||||
assert m.called
|
||||
|
||||
def test_proc_ppid_mocked(self):
|
||||
with mock.patch('psutil._pslinux.open', create=True) as m:
|
||||
self.assertRaises(
|
||||
NotImplementedError,
|
||||
psutil._pslinux.Process(os.getpid()).ppid)
|
||||
assert m.called
|
||||
|
||||
def test_proc_uids_mocked(self):
|
||||
with mock.patch('psutil._pslinux.open', create=True) as m:
|
||||
self.assertRaises(
|
||||
NotImplementedError,
|
||||
psutil._pslinux.Process(os.getpid()).uids)
|
||||
assert m.called
|
||||
|
||||
def test_proc_gids_mocked(self):
|
||||
with mock.patch('psutil._pslinux.open', create=True) as m:
|
||||
self.assertRaises(
|
||||
NotImplementedError,
|
||||
psutil._pslinux.Process(os.getpid()).gids)
|
||||
assert m.called
|
||||
|
||||
def test_proc_cmdline_mocked(self):
|
||||
# see: https://github.com/giampaolo/psutil/issues/639
|
||||
p = psutil.Process()
|
||||
fake_file = io.StringIO(u('foo\x00bar\x00'))
|
||||
with mock.patch('psutil._pslinux.open',
|
||||
return_value=fake_file, create=True) as m:
|
||||
p.cmdline() == ['foo', 'bar']
|
||||
assert m.called
|
||||
fake_file = io.StringIO(u('foo\x00bar\x00\x00'))
|
||||
with mock.patch('psutil._pslinux.open',
|
||||
return_value=fake_file, create=True) as m:
|
||||
p.cmdline() == ['foo', 'bar', '']
|
||||
assert m.called
|
||||
|
||||
def test_proc_io_counters_mocked(self):
|
||||
with mock.patch('psutil._pslinux.open', create=True) as m:
|
||||
self.assertRaises(
|
||||
NotImplementedError,
|
||||
psutil._pslinux.Process(os.getpid()).io_counters)
|
||||
assert m.called
|
||||
|
||||
def test_boot_time_mocked(self):
|
||||
with mock.patch('psutil._pslinux.open', create=True) as m:
|
||||
self.assertRaises(
|
||||
RuntimeError,
|
||||
psutil._pslinux.boot_time)
|
||||
assert m.called
|
||||
|
||||
def test_users_mocked(self):
|
||||
# Make sure ':0' and ':0.0' (returned by C ext) are converted
|
||||
# to 'localhost'.
|
||||
with mock.patch('psutil._pslinux.cext.users',
|
||||
return_value=[('giampaolo', 'pts/2', ':0',
|
||||
1436573184.0, True)]) as m:
|
||||
self.assertEqual(psutil.users()[0].host, 'localhost')
|
||||
assert m.called
|
||||
with mock.patch('psutil._pslinux.cext.users',
|
||||
return_value=[('giampaolo', 'pts/2', ':0.0',
|
||||
1436573184.0, True)]) as m:
|
||||
self.assertEqual(psutil.users()[0].host, 'localhost')
|
||||
assert m.called
|
||||
# ...otherwise it should be returned as-is
|
||||
with mock.patch('psutil._pslinux.cext.users',
|
||||
return_value=[('giampaolo', 'pts/2', 'foo',
|
||||
1436573184.0, True)]) as m:
|
||||
self.assertEqual(psutil.users()[0].host, 'foo')
|
||||
assert m.called
|
||||
|
||||
def test_disk_partitions_mocked(self):
|
||||
# Test that ZFS partitions are returned.
|
||||
with open("/proc/filesystems", "r") as f:
|
||||
data = f.read()
|
||||
if 'zfs' in data:
|
||||
for part in psutil.disk_partitions():
|
||||
if part.fstype == 'zfs':
|
||||
break
|
||||
else:
|
||||
self.fail("couldn't find any ZFS partition")
|
||||
else:
|
||||
# No ZFS partitions on this system. Let's fake one.
|
||||
fake_file = io.StringIO(u("nodev\tzfs\n"))
|
||||
with mock.patch('psutil._pslinux.open',
|
||||
return_value=fake_file, create=True) as m1:
|
||||
with mock.patch(
|
||||
'psutil._pslinux.cext.disk_partitions',
|
||||
return_value=[('/dev/sdb3', '/', 'zfs', 'rw')]) as m2:
|
||||
ret = psutil.disk_partitions()
|
||||
assert m1.called
|
||||
assert m2.called
|
||||
assert ret
|
||||
self.assertEqual(ret[0].fstype, 'zfs')
|
||||
|
||||
# --- tests for specific kernel versions
|
||||
|
||||
@unittest.skipUnless(
|
||||
@ -175,12 +462,12 @@ class LinuxSpecificTestCase(unittest.TestCase):
|
||||
self.assertTrue(hasattr(psutil, "RLIMIT_SIGPENDING"))
|
||||
|
||||
|
||||
def test_main():
|
||||
def main():
|
||||
test_suite = unittest.TestSuite()
|
||||
test_suite.addTest(unittest.makeSuite(LinuxSpecificTestCase))
|
||||
result = unittest.TextTestRunner(verbosity=2).run(test_suite)
|
||||
return result.wasSuccessful()
|
||||
|
||||
if __name__ == '__main__':
|
||||
if not test_main():
|
||||
if not main():
|
||||
sys.exit(1)
|
||||
|
@ -15,8 +15,8 @@ import time
|
||||
import psutil
|
||||
|
||||
from psutil._compat import PY3
|
||||
from test_psutil import (TOLERANCE, sh, get_test_subprocess, reap_children,
|
||||
retry_before_failing, unittest)
|
||||
from test_psutil import (TOLERANCE, OSX, sh, get_test_subprocess,
|
||||
reap_children, retry_before_failing, unittest)
|
||||
|
||||
|
||||
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
|
||||
@ -47,6 +47,7 @@ def vm_stat(field):
|
||||
return int(re.search('\d+', line).group(0)) * PAGESIZE
|
||||
|
||||
|
||||
@unittest.skipUnless(OSX, "not an OSX system")
|
||||
class OSXSpecificTestCase(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
@ -148,12 +149,12 @@ class OSXSpecificTestCase(unittest.TestCase):
|
||||
self.assertEqual(tot1, tot2)
|
||||
|
||||
|
||||
def test_main():
|
||||
def main():
|
||||
test_suite = unittest.TestSuite()
|
||||
test_suite.addTest(unittest.makeSuite(OSXSpecificTestCase))
|
||||
result = unittest.TextTestRunner(verbosity=2).run(test_suite)
|
||||
return result.wasSuccessful()
|
||||
|
||||
if __name__ == '__main__':
|
||||
if not test_main():
|
||||
if not main():
|
||||
sys.exit(1)
|
||||
|
@ -14,8 +14,8 @@ import time
|
||||
|
||||
import psutil
|
||||
|
||||
from psutil._compat import PY3
|
||||
from test_psutil import LINUX, SUNOS, OSX, BSD, PYTHON
|
||||
from psutil._compat import PY3, callable
|
||||
from test_psutil import LINUX, SUNOS, OSX, BSD, PYTHON, POSIX, TRAVIS
|
||||
from test_psutil import (get_test_subprocess, skip_on_access_denied,
|
||||
retry_before_failing, reap_children, sh, unittest,
|
||||
get_kernel_version, wait_for_pid)
|
||||
@ -42,6 +42,7 @@ def ps(cmd):
|
||||
return output
|
||||
|
||||
|
||||
@unittest.skipUnless(POSIX, "not a POSIX system")
|
||||
class PosixSpecificTestCase(unittest.TestCase):
|
||||
"""Compare psutil results against 'ps' command line utility."""
|
||||
|
||||
@ -111,11 +112,14 @@ class PosixSpecificTestCase(unittest.TestCase):
|
||||
def test_process_create_time(self):
|
||||
time_ps = ps("ps --no-headers -o start -p %s" % self.pid).split(' ')[0]
|
||||
time_psutil = psutil.Process(self.pid).create_time()
|
||||
if SUNOS:
|
||||
time_psutil = round(time_psutil)
|
||||
time_psutil_tstamp = datetime.datetime.fromtimestamp(
|
||||
time_psutil).strftime("%H:%M:%S")
|
||||
self.assertEqual(time_ps, time_psutil_tstamp)
|
||||
# sometimes ps shows the time rounded up instead of down, so we check
|
||||
# for both possible values
|
||||
round_time_psutil = round(time_psutil)
|
||||
round_time_psutil_tstamp = datetime.datetime.fromtimestamp(
|
||||
round_time_psutil).strftime("%H:%M:%S")
|
||||
self.assertIn(time_ps, [time_psutil_tstamp, round_time_psutil_tstamp])
|
||||
|
||||
def test_process_exe(self):
|
||||
ps_pathname = ps("ps --no-headers -o command -p %s" %
|
||||
@ -173,9 +177,10 @@ class PosixSpecificTestCase(unittest.TestCase):
|
||||
[x for x in pids_ps if x not in pids_psutil]
|
||||
self.fail("difference: " + str(difference))
|
||||
|
||||
# for some reason ifconfig -a does not report differente interfaces
|
||||
# psutil does
|
||||
# for some reason ifconfig -a does not report all interfaces
|
||||
# returned by psutil
|
||||
@unittest.skipIf(SUNOS, "test not reliable on SUNOS")
|
||||
@unittest.skipIf(TRAVIS, "test not reliable on Travis")
|
||||
def test_nic_names(self):
|
||||
p = subprocess.Popen("ifconfig -a", shell=1, stdout=subprocess.PIPE)
|
||||
output = p.communicate()[0].strip()
|
||||
@ -186,7 +191,9 @@ class PosixSpecificTestCase(unittest.TestCase):
|
||||
if line.startswith(nic):
|
||||
break
|
||||
else:
|
||||
self.fail("couldn't find %s nic in 'ifconfig -a' output" % nic)
|
||||
self.fail(
|
||||
"couldn't find %s nic in 'ifconfig -a' output\n%s" % (
|
||||
nic, output))
|
||||
|
||||
@retry_before_failing()
|
||||
def test_users(self):
|
||||
@ -208,8 +215,6 @@ class PosixSpecificTestCase(unittest.TestCase):
|
||||
if attr is not None and callable(attr):
|
||||
if name == 'rlimit':
|
||||
args = (psutil.RLIMIT_NOFILE,)
|
||||
elif name == 'set_rlimit':
|
||||
args = (psutil.RLIMIT_NOFILE, (5, 5))
|
||||
attr(*args)
|
||||
else:
|
||||
attr
|
||||
@ -220,11 +225,10 @@ class PosixSpecificTestCase(unittest.TestCase):
|
||||
'send_signal', 'wait', 'children', 'as_dict']
|
||||
if LINUX and get_kernel_version() < (2, 6, 36):
|
||||
ignored_names.append('rlimit')
|
||||
if LINUX and get_kernel_version() < (2, 6, 23):
|
||||
ignored_names.append('num_ctx_switches')
|
||||
for name in dir(psutil.Process):
|
||||
if (name.startswith('_')
|
||||
or name.startswith('set_')
|
||||
or name.startswith('get') # deprecated APIs
|
||||
or name in ignored_names):
|
||||
if (name.startswith('_') or name in ignored_names):
|
||||
continue
|
||||
else:
|
||||
try:
|
||||
@ -243,12 +247,12 @@ class PosixSpecificTestCase(unittest.TestCase):
|
||||
self.fail('\n' + '\n'.join(failures))
|
||||
|
||||
|
||||
def test_main():
|
||||
def main():
|
||||
test_suite = unittest.TestSuite()
|
||||
test_suite.addTest(unittest.makeSuite(PosixSpecificTestCase))
|
||||
result = unittest.TextTestRunner(verbosity=2).run(test_suite)
|
||||
return result.wasSuccessful()
|
||||
|
||||
if __name__ == '__main__':
|
||||
if not test_main():
|
||||
if not main():
|
||||
sys.exit(1)
|
||||
|
@ -7,15 +7,17 @@
|
||||
"""Sun OS specific tests. These are implicitly run by test_psutil.py."""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
from test_psutil import sh, unittest
|
||||
from test_psutil import SUNOS, sh, unittest
|
||||
import psutil
|
||||
|
||||
|
||||
@unittest.skipUnless(SUNOS, "not a SunOS system")
|
||||
class SunOSSpecificTestCase(unittest.TestCase):
|
||||
|
||||
def test_swap_memory(self):
|
||||
out = sh('swap -l -k')
|
||||
out = sh('env PATH=/usr/sbin:/sbin:%s swap -l -k' % os.environ['PATH'])
|
||||
lines = out.strip().split('\n')[1:]
|
||||
if not lines:
|
||||
raise ValueError('no swap device(s) configured')
|
||||
@ -35,12 +37,12 @@ class SunOSSpecificTestCase(unittest.TestCase):
|
||||
self.assertEqual(psutil_swap.free, free)
|
||||
|
||||
|
||||
def test_main():
|
||||
def main():
|
||||
test_suite = unittest.TestSuite()
|
||||
test_suite.addTest(unittest.makeSuite(SunOSSpecificTestCase))
|
||||
result = unittest.TextTestRunner(verbosity=2).run(test_suite)
|
||||
return result.wasSuccessful()
|
||||
|
||||
if __name__ == '__main__':
|
||||
if not test_main():
|
||||
if not main():
|
||||
sys.exit(1)
|
||||
|
@ -15,8 +15,10 @@ import sys
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from test_psutil import (get_test_subprocess, reap_children, unittest)
|
||||
from test_psutil import APPVEYOR, WINDOWS
|
||||
from test_psutil import get_test_subprocess, reap_children, unittest
|
||||
|
||||
import mock
|
||||
try:
|
||||
import wmi
|
||||
except ImportError:
|
||||
@ -28,17 +30,18 @@ except ImportError:
|
||||
win32api = win32con = None
|
||||
|
||||
from psutil._compat import PY3, callable, long
|
||||
from psutil._pswindows import ACCESS_DENIED_SET
|
||||
import _psutil_windows
|
||||
import psutil
|
||||
|
||||
|
||||
cext = psutil._psplatform.cext
|
||||
|
||||
|
||||
def wrap_exceptions(fun):
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
return fun(self, *args, **kwargs)
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
except OSError as err:
|
||||
from psutil._pswindows import ACCESS_DENIED_SET
|
||||
if err.errno in ACCESS_DENIED_SET:
|
||||
raise psutil.AccessDenied(None, None)
|
||||
if err.errno == errno.ESRCH:
|
||||
@ -47,6 +50,7 @@ def wrap_exceptions(fun):
|
||||
return wrapper
|
||||
|
||||
|
||||
@unittest.skipUnless(WINDOWS, "not a Windows system")
|
||||
class WindowsSpecificTestCase(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
@ -114,7 +118,9 @@ class WindowsSpecificTestCase(unittest.TestCase):
|
||||
def test_process_exe(self):
|
||||
w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
|
||||
p = psutil.Process(self.pid)
|
||||
self.assertEqual(p.exe(), w.ExecutablePath)
|
||||
# Note: wmi reports the exe as a lower case string.
|
||||
# Being Windows paths case-insensitive we ignore that.
|
||||
self.assertEqual(p.exe().lower(), w.ExecutablePath.lower())
|
||||
|
||||
@unittest.skipIf(wmi is None, "wmi module is not installed")
|
||||
def test_process_cmdline(self):
|
||||
@ -164,7 +170,7 @@ class WindowsSpecificTestCase(unittest.TestCase):
|
||||
|
||||
# --- psutil namespace functions and constants tests
|
||||
|
||||
@unittest.skipUnless(hasattr(os, 'NUMBER_OF_PROCESSORS'),
|
||||
@unittest.skipUnless('NUMBER_OF_PROCESSORS' in os.environ,
|
||||
'NUMBER_OF_PROCESSORS env var is not available')
|
||||
def test_cpu_count(self):
|
||||
num_cpus = int(os.environ['NUMBER_OF_PROCESSORS'])
|
||||
@ -188,20 +194,16 @@ class WindowsSpecificTestCase(unittest.TestCase):
|
||||
# time.localtime(p.create_time()))
|
||||
#
|
||||
|
||||
# Note: this test is not very reliable
|
||||
@unittest.skipIf(wmi is None, "wmi module is not installed")
|
||||
@unittest.skipIf(APPVEYOR, "test not relieable on appveyor")
|
||||
def test_pids(self):
|
||||
# Note: this test might fail if the OS is starting/killing
|
||||
# other processes in the meantime
|
||||
w = wmi.WMI().Win32_Process()
|
||||
wmi_pids = [x.ProcessId for x in w]
|
||||
wmi_pids.sort()
|
||||
psutil_pids = psutil.pids()
|
||||
psutil_pids.sort()
|
||||
if wmi_pids != psutil_pids:
|
||||
difference = \
|
||||
filter(lambda x: x not in wmi_pids, psutil_pids) + \
|
||||
filter(lambda x: x not in psutil_pids, wmi_pids)
|
||||
self.fail("difference: " + str(difference))
|
||||
wmi_pids = set([x.ProcessId for x in w])
|
||||
psutil_pids = set(psutil.pids())
|
||||
self.assertEqual(wmi_pids, psutil_pids)
|
||||
|
||||
@unittest.skipIf(wmi is None, "wmi module is not installed")
|
||||
def test_disks(self):
|
||||
@ -215,8 +217,7 @@ class WindowsSpecificTestCase(unittest.TestCase):
|
||||
break
|
||||
try:
|
||||
usage = psutil.disk_usage(ps_part.mountpoint)
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
except OSError as err:
|
||||
if err.errno == errno.ENOENT:
|
||||
# usually this is the floppy
|
||||
break
|
||||
@ -259,8 +260,6 @@ class WindowsSpecificTestCase(unittest.TestCase):
|
||||
failures = []
|
||||
for name in dir(psutil.Process):
|
||||
if name.startswith('_') \
|
||||
or name.startswith('set_') \
|
||||
or name.startswith('get') \
|
||||
or name in ('terminate', 'kill', 'suspend', 'resume',
|
||||
'nice', 'send_signal', 'wait', 'children',
|
||||
'as_dict'):
|
||||
@ -282,29 +281,42 @@ class WindowsSpecificTestCase(unittest.TestCase):
|
||||
if failures:
|
||||
self.fail('\n' + '\n'.join(failures))
|
||||
|
||||
def test_name_always_available(self):
|
||||
# On Windows name() is never supposed to raise AccessDenied,
|
||||
# see https://github.com/giampaolo/psutil/issues/627
|
||||
for p in psutil.process_iter():
|
||||
try:
|
||||
p.name()
|
||||
except psutil.NoSuchProcess():
|
||||
pass
|
||||
|
||||
|
||||
@unittest.skipUnless(WINDOWS, "not a Windows system")
|
||||
class TestDualProcessImplementation(unittest.TestCase):
|
||||
"""
|
||||
Certain APIs on Windows have 2 internal implementations, one
|
||||
based on documented Windows APIs, another one based
|
||||
NtQuerySystemInformation() which gets called as fallback in
|
||||
case the first fails because of limited permission error.
|
||||
Here we test that the two methods return the exact same value,
|
||||
see:
|
||||
https://github.com/giampaolo/psutil/issues/304
|
||||
"""
|
||||
|
||||
fun_names = [
|
||||
# function name, tolerance
|
||||
('proc_cpu_times', 0.2),
|
||||
('proc_create_time', 0.5),
|
||||
('proc_num_handles', 1), # 1 because impl #1 opens a handle
|
||||
('proc_io_counters', 0),
|
||||
('proc_memory_info', 1024), # KB
|
||||
('proc_io_counters', 0),
|
||||
]
|
||||
|
||||
def test_compare_values(self):
|
||||
# Certain APIs on Windows have 2 internal implementations, one
|
||||
# based on documented Windows APIs, another one based
|
||||
# NtQuerySystemInformation() which gets called as fallback in
|
||||
# case the first fails because of limited permission error.
|
||||
# Here we test that the two methods return the exact same value,
|
||||
# see:
|
||||
# https://github.com/giampaolo/psutil/issues/304
|
||||
def assert_ge_0(obj):
|
||||
if isinstance(obj, tuple):
|
||||
for value in obj:
|
||||
self.assertGreaterEqual(value, 0)
|
||||
self.assertGreaterEqual(value, 0, msg=obj)
|
||||
elif isinstance(obj, (int, long, float)):
|
||||
self.assertGreaterEqual(obj, 0)
|
||||
else:
|
||||
@ -322,55 +334,125 @@ class TestDualProcessImplementation(unittest.TestCase):
|
||||
diff = abs(a - b)
|
||||
self.assertLessEqual(diff, tolerance)
|
||||
|
||||
from psutil._pswindows import ntpinfo
|
||||
failures = []
|
||||
for name, tolerance in self.fun_names:
|
||||
meth1 = wrap_exceptions(getattr(_psutil_windows, name))
|
||||
meth2 = wrap_exceptions(getattr(_psutil_windows, name + '_2'))
|
||||
for p in psutil.process_iter():
|
||||
for p in psutil.process_iter():
|
||||
try:
|
||||
nt = ntpinfo(*cext.proc_info(p.pid))
|
||||
except psutil.NoSuchProcess:
|
||||
continue
|
||||
assert_ge_0(nt)
|
||||
|
||||
for name, tolerance in self.fun_names:
|
||||
if name == 'proc_memory_info' and p.pid == os.getpid():
|
||||
continue
|
||||
#
|
||||
try:
|
||||
ret1 = meth1(p.pid)
|
||||
except psutil.NoSuchProcess:
|
||||
if name == 'proc_create_time' and p.pid in (0, 4):
|
||||
continue
|
||||
except psutil.AccessDenied:
|
||||
ret1 = None
|
||||
#
|
||||
meth = wrap_exceptions(getattr(cext, name))
|
||||
try:
|
||||
ret2 = meth2(p.pid)
|
||||
except psutil.NoSuchProcess:
|
||||
# this is supposed to fail only in case of zombie process
|
||||
# never for permission error
|
||||
ret = meth(p.pid)
|
||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
||||
continue
|
||||
|
||||
# compare values
|
||||
try:
|
||||
if ret1 is None:
|
||||
assert_ge_0(ret2)
|
||||
else:
|
||||
compare_with_tolerance(ret1, ret2, tolerance)
|
||||
assert_ge_0(ret1)
|
||||
assert_ge_0(ret2)
|
||||
if name == 'proc_cpu_times':
|
||||
compare_with_tolerance(ret[0], nt.user_time, tolerance)
|
||||
compare_with_tolerance(ret[1],
|
||||
nt.kernel_time, tolerance)
|
||||
elif name == 'proc_create_time':
|
||||
compare_with_tolerance(ret, nt.create_time, tolerance)
|
||||
elif name == 'proc_num_handles':
|
||||
compare_with_tolerance(ret, nt.num_handles, tolerance)
|
||||
elif name == 'proc_io_counters':
|
||||
compare_with_tolerance(ret[0], nt.io_rcount, tolerance)
|
||||
compare_with_tolerance(ret[1], nt.io_wcount, tolerance)
|
||||
compare_with_tolerance(ret[2], nt.io_rbytes, tolerance)
|
||||
compare_with_tolerance(ret[3], nt.io_wbytes, tolerance)
|
||||
elif name == 'proc_memory_info':
|
||||
try:
|
||||
rawtupl = cext.proc_memory_info_2(p.pid)
|
||||
except psutil.NoSuchProcess:
|
||||
continue
|
||||
compare_with_tolerance(ret, rawtupl, tolerance)
|
||||
except AssertionError:
|
||||
trace = traceback.format_exc()
|
||||
msg = '%s\npid=%s, method=%r, ret_1=%r, ret_2=%r' % (
|
||||
trace, p.pid, name, ret1, ret2)
|
||||
trace, p.pid, name, ret, nt)
|
||||
failures.append(msg)
|
||||
break
|
||||
|
||||
if failures:
|
||||
self.fail('\n\n'.join(failures))
|
||||
|
||||
# ---
|
||||
# same tests as above but mimicks the AccessDenied failure of
|
||||
# the first (fast) method failing with AD.
|
||||
# TODO: currently does not take tolerance into account.
|
||||
|
||||
def test_name(self):
|
||||
name = psutil.Process().name()
|
||||
with mock.patch("psutil._psplatform.cext.proc_exe",
|
||||
side_effect=psutil.AccessDenied(os.getpid())) as fun:
|
||||
psutil.Process().name() == name
|
||||
assert fun.called
|
||||
|
||||
def test_memory_info(self):
|
||||
mem = psutil.Process().memory_info()
|
||||
with mock.patch("psutil._psplatform.cext.proc_memory_info",
|
||||
side_effect=OSError(errno.EPERM, "msg")) as fun:
|
||||
psutil.Process().memory_info() == mem
|
||||
assert fun.called
|
||||
|
||||
def test_create_time(self):
|
||||
ctime = psutil.Process().create_time()
|
||||
with mock.patch("psutil._psplatform.cext.proc_create_time",
|
||||
side_effect=OSError(errno.EPERM, "msg")) as fun:
|
||||
psutil.Process().create_time() == ctime
|
||||
assert fun.called
|
||||
|
||||
def test_cpu_times(self):
|
||||
cpu_times = psutil.Process().cpu_times()
|
||||
with mock.patch("psutil._psplatform.cext.proc_cpu_times",
|
||||
side_effect=OSError(errno.EPERM, "msg")) as fun:
|
||||
psutil.Process().cpu_times() == cpu_times
|
||||
assert fun.called
|
||||
|
||||
def test_io_counters(self):
|
||||
io_counters = psutil.Process().io_counters()
|
||||
with mock.patch("psutil._psplatform.cext.proc_io_counters",
|
||||
side_effect=OSError(errno.EPERM, "msg")) as fun:
|
||||
psutil.Process().io_counters() == io_counters
|
||||
assert fun.called
|
||||
|
||||
def test_num_handles(self):
|
||||
io_counters = psutil.Process().io_counters()
|
||||
with mock.patch("psutil._psplatform.cext.proc_io_counters",
|
||||
side_effect=OSError(errno.EPERM, "msg")) as fun:
|
||||
psutil.Process().io_counters() == io_counters
|
||||
assert fun.called
|
||||
|
||||
# --- other tests
|
||||
|
||||
def test_compare_name_exe(self):
|
||||
for p in psutil.process_iter():
|
||||
try:
|
||||
a = os.path.basename(p.exe())
|
||||
b = p.name()
|
||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
||||
pass
|
||||
else:
|
||||
self.assertEqual(a, b)
|
||||
|
||||
def test_zombies(self):
|
||||
# test that NPS is raised by the 2nd implementation in case a
|
||||
# process no longer exists
|
||||
ZOMBIE_PID = max(psutil.pids()) + 5000
|
||||
for name, _ in self.fun_names:
|
||||
meth = wrap_exceptions(getattr(_psutil_windows, name))
|
||||
meth = wrap_exceptions(getattr(cext, name))
|
||||
self.assertRaises(psutil.NoSuchProcess, meth, ZOMBIE_PID)
|
||||
|
||||
|
||||
def test_main():
|
||||
def main():
|
||||
test_suite = unittest.TestSuite()
|
||||
test_suite.addTest(unittest.makeSuite(WindowsSpecificTestCase))
|
||||
test_suite.addTest(unittest.makeSuite(TestDualProcessImplementation))
|
||||
@ -378,5 +460,5 @@ def test_main():
|
||||
return result.wasSuccessful()
|
||||
|
||||
if __name__ == '__main__':
|
||||
if not test_main():
|
||||
if not main():
|
||||
sys.exit(1)
|
||||
|
@ -10,6 +10,7 @@ functions many times and compare process memory usage before and
|
||||
after the calls. It might produce false positives.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import gc
|
||||
import os
|
||||
import socket
|
||||
@ -17,20 +18,20 @@ import sys
|
||||
import threading
|
||||
import time
|
||||
|
||||
import psutil
|
||||
import psutil._common
|
||||
|
||||
from psutil._compat import xrange, callable
|
||||
from test_psutil import (WINDOWS, POSIX, OSX, LINUX, SUNOS, BSD, TESTFN,
|
||||
RLIMIT_SUPPORT, TRAVIS)
|
||||
from test_psutil import (reap_children, supports_ipv6, safe_remove,
|
||||
get_test_subprocess)
|
||||
|
||||
if sys.version_info < (2, 7):
|
||||
import unittest2 as unittest # https://pypi.python.org/pypi/unittest2
|
||||
else:
|
||||
import unittest
|
||||
|
||||
import psutil
|
||||
import psutil._common
|
||||
|
||||
from psutil._compat import callable, xrange
|
||||
from test_psutil import (WINDOWS, POSIX, OSX, LINUX, SUNOS, TESTFN,
|
||||
RLIMIT_SUPPORT)
|
||||
from test_psutil import (reap_children, supports_ipv6, safe_remove,
|
||||
get_test_subprocess)
|
||||
|
||||
|
||||
LOOPS = 1000
|
||||
TOLERANCE = 4096
|
||||
@ -43,7 +44,7 @@ def skip_if_linux():
|
||||
|
||||
|
||||
class Base(unittest.TestCase):
|
||||
proc = psutil.Process(os.getpid())
|
||||
proc = psutil.Process()
|
||||
|
||||
def execute(self, function, *args, **kwargs):
|
||||
def call_many_times():
|
||||
@ -73,7 +74,7 @@ class Base(unittest.TestCase):
|
||||
# Let's keep calling fun for 3 more seconds and fail if
|
||||
# we notice any difference.
|
||||
stop_at = time.time() + 3
|
||||
while 1:
|
||||
while True:
|
||||
self.call(function, *args, **kwargs)
|
||||
if time.time() >= stop_at:
|
||||
break
|
||||
@ -85,10 +86,14 @@ class Base(unittest.TestCase):
|
||||
self.fail("rss2=%s, rss3=%s, difference=%s"
|
||||
% (rss2, rss3, difference))
|
||||
|
||||
def get_mem(self):
|
||||
return psutil.Process(os.getpid()).memory_info()[0]
|
||||
def execute_w_exc(self, exc, function, *args, **kwargs):
|
||||
kwargs['_exc'] = exc
|
||||
self.execute(function, *args, **kwargs)
|
||||
|
||||
def call(self, *args, **kwargs):
|
||||
def get_mem(self):
|
||||
return psutil.Process().memory_info()[0]
|
||||
|
||||
def call(self, function, *args, **kwargs):
|
||||
raise NotImplementedError("must be implemented in subclass")
|
||||
|
||||
|
||||
@ -102,12 +107,25 @@ class TestProcessObjectLeaks(Base):
|
||||
reap_children()
|
||||
|
||||
def call(self, function, *args, **kwargs):
|
||||
try:
|
||||
obj = getattr(self.proc, function)
|
||||
if callable(obj):
|
||||
obj(*args, **kwargs)
|
||||
except psutil.Error:
|
||||
pass
|
||||
if callable(function):
|
||||
if '_exc' in kwargs:
|
||||
exc = kwargs.pop('_exc')
|
||||
self.assertRaises(exc, function, *args, **kwargs)
|
||||
else:
|
||||
try:
|
||||
function(*args, **kwargs)
|
||||
except psutil.Error:
|
||||
pass
|
||||
else:
|
||||
meth = getattr(self.proc, function)
|
||||
if '_exc' in kwargs:
|
||||
exc = kwargs.pop('_exc')
|
||||
self.assertRaises(exc, meth, *args, **kwargs)
|
||||
else:
|
||||
try:
|
||||
meth(*args, **kwargs)
|
||||
except psutil.Error:
|
||||
pass
|
||||
|
||||
@skip_if_linux()
|
||||
def test_name(self):
|
||||
@ -143,7 +161,7 @@ class TestProcessObjectLeaks(Base):
|
||||
self.execute('nice')
|
||||
|
||||
def test_nice_set(self):
|
||||
niceness = psutil.Process(os.getpid()).nice()
|
||||
niceness = psutil.Process().nice()
|
||||
self.execute('nice', niceness)
|
||||
|
||||
@unittest.skipUnless(hasattr(psutil.Process, 'ionice'),
|
||||
@ -155,16 +173,20 @@ class TestProcessObjectLeaks(Base):
|
||||
"Linux and Windows Vista only")
|
||||
def test_ionice_set(self):
|
||||
if WINDOWS:
|
||||
value = psutil.Process(os.getpid()).ionice()
|
||||
value = psutil.Process().ionice()
|
||||
self.execute('ionice', value)
|
||||
else:
|
||||
from psutil._pslinux import cext
|
||||
self.execute('ionice', psutil.IOPRIO_CLASS_NONE)
|
||||
fun = functools.partial(cext.proc_ioprio_set, os.getpid(), -1, 0)
|
||||
self.execute_w_exc(OSError, fun)
|
||||
|
||||
@unittest.skipIf(OSX, "feature not supported on this platform")
|
||||
@unittest.skipIf(OSX or SUNOS, "feature not supported on this platform")
|
||||
@skip_if_linux()
|
||||
def test_io_counters(self):
|
||||
self.execute('io_counters')
|
||||
|
||||
@unittest.skipUnless(WINDOWS, "not worth being tested on posix")
|
||||
def test_username(self):
|
||||
self.execute('username')
|
||||
|
||||
@ -215,23 +237,24 @@ class TestProcessObjectLeaks(Base):
|
||||
def test_cwd(self):
|
||||
self.execute('cwd')
|
||||
|
||||
@unittest.skipUnless(WINDOWS or LINUX, "Windows or Linux only")
|
||||
@unittest.skipUnless(WINDOWS or LINUX or BSD,
|
||||
"Windows or Linux or BSD only")
|
||||
def test_cpu_affinity_get(self):
|
||||
self.execute('cpu_affinity')
|
||||
|
||||
@unittest.skipUnless(WINDOWS or LINUX, "Windows or Linux only")
|
||||
@unittest.skipUnless(WINDOWS or LINUX or BSD,
|
||||
"Windows or Linux or BSD only")
|
||||
def test_cpu_affinity_set(self):
|
||||
affinity = psutil.Process(os.getpid()).cpu_affinity()
|
||||
affinity = psutil.Process().cpu_affinity()
|
||||
self.execute('cpu_affinity', affinity)
|
||||
if not TRAVIS:
|
||||
self.execute_w_exc(ValueError, 'cpu_affinity', [-1])
|
||||
|
||||
@skip_if_linux()
|
||||
def test_open_files(self):
|
||||
safe_remove(TESTFN) # needed after UNIX socket test has run
|
||||
f = open(TESTFN, 'w')
|
||||
try:
|
||||
with open(TESTFN, 'w'):
|
||||
self.execute('open_files')
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
# OSX implementation is unbelievably slow
|
||||
@unittest.skipIf(OSX, "OSX implementation is too slow")
|
||||
@ -251,6 +274,7 @@ class TestProcessObjectLeaks(Base):
|
||||
def test_rlimit_set(self):
|
||||
limit = psutil.Process().rlimit(psutil.RLIMIT_NOFILE)
|
||||
self.execute('rlimit', psutil.RLIMIT_NOFILE, limit)
|
||||
self.execute_w_exc(OSError, 'rlimit', -1)
|
||||
|
||||
@skip_if_linux()
|
||||
# Windows implementation is based on a single system-wide function
|
||||
@ -301,6 +325,12 @@ class TestProcessObjectLeaksZombie(TestProcessObjectLeaks):
|
||||
"""
|
||||
proc = DEAD_PROC
|
||||
|
||||
def call(self, *args, **kwargs):
|
||||
try:
|
||||
TestProcessObjectLeaks.call(self, *args, **kwargs)
|
||||
except psutil.NoSuchProcess:
|
||||
pass
|
||||
|
||||
if not POSIX:
|
||||
def test_kill(self):
|
||||
self.execute('kill')
|
||||
@ -325,9 +355,8 @@ class TestModuleFunctionsLeaks(Base):
|
||||
gc.collect()
|
||||
|
||||
def call(self, function, *args, **kwargs):
|
||||
obj = getattr(psutil, function)
|
||||
if callable(obj):
|
||||
obj(*args, **kwargs)
|
||||
fun = getattr(psutil, function)
|
||||
fun(*args, **kwargs)
|
||||
|
||||
@skip_if_linux()
|
||||
def test_cpu_count_logical(self):
|
||||
@ -393,8 +422,15 @@ class TestModuleFunctionsLeaks(Base):
|
||||
def test_net_connections(self):
|
||||
self.execute('net_connections')
|
||||
|
||||
def test_net_if_addrs(self):
|
||||
self.execute('net_if_addrs')
|
||||
|
||||
def test_main():
|
||||
@unittest.skipIf(TRAVIS, "EPERM on travis")
|
||||
def test_net_if_stats(self):
|
||||
self.execute('net_if_stats')
|
||||
|
||||
|
||||
def main():
|
||||
test_suite = unittest.TestSuite()
|
||||
tests = [TestProcessObjectLeaksZombie,
|
||||
TestProcessObjectLeaks,
|
||||
@ -405,5 +441,5 @@ def test_main():
|
||||
return result.wasSuccessful()
|
||||
|
||||
if __name__ == '__main__':
|
||||
if not test_main():
|
||||
if not main():
|
||||
sys.exit(1)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,16 +9,24 @@ envlist = py26, py27, py32, py33, py34
|
||||
|
||||
[testenv]
|
||||
deps =
|
||||
pytest
|
||||
flake8
|
||||
pytest
|
||||
py26: ipaddress
|
||||
py26: mock==1.0.1
|
||||
py26: unittest2
|
||||
py27: ipaddress
|
||||
py27: mock
|
||||
py32: ipaddress
|
||||
py32: mock
|
||||
py33: ipaddress
|
||||
|
||||
setenv =
|
||||
PYTHONPATH = {toxinidir}/test
|
||||
|
||||
commands =
|
||||
py.test {posargs}
|
||||
flake8 --exclude=build,.tox,.git
|
||||
git ls-files | grep \\.py$ | xargs flake8
|
||||
|
||||
[testenv:py26]
|
||||
deps =
|
||||
flake8
|
||||
pytest
|
||||
unittest2
|
||||
# suppress "WARNING: 'git' command found but not installed in testenv
|
||||
whitelist_externals = git
|
||||
usedevelop = True
|
||||
|
Loading…
Reference in New Issue
Block a user