revert bug 1436857

--HG--
extra : rebase_source : 7e5096f0f4e725d4a8f1345b88d2f608c1d11c7f
This commit is contained in:
Jared Wein 2018-02-20 12:51:54 -08:00
parent c490bdeb07
commit 95a0702231
153 changed files with 14562 additions and 36086 deletions

View File

@ -337,7 +337,7 @@ class DesktopUnittest(TestingMixin, MercurialScript, BlobUploadMixin, MozbaseMix
dirs = self.query_abs_dirs()
self.register_virtualenv_module(name='pip>=1.5')
self.register_virtualenv_module('psutil==5.4.3', method='pip')
self.register_virtualenv_module('psutil==3.1.1', method='pip')
self.register_virtualenv_module(name='mock')
self.register_virtualenv_module(name='simplejson')

View File

@ -3,7 +3,7 @@ twisted==10.2.0
# websocket adapter for twisted, might be built into twisted someday
txws==0.9.1
psutil==5.4.3
psutil==3.1.1
# needed by txws, but pypi doesn't know about it
six==1.10.0

View File

@ -20,32 +20,6 @@ C: Italy
E: g.rodola@gmail.com
W: http://grodola.blogspot.com/
Experts
=======
Github usernames of people to CC on github when in need of help.
- NetBSD:
- 0-wiz-0, Thomas Klausner
- ryoqun, Ryo Onodera
- OpenBSD:
- landryb, Landry Breuil
- FreeBSD:
- glebius, Gleb Smirnoff (#1013)
- sunpoet, Po-Chuan Hsieh (pkg maintainer, #1105)
- kostikbel, Konstantin Belousov (#1105)
- OSX:
- whitlockjc, Jeremy Whitlock
- Windows:
- mrjefftang, Jeff Tang
- wj32, Wen Jia Liu
- fbenkstein, Frank Benkstein
- SunOS:
- wiggin15, Arnon Yaari
- alxchk, Oleksii Shevchuk
- AIX:
- wiggin15, Arnon Yaari (maintainer)
Contributors
============
@ -55,24 +29,11 @@ E: jloden@gmail.com
D: original co-author, initial design/bootstrap and occasional bug fixes
W: http://www.jayloden.com
N: Arnon Yaari (wiggin15)
W: https://github.com/wiggin15
I: 517, 607, 610, 1131, 1123, 1130, 1154, 1164, 1174, 1177
N: Jeff Tang
W: https://github.com/mrjefftang
I: 340, 529, 616, 653, 654, 648, 641
N: Jeremy Whitlock
E: jcscoobyrs@gmail.com
D: great help with OSX C development.
I: 125, 150, 174, 206
N: Landry Breuil
W: https://github.com/landryb
D: OpenBSD implementation.
I: 615
N: wj32
E: wj32.64@gmail.com
D: process username() and get_connections() on Windows
@ -95,14 +56,6 @@ W: http://daviddaeschler.com
D: some contributions to initial design/bootstrap plus occasional bug fixing
I: 522, 536
N: Thomas Klausner
W: https://github.com/0-wiz-0
I: #557
N: Ryo Onodera
W: https://github.com/ryoon
I: #557
N: cjgohlke
E: cjgohlke@gmail.com
D: Windows 64 bit support
@ -300,6 +253,10 @@ N: msabramo
E: msabramo@gmail.com
I: 492
N: Jeff Tang
W: https://github.com/mrjefftang
I: 340, 529, 616, 653, 654
N: Yaolong Huang
E: airekans@gmail.com
W: http://airekans.github.io/
@ -310,9 +267,8 @@ W: https://github.com/anders-chrigstrom
I: 496
N: spacewander
W: https://github.com/spacewander
E: spacewanderlzx@gmail.com
I: 561, 603
I: 561
N: Sylvain Mouquet
E: sylvain.mouquet@gmail.com
@ -352,166 +308,3 @@ N: Árni Már Jónsson
E: Reykjavik, Iceland
E: https://github.com/arnimarj
I: 634
N: Bart van Kleef
W: https://github.com/bkleef
I: 664
N: Steven Winfield
W: https://github.com/stevenwinfield
I: 672
N: sk6249
W: https://github.com/sk6249
I: 670
N: maozguttman
W: https://github.com/maozguttman
I: 659
N: dasumin
W: https://github.com/dasumin
I: 541
N: Mike Sarahan
W: https://github.com/msarahan
I: 688
N: Syohei YOSHIDA
W: https://github.com/syohex
I: 730
N: Frank Benkstein
W: https://github.com/fbenkstein
I: 732, 733
N: Visa Hankala
E: visa@openbsd.org
I: 741
N: Sebastian-Gabriel Brestin
C: Romania
E: sebastianbrestin@gmail.com
I: 704
N: Timmy Konick
W: https://github.com/tijko
I: 751
N: mpderbec
W: https://github.com/mpderbec
I: 660
N: Mozilla Foundation
D: sample code for process USS memory.
N: wxwright
W: https://github.com/wxwright
I: 776
N: Farhan Khan
E: khanzf@gmail.com
I: 823
N: Jake Omann
E: https://github.com/jomann09
I: 816, 775
N: Jeremy Humble
W: https://github.com/jhumble
I: 863
N: Ilya Georgievsky
W: https://github.com/xBeAsTx
I: 870
N: Yago Jesus
W: https://github.com/YJesus
I: 798
N: Andre Caron
C: Montreal, QC, Canada
E: andre.l.caron@gmail.com
W: https://github.com/AndreLouisCaron
I: 880
N: ewedlund
W: https://github.com/ewedlund
I: 874
N: Arcadiy Ivanov
W: https://github.com/arcivanov
I: 919
N: Max Bélanger
W: https://github.com/maxbelanger
I: 936, 1133
N: Pierre Fersing
C: France
E: pierre.fersing@bleemeo.com
I: 950
N: Thiago Borges Abdnur
W: https://github.com/bolaum
I: 959
N: Nicolas Hennion
W: https://github.com/nicolargo
I: 974
N: Baruch Siach
W: https://github.com/baruchsiach
I: 872
N: Danek Duvall
W: https://github.com/dhduvall
I: 1002
N: Alexander Hasselhuhn
C: Germany
W: https://github.com/alexanha
N: Himanshu Shekhar
W: https://github.com/himanshub16
I: 1036
N: Yannick Gingras
W: https://github.com/ygingras
I: 1057
N: Gleb Smirnoff
W: https://github.com/glebius
I: 1042, 1079
N: Oleksii Shevchuk
W: https://github.com/alxchk
I: 1077, 1093, 1091
N: Prodesire
W: https://github.com/Prodesire
I: 1138
N: Sebastian Saip
W: https://github.com/ssaip
I: 1141
N: Jakub Bacic
W: https://github.com/jakub-bacic
I: 1127
N: Akos Kiss
W: https://github.com/akosthekiss
I: 1150
N: Adrian Page
W: https://github.com/adpag
I: 1159, 1160, 1161
N: Matthew Long
W: https://github.com/matray
I: 1167
N: janderbrain
W: https://github.com/janderbrain
I: 1169

View File

@ -1,209 +0,0 @@
=======================
Setup and running tests
=======================
If you plan on hacking on psutil this is what you're supposed to do first:
- clone the GIT repository:
.. code-block:: bash
$ git clone git@github.com:giampaolo/psutil.git
- install test deps and GIT hooks:
.. code-block:: bash
make setup-dev-env
- run tests:
.. code-block:: bash
make test
- bear in mind that ``make``
(see `Makefile <https://github.com/giampaolo/psutil/blob/master/Makefile>`_)
is the designated tool to run tests, build, install etc. and that it is also
available on Windows
(see `make.bat <https://github.com/giampaolo/psutil/blob/master/make.bat>`_).
- do not use ``sudo``; ``make install`` installs psutil as a limited user in
"edit" mode; also ``make setup-dev-env`` installs deps as a limited user.
- use `make help` to see the list of available commands.
============
Coding style
============
- python code strictly follows `PEP 8 <https://www.python.org/dev/peps/pep-0008/>`_
styling guides and this is enforced by ``make install-git-hooks``.
- C code strictly follows `PEP 7 <https://www.python.org/dev/peps/pep-0007/>`_
styling guides.
========
Makefile
========
Some useful make commands:
.. code-block:: bash
make install # install
make setup-dev-env # install useful dev libs (pyflakes, unittest2, etc.)
make test # run unit tests
make test-memleaks # run memory leak tests
make test-coverage # run test coverage
make flake8 # run PEP8 linter
There are some differences between ``make`` on UNIX and Windows.
For instance, to run a specific Python version. On UNIX:
.. code-block:: bash
make test PYTHON=python3.5
On Windows:
.. code-block:: bat
set PYTHON=C:\python35\python.exe && make test
...or:
.. code-block:: bat
make -p 35 test
If you want to modify psutil and run a script on the fly which uses it do
(on UNIX):
.. code-block:: bash
make test TSCRIPT=foo.py
On Windows:
.. code-block:: bat
set TSCRIPT=foo.py && make test
====================
Adding a new feature
====================
Usually the files involved when adding a new functionality are:
.. code-block:: bash
psutil/__init__.py # main psutil namespace
psutil/_ps{platform}.py # python platform wrapper
psutil/_psutil_{platform}.c # C platform extension
psutil/_psutil_{platform}.h # C header file
psutil/tests/test_process|system.py # main test suite
psutil/tests/test_{platform}.py # platform specific test suite
Typical process occurring when adding a new functionality (API):
- define the new function in ``psutil/__init__.py``.
- write the platform specific implementation in ``psutil/_ps{platform}.py``
(e.g. ``psutil/_pslinux.py``).
- if the change requires C, write the C implementation in
``psutil/_psutil_{platform}.c`` (e.g. ``psutil/_psutil_linux.c``).
- write a generic test in ``psutil/tests/test_system.py`` or
``psutil/tests/test_process.py``.
- if possible, write a platform specific test in
``psutil/tests/test_{platform}.py`` (e.g. ``test_linux.py``).
This usually means testing the return value of the new feature against
a system CLI tool.
- update doc in ``doc/index.py``.
- update ``HISTORY.rst``.
- update ``README.rst`` (if necessary).
- make a pull request.
===================
Make a pull request
===================
- fork psutil
- create your feature branch (``git checkout -b my-new-feature``)
- commit your changes (``git commit -am 'add some feature'``)
- push to the branch (``git push origin my-new-feature``)
- create a new pull request
======================
Continuous integration
======================
All of the services listed below are automatically run on ``git push``.
Unit tests
----------
Tests are automatically run for every GIT push on **Linux**, **OSX** and
**Windows** by using:
- `Travis <https://travis-ci.org/giampaolo/psutil>`_ (Linux, OSX)
- `Appveyor <https://ci.appveyor.com/project/giampaolo/psutil>`_ (Windows)
Test files controlling these are
`.travis.yml <https://github.com/giampaolo/psutil/blob/master/.travis.yml>`_
and
`appveyor.yml <https://github.com/giampaolo/psutil/blob/master/appveyor.yml>`_.
Both services run psutil test suite against all supported python version
(2.6 - 3.6).
Two icons in the home page (README) always show the build status:
.. image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux%20/%20OSX
:target: https://travis-ci.org/giampaolo/psutil
:alt: Linux tests (Travis)
.. image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows
:target: https://ci.appveyor.com/project/giampaolo/psutil
:alt: Windows tests (Appveyor)
OSX, BSD, AIX and Solaris are currently tested manually (sigh!).
Test coverage
-------------
Test coverage is provided by `coveralls.io <https://coveralls.io/github/giampaolo/psutil>`_,
it is controlled via `.travis.yml <https://github.com/giampaolo/psutil/blob/master/.travis.yml>`_
and it is updated on every git push.
An icon in the home page (README) always shows the last coverage percentage:
.. 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)
=============
Documentation
=============
- doc source code is written in a single file: `/docs/index.rst <https://raw.githubusercontent.com/giampaolo/psutil/master/docs/index.rst>`_.
- it uses `RsT syntax <http://docutils.sourceforge.net/docs/user/rst/quickref.html>`_
and it's built with `sphinx <http://sphinx-doc.org/>`_.
- doc can be built with ``make setup-dev-env; cd docs; make html``.
- public doc is hosted on http://psutil.readthedocs.io/
=======================
Releasing a new version
=======================
These are notes for myself (Giampaolo):
- ``make release``
- post announce (``make print-announce``) on psutil and python-announce mailing
lists, twitter, g+, blog.
=============
FreeBSD notes
=============
- setup:
.. code-block:: bash
pkg install python python3 gcc git vim screen bash
chsh -s /usr/local/bin/bash user # set bash as default shell
- ``/usr/src`` contains the source codes for all installed CLI tools (grep in it).

File diff suppressed because it is too large Load Diff

View File

@ -1,165 +0,0 @@
TODO
====
A collection of ideas and notes about stuff to implement in future versions.
"#NNN" occurrences refer to bug tracker issues at:
https://github.com/giampaolo/psutil/issues
PLATFORMS
=========
- #355: Android (with patch)
- #82: Cygwin (PR at #998)
- #276: GNU/Hurd
- #693: Windows Nano
- DragonFlyBSD
- HP-UX
FEATURES
========
- #371: sensors_temperatures() at least for OSX.
- #669: Windows / net_if_addrs(): return broadcast addr.
- #550: CPU info (frequency, architecture, threads per core, cores per socket,
sockets, ...)
- #772: extended net_io_counters() metrics.
- #900: wheels for OSX and Linux.
- #922: extended net_io_stats() info.
- #914: extended platform specific process info.
- #898: wifi stats
- #893: (BSD) process environ
- #809: (BSD) per-process resource limits (rlimit()).
- (UNIX) process root (different from cwd)
- #782: (UNIX) process num of signals received.
- (Linux) locked files via /proc/locks:
https://www.centos.org/docs/5/html/5.2/Deployment_Guide/s2-proc-locks.html
- #269: NIC rx/tx queue. This should probably go into net_if_stats().
Figure out on what platforms this is supported:
Linux: yes
Others: ?
- Process.threads(): thread names; patch for OSX available at:
https://code.google.com/p/plcrashreporter/issues/detail?id=65
Sample code:
https://github.com/janmojzis/pstree/blob/master/proc_kvm.c
- 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
- scripts/taskmgr-gui.py (using tk).
- system-wide number of open file descriptors:
- https://jira.hyperic.com/browse/SIGAR-30
- Number of system threads.
- Windows: http://msdn.microsoft.com/en-us/library/windows/desktop/ms684824(v=vs.85).aspx
- 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()
killall-> (actual script)
tty -> psutil.Process.terminal()
who -> psutil.users()
```
- 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: scripts/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).
- [Linux]: process cgroups (http://en.wikipedia.org/wiki/Cgroups). They look
similar to prlimit() in terms of functionality but uglier (they should allow
limiting per-process network IO resources though, which is great). Needs
further reading.
- Python 3.3. exposed different sched.h functions:
http://docs.python.org/dev/whatsnew/3.3.html#os
http://bugs.python.org/issue12655
http://docs.python.org/dev/library/os.html#interface-to-the-scheduler
It might be worth to take a look and figure out whether we can include some
of those in psutil.
Also, we can probably reimplement wait_pid() on POSIX which is currently
implemented as a busy-loop.
- os.times() provides 'elapsed' times (cpu_times() might).
- ...also guest_time and cguest_time on Linux.
- Enrich exception classes hierarchy on Python >= 3.3 / post PEP-3151 so that:
- NoSuchProcess inherits from ProcessLookupError
- AccessDenied inherits from PermissionError
- TimeoutExpired inherits from TimeoutError (debatable)
See: http://docs.python.org/3/library/exceptions.html#os-exceptions
- Process.threads() might grow an extra "id" parameter so that it can be
used as such:
```
>>> p = psutil.Process(os.getpid())
>>> p.threads(id=psutil.current_thread_id())
thread(id=2539, user_time=0.03, system_time=0.02)
>>>
```
Note: this leads to questions such as "should we have a custom NoSuchThread
exception? Also see issue #418.
Note #2: this would work with os.getpid() only.
psutil.current_thread_id() might be desirable as per issue #418 though.
- should psutil.TimeoutExpired exception have a 'msg' kwarg similar to
NoSuchProcess and AccessDenied? Not that we need it, but currently we
cannot raise a TimeoutExpired exception with a specific error string.
- process_iter() might grow an "attrs" parameter similar to Process.as_dict()
invoke the necessary methods and include the results into a "cache"
attribute attached to the returned Process instances so that one can avoid
catching NSP and AccessDenied:
for p in process_iter(attrs=['cpu_percent']):
print(p.cache['cpu_percent'])
This also leads questions as whether we should introduce a sorting order.
- round Process.memory_percent() result?
- #550: number of threads per core.
BUGFIXES
========
- #600: windows / open_files(): support network file handles.
REJECTED
========
- #550: threads per core
RESOURCES
=========
- sigar: https://github.com/hyperic/sigar (Java)
- zabbix: https://zabbix.org/wiki/Get_Zabbix
- libstatgrab: http://www.i-scream.org/libstatgrab/
- top: http://www.unixtop.org/

View File

@ -1,160 +1,116 @@
Install pip
===========
============================
Installing using pip on UNIX
============================
pip is the easiest way to install psutil.
It is shipped by default with Python 2.7.9+ and 3.4+. For other Python versions
you can install it manually.
On Linux or via wget:
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::
.. code-block:: bash
$ wget https://bootstrap.pypa.io/get-pip.py
$ python get-pip.py
wget https://bootstrap.pypa.io/get-pip.py -O - | python
...then run::
On OSX or via curl:
$ pip install psutil
.. code-block:: bash
python < <(curl -s https://bootstrap.pypa.io/get-pip.py)
On Windows, `download pip <https://pip.pypa.io/en/latest/installing/>`__, open
cmd.exe and install it:
.. code-block:: bat
C:\Python27\python.exe get-pip.py
Permission issues (UNIX)
========================
The commands below assume you're running as root.
If you're not or you bump into permission errors you can either:
* prepend ``sudo``, e.g.:
.. code-block:: bash
sudo pip install psutil
* install psutil for your user only (not at system level):
.. code-block:: bash
pip install --user psutil
Linux
=====
Ubuntu / Debian:
.. code-block:: bash
sudo apt-get install gcc python-dev python-pip
pip install psutil
RedHat / CentOS:
You may need to install gcc and python header files first (see later).
.. code-block:: bash
=====================
Installing on Windows
=====================
sudo yum install gcc python-devel python-pip
pip install psutil
Just get the right installer for your Python version and architecture from:
https://pypi.python.org/pypi/psutil/#downloads
Since wheels installers are also available you may also use pip.
If you're on Python 3 use ``python3-dev`` and ``python3-pip`` instead.
OSX
===
========================================
Compiling on Windows using Visual Studio
========================================
Install `Xcode <https://developer.apple.com/downloads/?name=Xcode>`__
first, then:
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::
.. code-block:: bash
* 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>`_
pip install psutil
...then run::
Windows
=======
setup.py build
The easiest way to install psutil on Windows is to just use the pre-compiled
exe/wheel installers hosted on
`PYPI <https://pypi.python.org/pypi/psutil/#downloads>`__ via pip:
.. code-block:: bat
C:\Python27\python.exe -m pip install psutil
If you want to compile psutil from sources you'll need **Visual Studio**
(Mingw32 is no longer supported):
* Python 2.6, 2.7: `VS-2008 <http://www.microsoft.com/en-us/download/details.aspx?id=44266>`__
* Python 3.3, 3.4: `VS-2010 <http://www.visualstudio.com/downloads/download-visual-studio-vs#d-2010-express>`__
* Python 3.5+: `VS-2015 <http://www.visualstudio.com/en-au/news/vs2015-preview-vs>`__
Compiling 64 bit versions of Python 2.6 and 2.7 with VS 2008 requires
`Windows SDK and .NET Framework 3.5 SP1 <https://www.microsoft.com/en-us/download/details.aspx?id=3138>`__.
Once installed run vcvars64.bat, then you can finally compile (see
`here <http://stackoverflow.com/questions/11072521/>`__).
To compile / install psutil from sources on Windows run:
.. code-block:: bat
...or::
make.bat build
make.bat install
FreeBSD
=======
Compiling 64 bit versions of Python 2.6 and 2.7 with VS 2008 requires
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/
.. code-block:: bash
===================
Installing on Linux
===================
pkg install python gcc
python -m pip install psutil
gcc is required and so the python headers. They can easily be installed by
using the distro package manager. For example, on Debian and Ubuntu::
OpenBSD
=======
$ sudo apt-get install gcc python-dev
.. code-block:: bash
...on Redhat and CentOS::
export PKG_PATH="http://ftp.openbsd.org/pub/OpenBSD/`uname -r`/packages/`arch -s`/"
pkg_add -v python gcc
python -m pip install psutil
$ sudo yum install gcc python-devel
NetBSD
======
Once done, you can build/install psutil with::
.. code-block:: bash
export PKG_PATH="ftp.netbsd.org/pub/pkgsrc/packages/NetBSD/`uname -m`/`uname -r`/All"
pkg_add -v pkgin
pkgin install python gcc
python -m pip install psutil
Solaris
=======
If ``cc`` compiler is not installed create a symlink to ``gcc``:
.. code-block:: bash
sudo ln -s /usr/bin/gcc /usr/local/bin/cc
Install:
.. code-block:: bash
pkg install gcc
python -m pip install psutil
Install from sources
====================
.. code-block:: bash
git clone https://github.com/giampaolo/psutil.git
cd psutil
python setup.py install
$ python setup.py install
Dev Guide
=========
==================
Installing on OS X
==================
If you plan on hacking on psutil you may want to take a look at the
`dev guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`__.
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::
$ python setup.py build
To install and build::
$ python setup.py install
=====================
Installing on FreeBSD
=====================
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::
$ python setup.py build
Install and build::
$ python setup.py install
========
Makefile
========
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 (in --user mode)
$ make uninstall # uninstall (needs pip)
$ make test # run tests
$ make clean # remove installation files

View File

@ -1,131 +1,22 @@
include .coveragerc
include .git-pre-commit
include .git-pre-commit
include .gitignore
include .travis.yml
include CREDITS
include DEVGUIDE.rst
include HISTORY.rst
include IDEAS
include INSTALL.rst
include LICENSE
include MANIFEST.in
include Makefile
include README.rst
include docs/Makefile
include docs/README
include docs/_static/copybutton.js
include docs/_static/css/custom.css
include docs/_static/favicon.ico
include docs/_static/sidebar.js
include docs/conf.py
include docs/index.rst
include docs/make.bat
include make.bat
include psutil/DEVNOTES
include psutil/__init__.py
include psutil/_common.py
include psutil/_compat.py
include psutil/_exceptions.py
include psutil/_psaix.py
include psutil/_psbsd.py
include psutil/_pslinux.py
include psutil/_psosx.py
include psutil/_psposix.py
include psutil/_pssunos.py
include psutil/_psutil_aix.c
include psutil/_psutil_bsd.c
include psutil/_psutil_common.c
include psutil/_psutil_common.h
include psutil/_psutil_linux.c
include psutil/_psutil_osx.c
include psutil/_psutil_posix.c
include psutil/_psutil_posix.h
include psutil/_psutil_sunos.c
include psutil/_psutil_windows.c
include psutil/_pswindows.py
include psutil/arch/aix/common.c
include psutil/arch/aix/common.h
include psutil/arch/aix/ifaddrs.c
include psutil/arch/aix/ifaddrs.h
include psutil/arch/aix/net_connections.c
include psutil/arch/aix/net_connections.h
include psutil/arch/aix/net_kernel_structs.h
include psutil/arch/freebsd/proc_socks.c
include psutil/arch/freebsd/proc_socks.h
include psutil/arch/freebsd/specific.c
include psutil/arch/freebsd/specific.h
include psutil/arch/freebsd/sys_socks.c
include psutil/arch/freebsd/sys_socks.h
include psutil/arch/netbsd/socks.c
include psutil/arch/netbsd/socks.h
include psutil/arch/netbsd/specific.c
include psutil/arch/netbsd/specific.h
include psutil/arch/openbsd/specific.c
include psutil/arch/openbsd/specific.h
include psutil/arch/osx/process_info.c
include psutil/arch/osx/process_info.h
include psutil/arch/solaris/environ.c
include psutil/arch/solaris/environ.h
include psutil/arch/solaris/v10/ifaddrs.c
include psutil/arch/solaris/v10/ifaddrs.h
include psutil/arch/windows/glpi.h
include psutil/arch/windows/inet_ntop.c
include psutil/arch/windows/inet_ntop.h
include psutil/arch/windows/ntextapi.h
include psutil/arch/windows/process_handles.c
include psutil/arch/windows/process_handles.h
include psutil/arch/windows/process_info.c
include psutil/arch/windows/process_info.h
include psutil/arch/windows/security.c
include psutil/arch/windows/security.h
include psutil/arch/windows/services.c
include psutil/arch/windows/services.h
include psutil/tests/README.rst
include psutil/tests/__init__.py
include psutil/tests/__main__.py
include psutil/tests/test_aix.py
include psutil/tests/test_bsd.py
include psutil/tests/test_connections.py
include psutil/tests/test_contracts.py
include psutil/tests/test_linux.py
include psutil/tests/test_memory_leaks.py
include psutil/tests/test_misc.py
include psutil/tests/test_osx.py
include psutil/tests/test_posix.py
include psutil/tests/test_process.py
include psutil/tests/test_sunos.py
include psutil/tests/test_system.py
include psutil/tests/test_unicode.py
include psutil/tests/test_windows.py
include scripts/battery.py
include scripts/cpu_distribution.py
include scripts/disk_usage.py
include scripts/fans.py
include scripts/free.py
include scripts/ifconfig.py
include scripts/internal/README
include scripts/internal/bench_oneshot.py
include scripts/internal/bench_oneshot_2.py
include scripts/internal/check_broken_links.py
include scripts/internal/download_exes.py
include scripts/internal/generate_manifest.py
include scripts/internal/print_announce.py
include scripts/internal/print_timeline.py
include scripts/internal/winmake.py
include scripts/iotop.py
include scripts/killall.py
include scripts/meminfo.py
include scripts/netstat.py
include scripts/nettop.py
include scripts/pidof.py
include scripts/pmap.py
include scripts/procinfo.py
include scripts/procsmem.py
include scripts/ps.py
include scripts/pstree.py
include scripts/sensors.py
include scripts/temperatures.py
include scripts/top.py
include scripts/who.py
include scripts/winservices.py
include Makefile
include MANIFEST.in
include README.rst
include setup.py
include TODO
include tox.ini
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*

View File

@ -1,269 +1,122 @@
# Shortcuts for various tasks (UNIX only).
# To use a specific Python version run: "make install PYTHON=python3.3"
# You can set the variables below from the command line.
# To use a specific Python version run:
# $ make install PYTHON=python3.3
PYTHON = python
TSCRIPT = psutil/tests/__main__.py
ARGS =
# List of nice-to-have dev libs.
DEPS = \
argparse \
check-manifest \
coverage \
flake8 \
futures \
ipaddress \
mock==1.0.1 \
pep8 \
perf \
pyflakes \
requests \
setuptools \
sphinx \
twine \
unittest2 \
wheel
# In not in a virtualenv, add --user options for install commands.
INSTALL_OPTS = `$(PYTHON) -c "import sys; print('' if hasattr(sys, 'real_prefix') else '--user')"`
TEST_PREFIX = PYTHONWARNINGS=all PSUTIL_TESTING=1 PSUTIL_DEBUG=1
# You can set these variables from the command line.
PYTHON = python
TSCRIPT = test/test_psutil.py
all: test
# ===================================================================
# Install
# ===================================================================
clean:
rm -f `find . -type f -name \*.py[co]`
rm -f `find . -type f -name \*.so`
rm -f `find . -type f -name .\*~`
rm -f `find . -type f -name \*.orig`
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
clean: ## Remove all build files.
rm -rf `find . -type d -name __pycache__ \
-o -type f -name \*.bak \
-o -type f -name \*.orig \
-o -type f -name \*.pyc \
-o -type f -name \*.pyd \
-o -type f -name \*.pyo \
-o -type f -name \*.rej \
-o -type f -name \*.so \
-o -type f -name \*.~ \
-o -type f -name \*\$testfn`
rm -rf \
*.core \
*.egg-info \
*\$testfn* \
.coverage \
.tox \
build/ \
dist/ \
docs/_build/ \
htmlcov/ \
tmp/
_:
build: _ ## Compile without installing.
# make sure setuptools is installed (needed for 'develop' / edit mode)
$(PYTHON) -c "import setuptools"
PYTHONWARNINGS=all $(PYTHON) setup.py build
@# copies compiled *.so files in ./psutil directory in order to allow
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.
PYTHONWARNINGS=all $(PYTHON) setup.py build_ext -i
rm -rf tmp
$(PYTHON) -c "import psutil" # make sure it actually worked
$(PYTHON) setup.py build_ext -i
install: ## Install this package as current user in "edit" mode.
${MAKE} build
PYTHONWARNINGS=all $(PYTHON) setup.py develop $(INSTALL_OPTS)
rm -rf tmp
# 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 \
uninstall: ## Uninstall this package via pip.
install: build
$(PYTHON) setup.py install --user
uninstall:
cd ..; $(PYTHON) -m pip uninstall -y -v psutil
install-pip: ## Install pip (no-op if already installed).
$(PYTHON) -c \
"import sys, ssl, os, pkgutil, tempfile, atexit; \
sys.exit(0) if pkgutil.find_loader('pip') else None; \
pyexc = 'from urllib.request import urlopen' if sys.version_info[0] == 3 else 'from urllib2 import urlopen'; \
exec(pyexc); \
ctx = ssl._create_unverified_context() if hasattr(ssl, '_create_unverified_context') else None; \
kw = dict(context=ctx) if ctx else {}; \
req = urlopen('https://bootstrap.pypa.io/get-pip.py', **kw); \
data = req.read(); \
f = tempfile.NamedTemporaryFile(suffix='.py'); \
atexit.register(f.close); \
f.write(data); \
f.flush(); \
print('downloaded %s' % f.name); \
code = os.system('%s %s --user' % (sys.executable, f.name)); \
f.close(); \
sys.exit(code);"
test: install
$(PYTHON) $(TSCRIPT)
setup-dev-env: ## Install GIT hooks, pip, test deps (also upgrades them).
${MAKE} install-git-hooks
${MAKE} install-pip
$(PYTHON) -m pip install $(INSTALL_OPTS) --upgrade pip
$(PYTHON) -m pip install $(INSTALL_OPTS) --upgrade $(DEPS)
test-process: install
$(PYTHON) -m unittest -v test.test_psutil.TestProcess
# ===================================================================
# Tests
# ===================================================================
test-system: install
$(PYTHON) -m unittest -v test.test_psutil.TestSystemAPIs
test: ## Run all tests.
${MAKE} install
$(TEST_PREFIX) $(PYTHON) $(TSCRIPT)
test-memleaks: install
$(PYTHON) test/test_memory_leaks.py
test-process: ## Run process-related API tests.
${MAKE} install
$(TEST_PREFIX) $(PYTHON) -m unittest -v psutil.tests.test_process
# 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: install
@$(PYTHON) -m nose test/test_psutil.py test/_* --nocapture -v -m $(filter-out $@,$(MAKECMDGOALS))
test-system: ## Run system-related API tests.
${MAKE} install
$(TEST_PREFIX) $(PYTHON) -m unittest -v psutil.tests.test_system
# 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))
test-misc: ## Run miscellaneous tests.
${MAKE} install
$(TEST_PREFIX) $(PYTHON) psutil/tests/test_misc.py
test-unicode: ## Test APIs dealing with strings.
${MAKE} install
$(TEST_PREFIX) $(PYTHON) psutil/tests/test_unicode.py
test-contracts: ## APIs sanity tests.
${MAKE} install
$(TEST_PREFIX) $(PYTHON) psutil/tests/test_contracts.py
test-connections: ## Test net_connections() and Process.connections().
${MAKE} install
$(TEST_PREFIX) $(PYTHON) psutil/tests/test_connections.py
test-posix: ## POSIX specific tests.
${MAKE} install
$(TEST_PREFIX) $(PYTHON) psutil/tests/test_posix.py
test-platform: ## Run specific platform tests only.
${MAKE} install
$(TEST_PREFIX) $(PYTHON) psutil/tests/test_`$(PYTHON) -c 'import psutil; print([x.lower() for x in ("LINUX", "BSD", "OSX", "SUNOS", "WINDOWS", "AIX") if getattr(psutil, x)][0])'`.py
test-memleaks: ## Memory leak tests.
${MAKE} install
$(TEST_PREFIX) $(PYTHON) psutil/tests/test_memory_leaks.py
test-by-name: ## e.g. make test-by-name ARGS=psutil.tests.test_system.TestSystemAPIs
${MAKE} install
@$(TEST_PREFIX) $(PYTHON) -m unittest -v $(ARGS)
test-coverage: ## Run test coverage.
${MAKE} install
coverage: install
# Note: coverage options are controlled by .coveragerc file
rm -rf .coverage htmlcov
$(TEST_PREFIX) $(PYTHON) -m coverage run $(TSCRIPT)
$(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
# ===================================================================
# Linters
# ===================================================================
pep8: ## PEP8 linter.
pep8:
@git ls-files | grep \\.py$ | xargs $(PYTHON) -m pep8
pyflakes: ## Pyflakes linter.
pyflakes:
@export PYFLAKES_NODOCTEST=1 && \
git ls-files | grep \\.py$ | xargs $(PYTHON) -m pyflakes
flake8: ## flake8 linter.
flake8:
@git ls-files | grep \\.py$ | xargs $(PYTHON) -m flake8
# ===================================================================
# GIT
# ===================================================================
git-tag-release: ## Git-tag a new release.
git tag -a release-`python -c "import setup; print(setup.get_version())"` -m `git rev-list HEAD --count`:`git rev-parse --short HEAD`
git push --follow-tags
install-git-hooks: ## Install GIT pre-commit hook.
ln -sf ../../.git-pre-commit .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
# ===================================================================
# Distribution
# ===================================================================
# --- create
sdist: ## Create tar.gz source distribution.
${MAKE} generate-manifest
$(PYTHON) setup.py sdist
wheel: ## Generate wheel.
$(PYTHON) setup.py bdist_wheel
win-download-wheels: ## Download wheels hosted on appveyor.
$(TEST_PREFIX) $(PYTHON) scripts/internal/download_exes.py --user giampaolo --project psutil
# --- upload
upload-src: ## Upload source tarball on https://pypi.python.org/pypi/psutil.
${MAKE} sdist
# Upload source tarball on https://pypi.python.org/pypi/psutil.
upload-src: clean
$(PYTHON) setup.py sdist upload
upload-win-wheels: ## Upload wheels in dist/* directory on PYPI.
$(PYTHON) -m twine upload dist/*.whl
# Build and upload doc on https://pythonhosted.org/psutil/.
# Requires "pip install sphinx-pypi-upload".
upload-doc:
cd docs; make html
$(PYTHON) setup.py upload_sphinx --upload-dir=docs/_build/html
# --- others
# git-tag a new release
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"
pre-release: ## Check if we're ready to produce a new release.
rm -rf dist
${MAKE} install
${MAKE} generate-manifest
git diff MANIFEST.in > /dev/null # ...otherwise 'git diff-index HEAD' will complain
${MAKE} win-download-wheels
${MAKE} sdist
$(PYTHON) -c \
"from psutil import __version__ as ver; \
doc = open('docs/index.rst').read(); \
history = open('HISTORY.rst').read(); \
assert ver in doc, '%r not in docs/index.rst' % ver; \
assert ver in history, '%r not in HISTORY.rst' % ver; \
assert 'XXXX' not in history, 'XXXX in HISTORY.rst';"
$(PYTHON) -c "import subprocess, sys; out = subprocess.check_output('git diff --quiet && git diff --cached --quiet', shell=True).strip(); sys.exit('there are uncommitted changes:\n%s' % out) if out else 0 ;"
release: ## Create a release (down/uploads tar.gz, wheels, git tag release).
${MAKE} pre-release
$(PYTHON) -m twine upload dist/* # upload tar.gz and Windows wheels on PYPI
${MAKE} git-tag-release
print-announce: ## Print announce of new release.
@$(TEST_PREFIX) $(PYTHON) scripts/internal/print_announce.py
print-timeline: ## Print releases' timeline.
@$(TEST_PREFIX) $(PYTHON) scripts/internal/print_timeline.py
check-manifest: ## Inspect MANIFEST.in file.
$(PYTHON) -m check_manifest -v $(ARGS)
generate-manifest: ## Generates MANIFEST.in file.
$(PYTHON) scripts/internal/generate_manifest.py > MANIFEST.in
# ===================================================================
# Misc
# ===================================================================
grep-todos: ## Look for TODOs in the source files.
git grep -EIn "TODO|FIXME|XXX"
bench-oneshot: ## Benchmarks for oneshot() ctx manager (see #799).
${MAKE} install
$(TEST_PREFIX) $(PYTHON) scripts/internal/bench_oneshot.py
bench-oneshot-2: ## Same as above but using perf module (supposed to be more precise)
${MAKE} install
$(TEST_PREFIX) $(PYTHON) scripts/internal/bench_oneshot_2.py
check-broken-links: ## Look for broken links in source files.
git ls-files | xargs $(PYTHON) -Wa scripts/internal/check_broken_links.py
help: ## Display callable targets.
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
# install GIT pre-commit hook
install-git-hooks:
ln -sf ../../.git-pre-commit .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit

View File

@ -1,29 +1,28 @@
Metadata-Version: 1.1
Name: psutil
Version: 5.4.3
Summary: Cross-platform lib for process and system monitoring in Python.
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@gmail.com
Author-email: g.rodola <at> gmail <dot> com
License: BSD
Description-Content-Type: UNKNOWN
Description: .. image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux%20/%20OSX
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://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows
.. 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/github/giampaolo/psutil/badge.svg?branch=master
.. 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://readthedocs.org/projects/psutil/badge/?version=latest
:target: http://psutil.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
.. image:: https://img.shields.io/pypi/v/psutil.svg?label=pypi
.. image:: https://img.shields.io/pypi/v/psutil.svg
:target: https://pypi.python.org/pypi/psutil/
:alt: Latest version
@ -31,6 +30,10 @@ Description: .. image:: https://img.shields.io/travis/giampaolo/psutil/master.sv
: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
@ -40,8 +43,8 @@ Description: .. image:: https://img.shields.io/travis/giampaolo/psutil/master.sv
===========
- `Home page <https://github.com/giampaolo/psutil>`_
- `Install <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
- `Documentation <http://psutil.readthedocs.io>`_
- `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>`_
@ -52,70 +55,39 @@ Description: .. image:: https://img.shields.io/travis/giampaolo/psutil/master.sv
Summary
=======
psutil (process and system utilities) is a cross-platform library for
psutil (python system and process utilities) is a cross-platform library for
retrieving information on **running processes** and **system utilization**
(CPU, memory, disks, network, sensors) 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 UNIX command line tools such as:
ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice, ionice, iostat,
iotop, uptime, pidof, tty, taskset, pmap.
psutil currently supports the following platforms:
- **Linux**
- **Windows**
- **OSX**,
- **FreeBSD, OpenBSD**, **NetBSD**
- **Sun Solaris**
- **AIX**
...both **32-bit** and **64-bit** architectures, with Python
versions from **2.6 to 3.6**.
(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:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/top-small.png |
| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/top.png |
+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
| .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap-small.png |
| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap.png |
+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
.. image:: http://psutil.googlecode.com/svn/wiki/images/top-thumb.png
:target: http://psutil.googlecode.com/svn/wiki/images/top.png
:alt: top
Also see `scripts directory <https://github.com/giampaolo/psutil/tree/master/scripts>`__
and `doc recipes <http://psutil.readthedocs.io/#recipes/>`__.
.. image:: http://psutil.googlecode.com/svn/wiki/images/nettop-thumb.png
:target: http://psutil.googlecode.com/svn/wiki/images/nettop.png
:alt: nettop
=====================
Projects using psutil
=====================
.. image:: http://psutil.googlecode.com/svn/wiki/images/iotop-thumb.png
:target: http://psutil.googlecode.com/svn/wiki/images/iotop.png
:alt: iotop
At the time of writing psutil has roughly
`2.9 milion downloads <https://github.com/giampaolo/psutil/issues/1053#issuecomment-340166262>`__
per month and there are over
`6000 open source projects <https://libraries.io/pypi/psutil/dependent_repositories?page=1>`__
on github which depend from psutil.
Here's some I find particularly interesting:
See also:
- https://github.com/facebook/osquery/
- https://github.com/nicolargo/glances
- https://github.com/google/grr
- https://github.com/Jahaja/psdash
- https://github.com/ajenti/ajenti
- https://github.com/home-assistant/home-assistant/
========
Portings
========
- Go: https://github.com/shirou/gopsutil
- C: https://github.com/hamon-in/cpslib
- Node: https://github.com/christkv/node-psutil
- Rust: https://github.com/borntyping/rust-psutil
- Ruby: https://github.com/spacewander/posixpsutil
- Nim: https://github.com/johnscillieri/psutil-nim
* https://github.com/nicolargo/glances
* https://github.com/google/grr
* https://github.com/Jahaja/psdash
==============
Example usages
@ -144,6 +116,7 @@ Description: .. image:: https://img.shields.io/travis/giampaolo/psutil/master.sv
[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)
...
@ -156,21 +129,14 @@ Description: .. image:: https://img.shields.io/travis/giampaolo/psutil/master.sv
>>> psutil.cpu_count(logical=False)
2
>>>
>>> psutil.cpu_stats()
scpustats(ctx_switches=20455687, interrupts=6598984, soft_interrupts=2134212, syscalls=0)
>>>
>>> psutil.cpu_freq()
scpufreq(current=931.42925, min=800.0, max=3500.0)
>>>
Memory
======
.. code-block:: python
>>> import psutil
>>> psutil.virtual_memory()
svmem(total=10367352832, available=6472179712, percent=37.6, used=8186245120, free=2181107712, active=4748992512, inactive=2758115328, buffers=790724608, cached=3500347392, shared=787554304)
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)
>>>
@ -180,7 +146,6 @@ Description: .. image:: https://img.shields.io/travis/giampaolo/psutil/master.sv
.. code-block:: python
>>> import psutil
>>> psutil.disk_partitions()
[sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')]
@ -189,7 +154,7 @@ Description: .. image:: https://img.shields.io/travis/giampaolo/psutil/master.sv
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, read_merged_count=619166, write_merged_count=812396, busy_time=4523412)
sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220032, write_bytes=24081764352, read_time=5023392, write_time=63199568)
>>>
Network
@ -197,62 +162,37 @@ Description: .. image:: https://img.shields.io/travis/giampaolo/psutil/master.sv
.. code-block:: python
>>> import psutil
>>> 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()
[sconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED', pid=1254),
sconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING', pid=2987),
sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=60759), raddr=addr(ip='72.14.234.104', port=80), status='ESTABLISHED', pid=None),
sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=51314), raddr=addr(ip='72.14.234.83', port=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', ptp=None),
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)],
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
{'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)}
>>>
Sensors
=======
.. code-block:: python
>>> import psutil
>>> psutil.sensors_temperatures()
{'acpitz': [shwtemp(label='', current=47.0, high=103.0, critical=103.0)],
'asus': [shwtemp(label='', current=47.0, high=None, critical=None)],
'coretemp': [shwtemp(label='Physical id 0', current=52.0, high=100.0, critical=100.0),
shwtemp(label='Core 0', current=45.0, high=100.0, critical=100.0),
shwtemp(label='Core 1', current=52.0, high=100.0, critical=100.0),
shwtemp(label='Core 2', current=45.0, high=100.0, critical=100.0),
shwtemp(label='Core 3', current=47.0, high=100.0, critical=100.0)]}
>>>
>>> psutil.sensors_fans()
{'asus': [sfan(label='cpu_fan', current=3200)]}
>>>
>>> psutil.sensors_battery()
sbattery(percent=93, secsleft=16628, power_plugged=False)
>>>
Other system info
=================
.. code-block:: python
>>> import psutil
>>> psutil.users()
[suser(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0, pid=1352),
suser(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0, pid=1788)]
[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
@ -265,10 +205,12 @@ Description: .. image:: https://img.shields.io/travis/giampaolo/psutil/master.sv
>>> 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]
[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()
@ -280,16 +222,6 @@ Description: .. image:: https://img.shields.io/travis/giampaolo/psutil/master.sv
>>> p.cmdline()
['/usr/bin/python', 'main.py']
>>>
>>> p.pid
7055
>>> p.ppid()
7054
>>> p.parent()
<psutil.Process(pid=7054, name='bash') at 140008329539408>
>>> p.children()
[<psutil.Process(pid=8031, name='python') at 14020832451977>,
<psutil.Process(pid=8044, name='python') at 19229444921932>]
>>>
>>> p.status()
'running'
>>> p.username()
@ -305,41 +237,39 @@ Description: .. image:: https://img.shields.io/travis/giampaolo/psutil/master.sv
pgids(real=1000, effective=1000, saved=1000)
>>>
>>> p.cpu_times()
pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1)
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, 1]) # set
>>> p.cpu_num()
1
>>> p.cpu_affinity([0]) # set
>>>
>>> p.memory_percent()
0.63423
>>>
>>> p.memory_info()
pmem(rss=10915840, vms=67608576, shared=3313664, text=2310144, lib=0, data=7262208, dirty=0)
>>> p.memory_full_info() # "real" USS memory usage (Linux, OSX, Win only)
pfullmem(rss=10199040, vms=52133888, shared=3887104, text=2867200, lib=0, data=5967872, dirty=0, uss=6545408, pss=6872064, swap=0)
>>> p.memory_percent()
0.7823
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/x8664-linux-gnu/libutil-2.15.so', rss=32768, size=2125824, pss=32768, shared_clean=0, shared_dirty=0, private_clean=20480, private_dirty=12288, referenced=32768, anonymous=12288, swap=0),
pmmap_grouped(path='/lib/x8664-linux-gnu/libc-2.15.so', rss=3821568, size=3842048, pss=3821568, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=3821568, referenced=3575808, anonymous=3821568, swap=0),
pmmap_grouped(path='/lib/x8664-linux-gnu/libcrypto.so.0.1', rss=34124, rss=32768, size=2134016, pss=15360, shared_clean=24576, shared_dirty=0, private_clean=0, private_dirty=8192, referenced=24576, anonymous=8192, swap=0),
pmmap_grouped(path='[heap]', rss=32768, size=139264, pss=32768, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=32768, referenced=32768, anonymous=32768, swap=0),
pmmap_grouped(path='[stack]', rss=2465792, size=2494464, pss=2465792, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=2465792, referenced=2277376, anonymous=2465792, swap=0),
[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, read_chars=456232, write_chars=517543)
pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632)
>>>
>>> p.open_files()
[popenfile(path='/home/giampaolo/svn/psutil/setup.py', fd=3, position=0, mode='r', flags=32768),
popenfile(path='/var/log/monitd', fd=4, position=235542, mode='a', flags=33793)]
[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=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED'),
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING'),
pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=60759), raddr=addr(ip='72.14.234.104', port=80), status='ESTABLISHED'),
pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=51314), raddr=addr(ip='72.14.234.83', port=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
@ -366,15 +296,6 @@ Description: .. image:: https://img.shields.io/travis/giampaolo/psutil/master.sv
>>> p.rlimit(psutil.RLIMIT_NOFILE)
(5, 5)
>>>
>>> p.environ()
{'LC_PAPER': 'it_IT.UTF-8', 'SHELL': '/bin/bash', 'GREP_OPTIONS': '--color=auto',
'XDG_CONFIG_DIRS': '/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg', 'COLORTERM': 'gnome-terminal',
...}
>>>
>>> p.as_dict()
{'status': 'running', 'num_ctx_switches': pctxsw(voluntary=63, involuntary=1), 'pid': 5457, ...}
>>> p.is_running()
True
>>> p.suspend()
>>> p.resume()
>>>
@ -398,87 +319,81 @@ Description: .. image:: https://img.shields.io/travis/giampaolo/psutil/master.sv
.. code-block:: python
>>> import psutil
>>> for proc in psutil.process_iter(attrs=['pid', 'name']):
... print(proc.info)
>>> for p in psutil.process_iter():
... print(p)
...
{'pid': 1, 'name': 'systemd'}
{'pid': 2, 'name': 'kthreadd'}
{'pid': 3, 'name': 'ksoftirqd/0'}
psutil.Process(pid=1, name='init')
psutil.Process(pid=2, name='kthreadd')
psutil.Process(pid=3, name='ksoftirqd/0')
...
>>>
>>> psutil.pid_exists(3)
True
>>>
>>> def on_terminate(proc):
... print("process {} terminated".format(proc))
...
>>> # waits for multiple processes to terminate
>>> gone, alive = psutil.wait_procs(procs_list, timeout=3, callback=on_terminate)
>>> gone, alive = psutil.wait_procs(procs_list, 3, callback=on_terminate)
>>>
Popen wrapper:
.. code-block:: python
>>> import psutil
>>> from subprocess import PIPE
>>> p = psutil.Popen(["/usr/bin/python", "-c", "print('hello')"], stdout=PIPE)
>>> p.name()
'python'
>>> p.username()
'giampaolo'
>>> p.communicate()
('hello\n', None)
>>> p.wait(timeout=2)
0
>>>
Windows services
================
.. code-block:: python
>>> list(psutil.win_service_iter())
[<WindowsService(name='AeLookupSvc', display_name='Application Experience') at 38850096>,
<WindowsService(name='ALG', display_name='Application Layer Gateway Service') at 38850128>,
<WindowsService(name='APNMCP', display_name='Ask Update Service') at 38850160>,
<WindowsService(name='AppIDSvc', display_name='Application Identity') at 38850192>,
...]
>>> s = psutil.win_service_get('alg')
>>> s.as_dict()
{'binpath': 'C:\\Windows\\System32\\alg.exe',
'description': 'Provides support for 3rd party protocol plug-ins for Internet Connection Sharing',
'display_name': 'Application Layer Gateway Service',
'name': 'alg',
'pid': None,
'start_type': 'manual',
'status': 'stopped',
'username': 'NT AUTHORITY\\LocalService'}
Other samples
=============
See `doc recipes <http://psutil.readthedocs.io/#recipes>`__.
======
Author
Donate
======
psutil was created and is maintained by
`Giampaolo Rodola' <http://grodola.blogspot.com/p/about.html>`__.
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 <http://grodola.blogspot.com/p/about.html>`__) some money.
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 <https://www.linkedin.com/in/grodola>`_.
Don't want to donate money? Then maybe you could `write me a recommendation on Linkedin <http://www.linkedin.com/in/grodola>`_.
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,smem
============
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
@ -492,9 +407,6 @@ 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 :: BSD :: NetBSD
Classifier: Operating System :: POSIX :: BSD :: OpenBSD
Classifier: Operating System :: POSIX :: BSD
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: POSIX :: SunOS/Solaris
Classifier: Operating System :: POSIX
@ -503,9 +415,11 @@ 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 :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Programming Language :: Python
@ -516,6 +430,5 @@ Classifier: Topic :: System :: Hardware
Classifier: Topic :: System :: Monitoring
Classifier: Topic :: System :: Networking :: Monitoring
Classifier: Topic :: System :: Networking
Classifier: Topic :: System :: Operating System
Classifier: Topic :: System :: Systems Administration
Classifier: Topic :: Utilities

View File

@ -1,20 +1,20 @@
.. image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux%20/%20OSX
.. 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://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows
.. 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/github/giampaolo/psutil/badge.svg?branch=master
.. 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://readthedocs.org/projects/psutil/badge/?version=latest
:target: http://psutil.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
.. image:: https://img.shields.io/pypi/v/psutil.svg?label=pypi
.. image:: https://img.shields.io/pypi/v/psutil.svg
:target: https://pypi.python.org/pypi/psutil/
:alt: Latest version
@ -22,6 +22,10 @@
: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
@ -31,8 +35,8 @@ Quick links
===========
- `Home page <https://github.com/giampaolo/psutil>`_
- `Install <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
- `Documentation <http://psutil.readthedocs.io>`_
- `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>`_
@ -43,70 +47,39 @@ Quick links
Summary
=======
psutil (process and system utilities) is a cross-platform library for
psutil (python system and process utilities) is a cross-platform library for
retrieving information on **running processes** and **system utilization**
(CPU, memory, disks, network, sensors) 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 UNIX command line tools such as:
ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice, ionice, iostat,
iotop, uptime, pidof, tty, taskset, pmap.
psutil currently supports the following platforms:
- **Linux**
- **Windows**
- **OSX**,
- **FreeBSD, OpenBSD**, **NetBSD**
- **Sun Solaris**
- **AIX**
...both **32-bit** and **64-bit** architectures, with Python
versions from **2.6 to 3.6**.
(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:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/top-small.png |
| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/top.png |
+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
| .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap-small.png |
| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap.png |
+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
.. image:: http://psutil.googlecode.com/svn/wiki/images/top-thumb.png
:target: http://psutil.googlecode.com/svn/wiki/images/top.png
:alt: top
Also see `scripts directory <https://github.com/giampaolo/psutil/tree/master/scripts>`__
and `doc recipes <http://psutil.readthedocs.io/#recipes/>`__.
.. image:: http://psutil.googlecode.com/svn/wiki/images/nettop-thumb.png
:target: http://psutil.googlecode.com/svn/wiki/images/nettop.png
:alt: nettop
=====================
Projects using psutil
=====================
.. image:: http://psutil.googlecode.com/svn/wiki/images/iotop-thumb.png
:target: http://psutil.googlecode.com/svn/wiki/images/iotop.png
:alt: iotop
At the time of writing psutil has roughly
`2.9 milion downloads <https://github.com/giampaolo/psutil/issues/1053#issuecomment-340166262>`__
per month and there are over
`6000 open source projects <https://libraries.io/pypi/psutil/dependent_repositories?page=1>`__
on github which depend from psutil.
Here's some I find particularly interesting:
See also:
- https://github.com/facebook/osquery/
- https://github.com/nicolargo/glances
- https://github.com/google/grr
- https://github.com/Jahaja/psdash
- https://github.com/ajenti/ajenti
- https://github.com/home-assistant/home-assistant/
========
Portings
========
- Go: https://github.com/shirou/gopsutil
- C: https://github.com/hamon-in/cpslib
- Node: https://github.com/christkv/node-psutil
- Rust: https://github.com/borntyping/rust-psutil
- Ruby: https://github.com/spacewander/posixpsutil
- Nim: https://github.com/johnscillieri/psutil-nim
* https://github.com/nicolargo/glances
* https://github.com/google/grr
* https://github.com/Jahaja/psdash
==============
Example usages
@ -135,6 +108,7 @@ CPU
[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)
...
@ -147,21 +121,14 @@ CPU
>>> psutil.cpu_count(logical=False)
2
>>>
>>> psutil.cpu_stats()
scpustats(ctx_switches=20455687, interrupts=6598984, soft_interrupts=2134212, syscalls=0)
>>>
>>> psutil.cpu_freq()
scpufreq(current=931.42925, min=800.0, max=3500.0)
>>>
Memory
======
.. code-block:: python
>>> import psutil
>>> psutil.virtual_memory()
svmem(total=10367352832, available=6472179712, percent=37.6, used=8186245120, free=2181107712, active=4748992512, inactive=2758115328, buffers=790724608, cached=3500347392, shared=787554304)
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)
>>>
@ -171,7 +138,6 @@ Disks
.. code-block:: python
>>> import psutil
>>> psutil.disk_partitions()
[sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')]
@ -180,7 +146,7 @@ Disks
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, read_merged_count=619166, write_merged_count=812396, busy_time=4523412)
sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220032, write_bytes=24081764352, read_time=5023392, write_time=63199568)
>>>
Network
@ -188,62 +154,37 @@ Network
.. code-block:: python
>>> import psutil
>>> 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()
[sconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED', pid=1254),
sconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING', pid=2987),
sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=60759), raddr=addr(ip='72.14.234.104', port=80), status='ESTABLISHED', pid=None),
sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=51314), raddr=addr(ip='72.14.234.83', port=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', ptp=None),
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)],
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
{'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)}
>>>
Sensors
=======
.. code-block:: python
>>> import psutil
>>> psutil.sensors_temperatures()
{'acpitz': [shwtemp(label='', current=47.0, high=103.0, critical=103.0)],
'asus': [shwtemp(label='', current=47.0, high=None, critical=None)],
'coretemp': [shwtemp(label='Physical id 0', current=52.0, high=100.0, critical=100.0),
shwtemp(label='Core 0', current=45.0, high=100.0, critical=100.0),
shwtemp(label='Core 1', current=52.0, high=100.0, critical=100.0),
shwtemp(label='Core 2', current=45.0, high=100.0, critical=100.0),
shwtemp(label='Core 3', current=47.0, high=100.0, critical=100.0)]}
>>>
>>> psutil.sensors_fans()
{'asus': [sfan(label='cpu_fan', current=3200)]}
>>>
>>> psutil.sensors_battery()
sbattery(percent=93, secsleft=16628, power_plugged=False)
>>>
Other system info
=================
.. code-block:: python
>>> import psutil
>>> psutil.users()
[suser(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0, pid=1352),
suser(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0, pid=1788)]
[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
@ -256,10 +197,12 @@ Process management
>>> 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]
[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()
@ -271,16 +214,6 @@ Process management
>>> p.cmdline()
['/usr/bin/python', 'main.py']
>>>
>>> p.pid
7055
>>> p.ppid()
7054
>>> p.parent()
<psutil.Process(pid=7054, name='bash') at 140008329539408>
>>> p.children()
[<psutil.Process(pid=8031, name='python') at 14020832451977>,
<psutil.Process(pid=8044, name='python') at 19229444921932>]
>>>
>>> p.status()
'running'
>>> p.username()
@ -296,41 +229,39 @@ Process management
pgids(real=1000, effective=1000, saved=1000)
>>>
>>> p.cpu_times()
pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1)
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, 1]) # set
>>> p.cpu_num()
1
>>> p.cpu_affinity([0]) # set
>>>
>>> p.memory_percent()
0.63423
>>>
>>> p.memory_info()
pmem(rss=10915840, vms=67608576, shared=3313664, text=2310144, lib=0, data=7262208, dirty=0)
>>> p.memory_full_info() # "real" USS memory usage (Linux, OSX, Win only)
pfullmem(rss=10199040, vms=52133888, shared=3887104, text=2867200, lib=0, data=5967872, dirty=0, uss=6545408, pss=6872064, swap=0)
>>> p.memory_percent()
0.7823
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/x8664-linux-gnu/libutil-2.15.so', rss=32768, size=2125824, pss=32768, shared_clean=0, shared_dirty=0, private_clean=20480, private_dirty=12288, referenced=32768, anonymous=12288, swap=0),
pmmap_grouped(path='/lib/x8664-linux-gnu/libc-2.15.so', rss=3821568, size=3842048, pss=3821568, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=3821568, referenced=3575808, anonymous=3821568, swap=0),
pmmap_grouped(path='/lib/x8664-linux-gnu/libcrypto.so.0.1', rss=34124, rss=32768, size=2134016, pss=15360, shared_clean=24576, shared_dirty=0, private_clean=0, private_dirty=8192, referenced=24576, anonymous=8192, swap=0),
pmmap_grouped(path='[heap]', rss=32768, size=139264, pss=32768, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=32768, referenced=32768, anonymous=32768, swap=0),
pmmap_grouped(path='[stack]', rss=2465792, size=2494464, pss=2465792, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=2465792, referenced=2277376, anonymous=2465792, swap=0),
[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, read_chars=456232, write_chars=517543)
pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632)
>>>
>>> p.open_files()
[popenfile(path='/home/giampaolo/svn/psutil/setup.py', fd=3, position=0, mode='r', flags=32768),
popenfile(path='/var/log/monitd', fd=4, position=235542, mode='a', flags=33793)]
[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=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED'),
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING'),
pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=60759), raddr=addr(ip='72.14.234.104', port=80), status='ESTABLISHED'),
pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=51314), raddr=addr(ip='72.14.234.83', port=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
@ -357,15 +288,6 @@ Process management
>>> p.rlimit(psutil.RLIMIT_NOFILE)
(5, 5)
>>>
>>> p.environ()
{'LC_PAPER': 'it_IT.UTF-8', 'SHELL': '/bin/bash', 'GREP_OPTIONS': '--color=auto',
'XDG_CONFIG_DIRS': '/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg', 'COLORTERM': 'gnome-terminal',
...}
>>>
>>> p.as_dict()
{'status': 'running', 'num_ctx_switches': pctxsw(voluntary=63, involuntary=1), 'pid': 5457, ...}
>>> p.is_running()
True
>>> p.suspend()
>>> p.resume()
>>>
@ -389,82 +311,76 @@ Further process APIs
.. code-block:: python
>>> import psutil
>>> for proc in psutil.process_iter(attrs=['pid', 'name']):
... print(proc.info)
>>> for p in psutil.process_iter():
... print(p)
...
{'pid': 1, 'name': 'systemd'}
{'pid': 2, 'name': 'kthreadd'}
{'pid': 3, 'name': 'ksoftirqd/0'}
psutil.Process(pid=1, name='init')
psutil.Process(pid=2, name='kthreadd')
psutil.Process(pid=3, name='ksoftirqd/0')
...
>>>
>>> psutil.pid_exists(3)
True
>>>
>>> def on_terminate(proc):
... print("process {} terminated".format(proc))
...
>>> # waits for multiple processes to terminate
>>> gone, alive = psutil.wait_procs(procs_list, timeout=3, callback=on_terminate)
>>> gone, alive = psutil.wait_procs(procs_list, 3, callback=on_terminate)
>>>
Popen wrapper:
.. code-block:: python
>>> import psutil
>>> from subprocess import PIPE
>>> p = psutil.Popen(["/usr/bin/python", "-c", "print('hello')"], stdout=PIPE)
>>> p.name()
'python'
>>> p.username()
'giampaolo'
>>> p.communicate()
('hello\n', None)
>>> p.wait(timeout=2)
0
>>>
Windows services
================
.. code-block:: python
>>> list(psutil.win_service_iter())
[<WindowsService(name='AeLookupSvc', display_name='Application Experience') at 38850096>,
<WindowsService(name='ALG', display_name='Application Layer Gateway Service') at 38850128>,
<WindowsService(name='APNMCP', display_name='Ask Update Service') at 38850160>,
<WindowsService(name='AppIDSvc', display_name='Application Identity') at 38850192>,
...]
>>> s = psutil.win_service_get('alg')
>>> s.as_dict()
{'binpath': 'C:\\Windows\\System32\\alg.exe',
'description': 'Provides support for 3rd party protocol plug-ins for Internet Connection Sharing',
'display_name': 'Application Layer Gateway Service',
'name': 'alg',
'pid': None,
'start_type': 'manual',
'status': 'stopped',
'username': 'NT AUTHORITY\\LocalService'}
Other samples
=============
See `doc recipes <http://psutil.readthedocs.io/#recipes>`__.
======
Author
Donate
======
psutil was created and is maintained by
`Giampaolo Rodola' <http://grodola.blogspot.com/p/about.html>`__.
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 <http://grodola.blogspot.com/p/about.html>`__) some money.
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 <https://www.linkedin.com/in/grodola>`_.
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>`_

167
third_party/python/psutil/TODO vendored Normal file
View File

@ -0,0 +1,167 @@
TODO
====
A collection of ideas and notes about stuff to implement in future versions.
"#NNN" occurrences refer to bug tracker issues at:
https://github.com/giampaolo/psutil/issues
HIGHER PRIORITY
===============
* OpenBSD support.
* #371: CPU temperature (apparently OSX and Linux only; on Linux it requires
lm-sensors lib).
* #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; 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
==============
* #355: Android support.
* #276: GNU/Hurd support.
* #429: NetBSD support.
* DragonFlyBSD support?
* AIX support?
* examples/taskmgr-gui.py (using tk).
* system-wide number of open file descriptors:
* https://jira.hyperic.com/browse/SIGAR-30
* http://www.netadmintools.com/part295.html
* Number of system threads.
* Windows: http://msdn.microsoft.com/en-us/library/windows/desktop/ms684824(v=vs.85).aspx
* #357: what CPU a process is on.
* 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()
killall-> (actual script)
tty -> psutil.Process.terminal()
who -> psutil.users()
DEBATABLE
=========
* 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).
* [Linux]: process cgroups (http://en.wikipedia.org/wiki/Cgroups). They look
similar to prlimit() in terms of functionality but uglier (they should allow
limiting per-process network IO resources though, which is great). Needs
further reading.
* Should we expose OS constants (psutil.WINDOWS, psutil.OSX etc.)?
* Python 3.3. exposed different sched.h functions:
http://docs.python.org/dev/whatsnew/3.3.html#os
http://bugs.python.org/issue12655
http://docs.python.org/dev/library/os.html#interface-to-the-scheduler
It might be worth to take a look and figure out whether we can include some
of those in psutil.
Also, we can probably reimplement wait_pid() on POSIX which is currently
implemented as a busy-loop.
* 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
- AccessDenied inherits from PermissionError
- TimeoutExpired inherits from TimeoutError (debatable)
See: http://docs.python.org/3/library/exceptions.html#os-exceptions
* Process.threads() might grow an extra "id" parameter so that it can be
used as such:
>>> p = psutil.Process(os.getpid())
>>> p.threads(id=psutil.current_thread_id())
thread(id=2539, user_time=0.03, system_time=0.02)
>>>
Note: this leads to questions such as "should we have a custom NoSuchThread
exception? Also see issue #418.
Note #2: this would work with os.getpid() only.
psutil.current_thread_id() might be desirable as per issue #418 though.
* should psutil.TimeoutExpired exception have a 'msg' kwarg similar to
NoSuchProcess and AccessDenied? Not that we need it, but currently we
cannot raise a TimeoutExpired exception with a specific error string.
* process_iter() might grow an "attrs" parameter similar to Process.as_dict()
invoke the necessary methods and include the results into a "cache"
attribute attached to the returned Process instances so that one can avoid
catching NSP and AccessDenied:
for p in process_iter(attrs=['cpu_percent']):
print(p.cache['cpu_percent'])
This also leads questions as whether we should introduce a sorting order.
* round Process.memory_percent() result?
* #550: number of threads per core.
* Have psutil.Process().cpu_affinity([]) be an alias for "all CPUs"?
COMPATIBILITY BREAKAGE
======================
Removals (will likely happen in 2.2):
* (S) psutil.Process.nice (deprecated in 0.5.0)
* (S) get_process_list (deprecated in 0.5.0)
* (S) psutil.*mem* functions (deprecated in 0.3.0 and 0.6.0)
* (M) psutil.network_io_counters (deprecated in 1.0.0)
* (M) local_address and remote_address Process.connection() namedtuple fields
(deprecated in 1.0.0)
REJECTED IDEAS
==============
STUB

View File

@ -2,12 +2,16 @@
#
# You can set these variables from the command line.
PYTHON = python
SPHINXOPTS =
SPHINXBUILD = $(PYTHON) -m sphinx
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
@ -15,7 +19,8 @@ ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@ -25,10 +30,8 @@ help:
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " applehelp to make an Apple Help Book"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " epub3 to make an epub3"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@ -42,51 +45,41 @@ help:
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " coverage to run coverage check of the documentation (if enabled)"
@echo " dummy to check syntax errors of document sources"
.PHONY: clean
clean:
rm -rf $(BUILDDIR)
.PHONY: html
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
.PHONY: dirhtml
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
.PHONY: singlehtml
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
.PHONY: pickle
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
.PHONY: json
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
.PHONY: htmlhelp
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
.PHONY: qthelp
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@ -96,16 +89,6 @@ qthelp:
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/psutil.qhc"
.PHONY: applehelp
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
.PHONY: devhelp
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@ -115,19 +98,11 @@ devhelp:
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/psutil"
@echo "# devhelp"
.PHONY: epub
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
.PHONY: epub3
epub3:
$(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
@echo
@echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
.PHONY: latex
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@ -135,33 +110,28 @@ latex:
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
.PHONY: latexpdf
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
.PHONY: latexpdfja
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
.PHONY: text
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
.PHONY: man
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
.PHONY: texinfo
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@ -169,58 +139,39 @@ texinfo:
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
.PHONY: info
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
.PHONY: gettext
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
.PHONY: changes
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
.PHONY: linkcheck
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
.PHONY: doctest
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
.PHONY: coverage
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
.PHONY: xml
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
.PHONY: pseudoxml
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
.PHONY: dummy
dummy:
$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
@echo
@echo "Build finished. Dummy builder generates no files."

View File

@ -3,7 +3,7 @@ About
This directory contains the reStructuredText (reST) sources to the psutil
documentation. You don't need to build them yourself, prebuilt versions are
available at http://psutil.readthedocs.io.
available at https://pythonhosted.org/psutil/.
In case you want, you need to install sphinx first:
$ pip install sphinx
@ -12,4 +12,4 @@ Then run:
$ make html
You'll then have an HTML version of the doc at _build/html/index.html.
You'll then have an HTML version of the doc at _build/html/index.html.

View File

@ -1,518 +0,0 @@
.wy-nav-content {
max-width: 100% !important;
padding: 15px !important;
}
.rst-content dl:not(.docutils) {
margin: 0px 0px 0px 0px;
}
.data dd {
margin-bottom: 0px !important;
}
.data .descname {
border-right:10px !important;
}
.local-toc li ul li{
padding-left: 20px !important;
}
.function .descclassname {
font-weight: normal !important;
}
.class .descclassname {
font-weight: normal !important;
}
.admonition.warning {
padding-top: 2px !important;
padding-bottom: 2px !important;
}
.admonition.note {
padding-top: 2px !important;
padding-bottom: 2px !important;
}
.rst-content dl:not(.docutils) dt {
color: #555;
}
.sig-paren {
padding-left: 2px;
padding-right: 2px;
}
h1, h2, h3 {
background: #eee;
padding: 5px;
border-bottom: 1px solid #ccc;
}
h1 {
font-size: 35px;
}
.admonition.warning {
padding-top: 5px !important;
padding-bottom: 5px !important;
}
.admonition.warning p {
margin-bottom: 5px !important;
}
.admonition.note {
padding-top: 5px !important;
padding-bottom: 5px !important;
}
.admonition.note p {
margin-bottom: 5px !important;
backround-color: rgb(238, 255, 204) !important;
}
.codeblock div[class^='highlight'], pre.literal-block div[class^='highlight'], .rst-content .literal-block div[class^='highlight'], div[class^='highlight'] div[class^='highlight'] {
background-color: #eeffcc !important;
}
.highlight .hll {
background-color: #ffffcc
}
.highlight {
background: #eeffcc;
}
.highlight-default, .highlight-python {
border-radius: 3px !important;
border: 1px solid #ac9 !important;
}
.highlight .c {
color: #408090;
font-style: italic
}
.wy-side-nav-search {
background-color: grey !important
}
.highlight {
border-radius: 3px !important;
}
div.highlight-default {
margin-bottom: 10px !important;
}
pre {
padding: 5px !important;
}
/* ================================================================== */
/* Warnings and info boxes like python doc */
/* ================================================================== */
div.admonition {
margin-top: 10px !important;
margin-bottom: 10px !important;
}
div.warning {
background-color: #ffe4e4 !important;
border: 1px solid #f66 !important;
border-radius: 3px !important;
}
div.note {
background-color: #eee !important;
border: 1px solid #ccc !important;
border-radius: 3px !important;
}
div.admonition p.admonition-title + p {
display: inline !important;
}
p.admonition-title {
display: inline !important;
background: none !important;
color: black !important;
}
p.admonition-title:after {
content: ":" !important;
}
div.body div.admonition, div.body div.impl-detail {
}
.fa-exclamation-circle:before, .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .wy-input-context:before, .rst-content .admonition-title:before {
display: none !important;
}
.note code {
background: #d6d6d6 !important;
}
/* ================================================================== */
/* Syntax highlight like Python doc.
/* ================================================================== */
/* Comment */
.highlight .err {
border: 1px solid #FF0000
}
/* Error */
.highlight .k {
color: #007020;
font-weight: bold
}
/* Keyword */
.highlight .o {
color: #666666
}
/* Operator */
.highlight .ch {
color: #408090;
font-style: italic
}
/* Comment.Hashbang */
.highlight .cm {
color: #408090;
font-style: italic
}
/* Comment.Multiline */
.highlight .cp {
color: #007020
}
/* Comment.Preproc */
.highlight .cpf {
color: #408090;
font-style: italic
}
/* Comment.PreprocFile */
.highlight .c1 {
color: #408090;
font-style: italic
}
/* Comment.Single */
.highlight .cs {
color: #408090;
background-color: #fff0f0
}
/* Comment.Special */
.highlight .gd {
color: #A00000
}
/* Generic.Deleted */
.highlight .ge {
font-style: italic
}
/* Generic.Emph */
.highlight .gr {
color: #FF0000
}
/* Generic.Error */
.highlight .gh {
color: #000080;
font-weight: bold
}
/* Generic.Heading */
.highlight .gi {
color: #00A000
}
/* Generic.Inserted */
.highlight .go {
color: #333333
}
/* Generic.Output */
.highlight .gp {
color: #c65d09;
font-weight: bold
}
/* Generic.Prompt */
.highlight .gs {
font-weight: bold
}
/* Generic.Strong */
.highlight .gu {
color: #800080;
font-weight: bold
}
/* Generic.Subheading */
.highlight .gt {
color: #0044DD
}
/* Generic.Traceback */
.highlight .kc {
color: #007020;
font-weight: bold
}
/* Keyword.Constant */
.highlight .kd {
color: #007020;
font-weight: bold
}
/* Keyword.Declaration */
.highlight .kn {
color: #007020;
font-weight: bold
}
/* Keyword.Namespace */
.highlight .kp {
color: #007020
}
/* Keyword.Pseudo */
.highlight .kr {
color: #007020;
font-weight: bold
}
/* Keyword.Reserved */
.highlight .kt {
color: #902000
}
/* Keyword.Type */
.highlight .m {
color: #208050
}
/* Literal.Number */
.highlight .s {
color: #4070a0
}
/* Literal.String */
.highlight .na {
color: #4070a0
}
/* Name.Attribute */
.highlight .nb {
color: #007020
}
/* Name.Builtin */
.highlight .nc {
color: #0e84b5;
font-weight: bold
}
/* Name.Class */
.highlight .no {
color: #60add5
}
/* Name.Constant */
.highlight .nd {
color: #555555;
font-weight: bold
}
/* Name.Decorator */
.highlight .ni {
color: #d55537;
font-weight: bold
}
/* Name.Entity */
.highlight .ne {
color: #007020
}
/* Name.Exception */
.highlight .nf {
color: #06287e
}
/* Name.Function */
.highlight .nl {
color: #002070;
font-weight: bold
}
/* Name.Label */
.highlight .nn {
color: #0e84b5;
font-weight: bold
}
/* Name.Namespace */
.highlight .nt {
color: #062873;
font-weight: bold
}
/* Name.Tag */
.highlight .nv {
color: #bb60d5
}
/* Name.Variable */
.highlight .ow {
color: #007020;
font-weight: bold
}
/* Operator.Word */
.highlight .w {
color: #bbbbbb
}
/* Text.Whitespace */
.highlight .mb {
color: #208050
}
/* Literal.Number.Bin */
.highlight .mf {
color: #208050
}
/* Literal.Number.Float */
.highlight .mh {
color: #208050
}
/* Literal.Number.Hex */
.highlight .mi {
color: #208050
}
/* Literal.Number.Integer */
.highlight .mo {
color: #208050
}
/* Literal.Number.Oct */
.highlight .sa {
color: #4070a0
}
/* Literal.String.Affix */
.highlight .sb {
color: #4070a0
}
/* Literal.String.Backtick */
.highlight .sc {
color: #4070a0
}
/* Literal.String.Char */
.highlight .dl {
color: #4070a0
}
/* Literal.String.Delimiter */
.highlight .sd {
color: #4070a0;
font-style: italic
}
/* Literal.String.Doc */
.highlight .s2 {
color: #4070a0
}
/* Literal.String.Double */
.highlight .se {
color: #4070a0;
font-weight: bold
}
/* Literal.String.Escape */
.highlight .sh {
color: #4070a0
}
/* Literal.String.Heredoc */
.highlight .si {
color: #70a0d0;
font-style: italic
}
/* Literal.String.Interpol */
.highlight .sx {
color: #c65d09
}
/* Literal.String.Other */
.highlight .sr {
color: #235388
}
/* Literal.String.Regex */
.highlight .s1 {
color: #4070a0
}
/* Literal.String.Single */
.highlight .ss {
color: #517918
}
/* Literal.String.Symbol */
.highlight .bp {
color: #007020
}
/* Name.Builtin.Pseudo */
.highlight .fm {
color: #06287e
}
/* Name.Function.Magic */
.highlight .vc {
color: #bb60d5
}
/* Name.Variable.Class */
.highlight .vg {
color: #bb60d5
}
/* Name.Variable.Global */
.highlight .vi {
color: #bb60d5
}
/* Name.Variable.Instance */
.highlight .vm {
color: #bb60d5
}
/* Name.Variable.Magic */
.highlight .il {
color: #208050
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -0,0 +1,12 @@
{#
basic/globaltoc.html
~~~~~~~~~~~~~~~~~~~~
Sphinx sidebar template: global table of contents.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
<h3>{{ _('Manual') }}</h3>
{{ toctree() }}
<a href="{{ pathto(master_doc) }}">Back to Welcome</a>

View File

@ -0,0 +1,4 @@
{% extends "defindex.html" %}
{% block tables %}
{% endblock %}

View File

@ -0,0 +1,8 @@
<h3>Useful links</h3>
<ul>
<li><a href="https://github.com/giampaolo/psutil">Github project</a></li>
<li><a href="http://grodola.blogspot.com/search/label/psutil">Blog</a></li>
<li><a href="https://pypi.python.org/pypi?:action=display&name=psutil#downloads">Download</a></li>
<li><a href="https://github.com/giampaolo/psutil/issues">Issues</a></li>
<li><a href="http://groups.google.com/group/psutil/topics">Forum</a></li>
</ul>

View File

@ -0,0 +1,66 @@
{% extends "!page.html" %}
{% block extrahead %}
{{ super() }}
{% if not embedded %}<script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>{% endif %}
<script type="text/javascript">
// Store editor pop-up help state in localStorage
// so it does not re-pop-up itself between page loads.
// Do not even to pretend to support IE gracefully.
(function($) {
$(document).ready(function() {
var box = $("#editor-trap");
var klass = "toggled";
var storageKey = "toggled";
function toggle() {
box.toggleClass(klass);
// Store the toggle status in local storage as "has value string" or null
window.localStorage.setItem(storageKey, box.hasClass(klass) ? "toggled" : "not-toggled");
}
box.click(toggle);
// Check the persistent state of the editor pop-up
// Note that localStorage does not necessarily support boolean values (ugh!)
// http://stackoverflow.com/questions/3263161/cannot-set-boolean-values-in-localstorage
var v = window.localStorage.getItem(storageKey);
if(v == "toggled" || !v) {
box.addClass(klass);
}
});
})(jQuery);
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-2097050-4']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
{% endblock %}
{% block rootrellink %}
<li><a href="https://github.com/giampaolo/psutil/"><img src="{{ pathto('_static/logo.png', 1) }}" style="height: 30px; vertical-align: middle; padding-right: 1em;" /> Project Homepage</a>{{ reldelim1 }}</li>
<li><a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }}</li>
{% endblock %}
{% block footer %}
<div class="footer">
&copy; Copyright {{ copyright|e }}.
<br />
Last updated on {{ last_updated|e }}.
<br />
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> {{ sphinx_version|e }}.
</div>
{% endblock %}

View File

@ -0,0 +1,187 @@
@import url("default.css");
body {
background-color: white;
margin-left: 1em;
margin-right: 1em;
}
div.related {
margin-bottom: 1.2em;
padding: 0.5em 0;
border-top: 1px solid #ccc;
margin-top: 0.5em;
}
div.related a:hover {
color: #0095C4;
}
div.related:first-child {
border-top: 0;
padding-top: 0;
border-bottom: 1px solid #ccc;
}
div.sphinxsidebar {
background-color: #eeeeee;
border-radius: 5px;
line-height: 130%;
font-size: smaller;
}
div.sphinxsidebar h3, div.sphinxsidebar h4 {
margin-top: 1.5em;
}
div.sphinxsidebarwrapper > h3:first-child {
margin-top: 0.2em;
}
div.sphinxsidebarwrapper > ul > li > ul > li {
margin-bottom: 0.4em;
}
div.sphinxsidebar a:hover {
color: #0095C4;
}
div.sphinxsidebar input {
font-family: 'Lucida Grande','Lucida Sans','DejaVu Sans',Arial,sans-serif;
border: 1px solid #999999;
font-size: smaller;
border-radius: 3px;
}
div.sphinxsidebar input[type=text] {
max-width: 150px;
}
div.body {
padding: 0 0 0 1.2em;
}
div.body p {
line-height: 140%;
}
div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 {
margin: 0;
border: 0;
padding: 0.3em 0;
}
div.body hr {
border: 0;
background-color: #ccc;
height: 1px;
}
div.body pre {
border-radius: 3px;
border: 1px solid #ac9;
}
div.body div.admonition, div.body div.impl-detail {
border-radius: 3px;
}
div.body div.impl-detail > p {
margin: 0;
}
div.body div.seealso {
border: 1px solid #dddd66;
}
div.body a {
color: #00608f;
}
div.body a:visited {
color: #30306f;
}
div.body a:hover {
color: #00B0E4;
}
tt, pre {
font-family: monospace, sans-serif;
font-size: 96.5%;
}
div.body tt {
border-radius: 3px;
}
div.body tt.descname {
font-size: 120%;
}
div.body tt.xref, div.body a tt {
font-weight: normal;
}
p.deprecated {
border-radius: 3px;
}
table.docutils {
border: 1px solid #ddd;
min-width: 20%;
border-radius: 3px;
margin-top: 10px;
margin-bottom: 10px;
}
table.docutils td, table.docutils th {
border: 1px solid #ddd !important;
border-radius: 3px;
}
table p, table li {
text-align: left !important;
}
table.docutils th {
background-color: #eee;
padding: 0.3em 0.5em;
}
table.docutils td {
background-color: white;
padding: 0.3em 0.5em;
}
table.footnote, table.footnote td {
border: 0 !important;
}
div.footer {
line-height: 150%;
margin-top: -2em;
text-align: right;
width: auto;
margin-right: 10px;
}
div.footer a:hover {
color: #0095C4;
}
div.body h1,
div.body h2,
div.body h3 {
background-color: #EAEAEA;
border-bottom: 1px solid #CCC;
padding-top: 2px;
padding-bottom: 2px;
padding-left: 5px;
margin-top: 5px;
margin-bottom: 5px;
}
div.body h2 {
padding-left:10px;
}

View File

@ -0,0 +1,23 @@
[theme]
inherit = default
stylesheet = pydoctheme.css
pygments_style = sphinx
[options]
bodyfont = 'Lucida Grande', 'Lucida Sans', 'DejaVu Sans', Arial, sans-serif
headfont = 'Lucida Grande', 'Lucida Sans', 'DejaVu Sans', Arial, sans-serif
footerbgcolor = white
footertextcolor = #555555
relbarbgcolor = white
relbartextcolor = #666666
relbarlinkcolor = #444444
sidebarbgcolor = white
sidebartextcolor = #444444
sidebarlinkcolor = #444444
bgcolor = white
textcolor = #222222
linkcolor = #0090c0
visitedlinkcolor = #00608f
headtextcolor = #1a1a1a
headbgcolor = white
headlinkcolor = #aaaaaa

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# psutil documentation build configuration file, created by
# sphinx-quickstart on Wed Oct 19 21:54:30 2016.
# sphinx-quickstart.
#
# This file is execfile()d with the current directory set to its
# containing dir.
@ -12,22 +12,12 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
import datetime
import os
PROJECT_NAME = "psutil"
AUTHOR = u"Giampaolo Rodola"
AUTHOR = "Giampaolo Rodola'"
THIS_YEAR = str(datetime.datetime.now().year)
HERE = os.path.abspath(os.path.dirname(__file__))
@ -45,33 +35,27 @@ def get_version():
else:
raise ValueError("couldn't find version string")
VERSION = get_version()
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc',
'sphinx.ext.coverage',
'sphinx.ext.imgmath',
'sphinx.ext.pngmath',
'sphinx.ext.viewcode',
'sphinx.ext.intersphinx']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ['_template']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#
# source_encoding = 'utf-8-sig'
# The master toctree document.
@ -80,7 +64,6 @@ master_doc = 'index'
# General information about the project.
project = PROJECT_NAME
copyright = '2009-%s, %s' % (THIS_YEAR, AUTHOR)
author = 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
@ -88,47 +71,35 @@ author = AUTHOR
#
# The short X.Y version.
version = VERSION
# The full version, including alpha/beta/rc tags.
release = VERSION
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#
# today = ''
#
# Else, today_fmt is used as the format for a strftime call.
#
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all
# documents.
#
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#
# add_function_parentheses = True
add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#
# add_module_names = True
autodoc_docstring_signature = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
@ -137,240 +108,141 @@ pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
# keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
html_theme = 'pydoctheme'
html_theme_options = {'collapsiblesidebar': True}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
html_theme_path = ["_themes"]
# The name for this set of Sphinx documents.
# "<project> v<release> documentation" by default.
#
# html_title = u'psutil v1.0'
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
html_title = "{project} {version} documentation".format(**locals())
# A shorter title for the navigation bar. Default is the same as html_title.
#
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#
# html_logo = None
# The name of an image file (relative to this directory) to use as a favicon of
# the docs. This file should be a Windows icon file (.ico) being 16x16 or
# 32x32 pixels large.
# html_logo = 'logo.png'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = '_static/favicon.ico'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#
# html_extra_path = []
# If not None, a 'Last updated on:' timestamp is inserted at every page
# bottom, using the given strftime format.
# The empty string is equivalent to '%b %d, %Y'.
#
# html_last_updated_fmt = None
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#
# html_use_smartypants = True
html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#
# html_sidebars = {}
html_sidebars = {
'index': 'indexsidebar.html',
'**': ['globaltoc.html',
'relations.html',
'sourcelink.html',
'searchbox.html']
}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#
# html_additional_pages = {}
# html_additional_pages = {
# 'index': 'indexcontent.html',
# }
# If false, no module index is generated.
#
# html_domain_indices = True
html_domain_indices = False
# If false, no index is generated.
#
# html_use_index = True
html_use_index = True
# If true, the index is split into individual pages for each letter.
#
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
#
# html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# 'ja' uses this config value.
# 'zh' user can custom change `jieba` dictionary path.
#
# html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#
# html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = '%s-doc' % PROJECT_NAME
# -- Options for LaTeX output ---------------------------------------------
# -- Options for LaTeX output ------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The paper size ('letter' or 'a4').
# latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# The font size ('10pt', '11pt' or '12pt').
# latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
(master_doc, 'psutil.tex', u'psutil Documentation',
AUTHOR, 'manual'),
('index', '%s.tex' % PROJECT_NAME,
'%s documentation' % PROJECT_NAME, AUTHOR),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#
# The name of an image file (relative to this directory) to place at
# the top of the title page.
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#
# latex_use_parts = False
# If true, show page references after internal links.
#
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#
# latex_show_urls = False
# Additional stuff for the LaTeX preamble.
# latex_preamble = ''
# Documents to append as an appendix to all manuals.
#
# latex_appendices = []
# It false, will not define \strong, \code, itleref, \crossref ... but only
# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added
# packages.
#
# latex_keep_old_macro_names = True
# If false, no module index is generated.
#
# latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# -- Options for manual page output ------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'psutil', u'psutil Documentation',
[author], 1)
('index', PROJECT_NAME, '%s documentation' % PROJECT_NAME, [AUTHOR], 1)
]
# If true, show URL addresses after external links.
#
# man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'psutil', u'psutil Documentation',
author, 'psutil', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#
# texinfo_appendices = []
# If false, no module index is generated.
#
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#
# texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#
# texinfo_no_detailmenu = False
html_context = {
'css_files': [
'https://media.readthedocs.org/css/sphinx_rtd_theme.css',
'https://media.readthedocs.org/css/readthedocs-doc-embed.css',
'_static/css/custom.css',
],
}

File diff suppressed because it is too large Load Diff

View File

@ -1,242 +1,242 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. xml to make Docutils-native XML files
echo. pseudoxml to make pseudoxml-XML files for display purposes
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
%SPHINXBUILD% 2> nul
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\pyftpdlib.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\pyftpdlib.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdf" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdfja" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf-ja
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
if "%1" == "xml" (
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The XML files are in %BUILDDIR%/xml.
goto end
)
if "%1" == "pseudoxml" (
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
goto end
)
:end
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. xml to make Docutils-native XML files
echo. pseudoxml to make pseudoxml-XML files for display purposes
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
%SPHINXBUILD% 2> nul
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\psutil.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\psutil.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdf" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdfja" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf-ja
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
if "%1" == "xml" (
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The XML files are in %BUILDDIR%/xml.
goto end
)
if "%1" == "pseudoxml" (
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
goto end
)
:end

11
third_party/python/psutil/docs/xxx vendored Normal file
View 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

View File

@ -7,7 +7,7 @@
"""
List all mounted disk partitions a-la "df -h" command.
$ python scripts/disk_usage.py
$ python examples/disk_usage.py
Device Total Used Free Use % Type Mount
/dev/sdb3 18.9G 14.7G 3.3G 77% ext4 /
/dev/sda6 345.9G 83.8G 244.5G 24% ext4 /home
@ -58,6 +58,5 @@ def main():
part.fstype,
part.mountpoint))
if __name__ == '__main__':
sys.exit(main())

View File

@ -7,7 +7,7 @@
"""
A clone of 'free' cmdline utility.
$ python scripts/free.py
$ python examples/free.py
total used free shared buffers cache
Mem: 10125520 8625996 1499524 0 349500 3307836
Swap: 0 0 0
@ -37,6 +37,5 @@ def main():
'',
''))
if __name__ == '__main__':
main()

View 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()

View File

@ -14,7 +14,7 @@ It doesn't work on Windows as curses module is required.
Example output:
$ python scripts/iotop.py
$ python examples/iotop.py
Total DISK READ: 0.00 B/s | Total DISK WRITE: 472.00 K/s
PID USER DISK READ DISK WRITE COMMAND
13155 giampao 0.00 B/s 428.00 K/s /usr/bin/google-chrome-beta
@ -48,7 +48,6 @@ def tear_down():
curses.echo()
curses.endwin()
win = curses.initscr()
atexit.register(tear_down)
curses.endwin()
@ -112,15 +111,14 @@ def poll(interval):
# then retrieve the same info again
for p in procs[:]:
with p.oneshot():
try:
p._after = p.io_counters()
p._cmdline = ' '.join(p.cmdline())
if not p._cmdline:
p._cmdline = p.name()
p._username = p.username()
except (psutil.NoSuchProcess, psutil.ZombieProcess):
procs.remove(p)
try:
p._after = p.io_counters()
p._cmdline = ' '.join(p.cmdline())
if not p._cmdline:
p._cmdline = p.name()
p._username = p.username()
except (psutil.NoSuchProcess, psutil.ZombieProcess):
procs.remove(p)
disks_after = psutil.disk_io_counters()
# finally calculate results by comparing data before and
@ -177,6 +175,5 @@ def main():
except (KeyboardInterrupt, SystemExit):
pass
if __name__ == '__main__':
main()

View File

@ -29,6 +29,4 @@ def main():
else:
sys.exit(0)
if __name__ == '__main__':
main()
sys.exit(main())

View File

@ -7,7 +7,7 @@
"""
Print system memory information.
$ python scripts/meminfo.py
$ python examples/meminfo.py
MEMORY
------
Total : 9.7G
@ -64,6 +64,5 @@ def main():
print('\nSWAP\n----')
pprint_ntuple(psutil.swap_memory())
if __name__ == '__main__':
main()

View File

@ -7,7 +7,7 @@
"""
A clone of 'netstat -antp' on Linux.
$ python scripts/netstat.py
$ python examples/netstat.py
Proto Local address Remote address Status PID Program name
tcp 127.0.0.1:48256 127.0.0.1:45884 ESTABLISHED 13646 chrome
tcp 127.0.0.1:47073 127.0.0.1:45884 ESTABLISHED 13646 chrome
@ -41,8 +41,11 @@ def main():
"Proto", "Local address", "Remote address", "Status", "PID",
"Program name"))
proc_names = {}
for p in psutil.process_iter(attrs=['pid', 'name']):
proc_names[p.info['pid']] = p.info['name']
for p in psutil.process_iter():
try:
proc_names[p.pid] = p.name()
except psutil.Error:
pass
for c in psutil.net_connections(kind='inet'):
laddr = "%s:%s" % (c.laddr)
raddr = ""
@ -57,6 +60,5 @@ def main():
proc_names.get(c.pid, '?')[:15],
))
if __name__ == '__main__':
main()

View File

@ -11,7 +11,7 @@ Shows real-time network statistics.
Author: Giampaolo Rodola' <g.rodola@gmail.com>
$ python scripts/nettop.py
$ python examples/nettop.py
-----------------------------------------------------------
total bytes: sent: 1.49 G received: 4.82 G
total packets: sent: 7338724 received: 8082712
@ -49,7 +49,6 @@ def tear_down():
curses.echo()
curses.endwin()
win = curses.initscr()
atexit.register(tear_down)
curses.endwin()
@ -162,6 +161,5 @@ def main():
except (KeyboardInterrupt, SystemExit):
pass
if __name__ == '__main__':
main()

View File

@ -18,11 +18,25 @@ import sys
def pidof(pgname):
pids = []
for proc in psutil.process_iter(attrs=['name', 'cmdline']):
for proc in psutil.process_iter():
# search for matches in the process name and cmdline
if proc.info['name'] == pgname or \
proc.info['cmdline'] and proc.info['cmdline'][0] == pgname:
pids.append(str(proc.pid))
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
@ -35,6 +49,5 @@ def main():
if pids:
print(" ".join(pids))
if __name__ == '__main__':
main()

View File

@ -8,7 +8,7 @@
A clone of 'pmap' utility on Linux, 'vmmap' on OSX and 'procstat -v' on BSD.
Report memory map of a process.
$ python scripts/pmap.py 32402
$ python examples/pmap.py 32402
pid=32402, name=hg
Address RSS Mode Mapping
0000000000400000 1200K r-xp /usr/bin/python2.7
@ -53,6 +53,5 @@ def main():
print("-" * 33)
print(templ % ("Total", str(total_rss / 1024) + 'K', '', ''))
if __name__ == '__main__':
main()

View File

@ -0,0 +1,167 @@
#!/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.
"""
Print detailed information about a process.
Author: Giampaolo Rodola' <g.rodola@gmail.com>
$ python examples/process_detail.py
pid 820
name python
exe /usr/bin/python2.7
parent 29613 (bash)
cmdline python examples/process_detail.py
started 2014-41-27 03:41
user giampaolo
uids real=1000, effective=1000, saved=1000
gids real=1000, effective=1000, saved=1000
terminal /dev/pts/17
cwd /ssd/svn/psutil
memory 0.1% (resident=10.6M, virtual=58.5M)
cpu 0.0% (user=0.09, system=0.0)
status running
niceness 0
num threads 1
I/O bytes-read=0B, bytes-written=0B
open files
running threads id=820, user-time=0.09, sys-time=0.0
"""
import datetime
import os
import socket
import sys
import psutil
POSIX = os.name == 'posix'
def convert_bytes(n):
symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
prefix = {}
for i, s in enumerate(symbols):
prefix[s] = 1 << (i + 1) * 10
for s in reversed(symbols):
if n >= prefix[s]:
value = float(n) / prefix[s]
return '%.1f%s' % (value, s)
return "%sB" % n
def print_(a, b):
if sys.stdout.isatty() and POSIX:
fmt = '\x1b[1;32m%-17s\x1b[0m %s' % (a, b)
else:
fmt = '%-15s %s' % (a, b)
# python 2/3 compatibility layer
sys.stdout.write(fmt + '\n')
sys.stdout.flush()
def run(pid):
ACCESS_DENIED = ''
try:
p = psutil.Process(pid)
pinfo = p.as_dict(ad_value=ACCESS_DENIED)
except psutil.NoSuchProcess as err:
sys.exit(str(err))
try:
parent = p.parent()
if parent:
parent = '(%s)' % parent.name()
else:
parent = ''
except psutil.Error:
parent = ''
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)
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'])
print_('name', pinfo['name'])
print_('exe', pinfo['exe'])
print_('parent', '%s %s' % (pinfo['ppid'], parent))
print_('cmdline', ' '.join(pinfo['cmdline']))
print_('started', started)
print_('user', pinfo['username'])
if POSIX and pinfo['uids'] and pinfo['gids']:
print_('uids', 'real=%s, effective=%s, saved=%s' % pinfo['uids'])
if POSIX and pinfo['gids']:
print_('gids', 'real=%s, effective=%s, saved=%s' % pinfo['gids'])
if POSIX:
print_('terminal', pinfo['terminal'] or '')
print_('cwd', pinfo['cwd'])
print_('memory', mem)
print_('cpu', '%s%% (user=%s, system=%s)' % (
pinfo['cpu_percent'],
getattr(pinfo['cpu_times'], 'user', '?'),
getattr(pinfo['cpu_times'], 'system', '?')))
print_('status', pinfo['status'])
print_('niceness', pinfo['nice'])
print_('num threads', pinfo['num_threads'])
if io != ACCESS_DENIED:
print_('I/O', 'bytes-read=%s, bytes-written=%s' % (
convert_bytes(io.read_bytes),
convert_bytes(io.write_bytes)))
if children:
print_('children', '')
for child in children:
print_('', 'pid=%s name=%s' % (child.pid, child.name()))
if pinfo['open_files'] != ACCESS_DENIED:
print_('open files', '')
for file in pinfo['open_files']:
print_('', 'fd=%s %s ' % (file.fd, file.path))
if pinfo['threads']:
print_('running threads', '')
for thread in pinfo['threads']:
print_('', 'id=%s, user-time=%s, sys-time=%s' % (
thread.id, thread.user_time, thread.system_time))
if pinfo['connections'] not in (ACCESS_DENIED, []):
print_('open connections', '')
for conn in pinfo['connections']:
if conn.type == socket.SOCK_STREAM:
type = 'TCP'
elif conn.type == socket.SOCK_DGRAM:
type = 'UDP'
else:
type = 'UNIX'
lip, lport = conn.laddr
if not conn.raddr:
rip, rport = '*', '*'
else:
rip, rport = conn.raddr
print_('', '%s:%s -> %s:%s type=%s status=%s' % (
lip, lport, rip, rport, type, conn.status))
def main(argv=None):
if argv is None:
argv = sys.argv
if len(argv) == 1:
sys.exit(run(os.getpid()))
elif len(argv) == 2:
sys.exit(run(int(argv[1])))
else:
sys.exit('usage: %s [pid]' % __file__)
if __name__ == '__main__':
sys.exit(main())

View File

@ -7,7 +7,7 @@
"""
A clone of 'ps -aux' on UNIX.
$ python scripts/ps.py
$ python examples/ps.py
...
"""
@ -18,37 +18,16 @@ import time
import psutil
PROC_STATUSES_RAW = {
psutil.STATUS_RUNNING: "R",
psutil.STATUS_SLEEPING: "S",
psutil.STATUS_DISK_SLEEP: "D",
psutil.STATUS_STOPPED: "T",
psutil.STATUS_TRACING_STOP: "t",
psutil.STATUS_ZOMBIE: "Z",
psutil.STATUS_DEAD: "X",
psutil.STATUS_WAKING: "WA",
psutil.STATUS_IDLE: "I",
psutil.STATUS_LOCKED: "L",
psutil.STATUS_WAITING: "W",
}
if hasattr(psutil, 'STATUS_WAKE_KILL'):
PROC_STATUSES_RAW[psutil.STATUS_WAKE_KILL] = "WK"
if hasattr(psutil, 'STATUS_SUSPENDED'):
PROC_STATUSES_RAW[psutil.STATUS_SUSPENDED] = "V"
def main():
today_day = datetime.date.today()
templ = "%-10s %5s %4s %4s %7s %7s %-13s %-5s %5s %7s %s"
templ = "%-10s %5s %4s %4s %7s %7s %-13s %5s %7s %s"
attrs = ['pid', 'cpu_percent', 'memory_percent', 'name', 'cpu_times',
'create_time', 'memory_info', 'status']
'create_time', 'memory_info']
if os.name == 'posix':
attrs.append('uids')
attrs.append('terminal')
print(templ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY",
"STAT", "START", "TIME", "COMMAND"))
"START", "TIME", "COMMAND"))
for p in psutil.process_iter():
try:
pinfo = p.as_dict(attrs, ad_value='')
@ -85,7 +64,6 @@ def main():
int(pinfo['memory_info'].rss / 1024) or '?'
memp = pinfo['memory_percent'] and \
round(pinfo['memory_percent'], 1) or '?'
status = PROC_STATUSES_RAW.get(pinfo['status'], pinfo['status'])
print(templ % (
user[:10],
pinfo['pid'],
@ -94,7 +72,6 @@ def main():
vms,
rss,
pinfo.get('terminal', '') or '?',
status,
ctime,
cputime,
pinfo['name'].strip() or '?'))

View File

@ -8,7 +8,7 @@
Similar to 'ps aux --forest' on Linux, prints the process list
as a tree structure.
$ python scripts/pstree.py
$ python examples/pstree.py
0 ?
|- 1 init
| |- 289 cgmanager

View File

@ -9,14 +9,14 @@ A clone of top / htop.
Author: Giampaolo Rodola' <g.rodola@gmail.com>
$ python scripts/top.py
$ python examples/top.py
CPU0 [| ] 4.9%
CPU1 [||| ] 7.8%
CPU2 [ ] 2.0%
CPU3 [||||| ] 13.9%
Mem [||||||||||||||||||| ] 49.8% 4920M / 9888M
Swap [ ] 0.0% 0M / 0M
Processes: 287 (running=1, sleeping=286, zombie=1)
Mem [||||||||||||||||||| ] 49.8% 4920M/9888M
Swap [ ] 0.0% 0M/0M
Processes: 287 (running=1 sleeping=286)
Load average: 0.34 0.54 0.46 Uptime: 3 days, 10:16:37
PID USER NI VIRT RES CPU% MEM% TIME+ NAME
@ -34,11 +34,11 @@ PID USER NI VIRT RES CPU% MEM% TIME+ NAME
...
"""
from datetime import datetime, timedelta
import atexit
import datetime
import os
import sys
import time
import sys
try:
import curses
except ImportError:
@ -48,14 +48,12 @@ import psutil
# --- curses stuff
def tear_down():
win.keypad(0)
curses.nocbreak()
curses.echo()
curses.endwin()
win = curses.initscr()
atexit.register(tear_down)
curses.endwin()
@ -77,7 +75,6 @@ def print_line(line, highlight=False):
raise
else:
lineno += 1
# --- /curses stuff
@ -140,10 +137,11 @@ def print_header(procs_status, num_procs):
perc))
mem = psutil.virtual_memory()
dashes, empty_dashes = get_dashes(mem.percent)
line = " Mem [%s%s] %5s%% %6s / %s" % (
used = mem.total - mem.available
line = " Mem [%s%s] %5s%% %6s/%s" % (
dashes, empty_dashes,
mem.percent,
str(int(mem.used / 1024 / 1024)) + "M",
str(int(used / 1024 / 1024)) + "M",
str(int(mem.total / 1024 / 1024)) + "M"
)
print_line(line)
@ -151,7 +149,7 @@ def print_header(procs_status, num_procs):
# swap usage
swap = psutil.swap_memory()
dashes, empty_dashes = get_dashes(swap.percent)
line = " Swap [%s%s] %5s%% %6s / %s" % (
line = " Swap [%s%s] %5s%% %6s/%s" % (
dashes, empty_dashes,
swap.percent,
str(int(swap.used / 1024 / 1024)) + "M",
@ -165,10 +163,9 @@ def print_header(procs_status, num_procs):
if y:
st.append("%s=%s" % (x, y))
st.sort(key=lambda x: x[:3] in ('run', 'sle'), reverse=1)
print_line(" Processes: %s (%s)" % (num_procs, ', '.join(st)))
print_line(" Processes: %s (%s)" % (num_procs, ' '.join(st)))
# load average, uptime
uptime = datetime.datetime.now() - \
datetime.datetime.fromtimestamp(psutil.boot_time())
uptime = datetime.now() - datetime.fromtimestamp(psutil.boot_time())
av1, av2, av3 = os.getloadavg()
line = " Load average: %.2f %.2f %.2f Uptime: %s" \
% (av1, av2, av3, str(uptime).split('.')[0])
@ -189,7 +186,7 @@ def refresh_window(procs, procs_status):
# TIME+ column shows process CPU cumulative time and it
# is expressed as: "mm:ss.ms"
if p.dict['cpu_times'] is not None:
ctime = datetime.timedelta(seconds=sum(p.dict['cpu_times']))
ctime = timedelta(seconds=sum(p.dict['cpu_times']))
ctime = "%s:%s.%s" % (ctime.seconds // 60 % 60,
str((ctime.seconds % 60)).zfill(2),
str(ctime.microseconds)[:2])
@ -232,6 +229,5 @@ def main():
except (KeyboardInterrupt, SystemExit):
pass
if __name__ == '__main__':
main()

View File

@ -8,9 +8,11 @@
A clone of 'who' command; print information about users who are
currently logged in.
$ python scripts/who.py
giampaolo console 2017-03-25 22:24 loginwindow
giampaolo ttys000 2017-03-25 23:28 (10.0.2.2) sshd
$ python examples/who.py
giampaolo tty7 2014-02-23 17:25 (:0)
giampaolo pts/7 2014-02-24 18:25 (:192.168.1.56)
giampaolo pts/8 2014-02-24 18:25 (:0)
giampaolo pts/9 2014-02-27 01:32 (:0)
"""
from datetime import datetime
@ -21,15 +23,11 @@ import psutil
def main():
users = psutil.users()
for user in users:
proc_name = psutil.Process(user.pid).name() if user.pid else ""
print("%-12s %-10s %-10s %-14s %s" % (
print("%-15s %-15s %s (%s)" % (
user.name,
user.terminal or '-',
datetime.fromtimestamp(user.started).strftime("%Y-%m-%d %H:%M"),
"(%s)" % user.host if user.host else "",
proc_name
))
user.host))
if __name__ == '__main__':
main()

View File

@ -23,10 +23,179 @@ if "%PYTHON%" == "" (
set PYTHON=C:\Python27\python.exe
)
if "%TSCRIPT%" == "" (
set TSCRIPT=psutil\tests\__main__.py
set TSCRIPT=test\test_psutil.py
)
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%
%PYTHON% scripts\internal\winmake.py %1 %2 %3 %4 %5 %6
rem ==========================================================================
if "%1" == "help" (
:help
echo Run `make ^<target^>` where ^<target^> is one of:
echo build compile without installing
echo build-all build exes + wheels
echo clean clean build files
echo flake8 run flake8
echo install compile and install
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-all upload exes + wheels
goto :eof
)
if "%1" == "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)
for /r %%R in (*.orig) do if exist %%R (del /s %%R)
for /r %%R in (*.bak) do if exist %%R (del /s %%R)
for /r %%R in (*.rej) do if exist %%R (del /s %%R)
if exist psutil.egg-info (rmdir /S /Q psutil.egg-info)
if exist build (rmdir /S /Q build)
if exist dist (rmdir /S /Q dist)
goto :eof
)
if "%1" == "build" (
: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
call :build
%PYTHON% setup.py install
goto :eof
)
if "%1" == "uninstall" (
for %%A in ("%PYTHON%") do (
set folder=%%~dpA
)
for /F "delims=" %%i in ('dir /b %folder%\Lib\site-packages\*psutil*') do (
rmdir /S /Q %folder%\Lib\site-packages\%%i
)
goto :eof
)
if "%1" == "test" (
call :install
%PYTHON% %TSCRIPT%
goto :eof
)
if "%1" == "test-process" (
call :install
%PYTHON% -m unittest -v test.test_psutil.TestProcess
goto :eof
)
if "%1" == "test-system" (
call :install
%PYTHON% -m unittest -v test.test_psutil.TestSystem
goto :eof
)
if "%1" == "test-memleaks" (
call :install
%PYTHON% test\test_memory_leaks.py
goto :eof
)
if "%1" == "build-all" (
:build-all
"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat"
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-all" (
:upload-exes
"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-dev-env" (
:setup-env
@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" == "flake8" (
:flake8
%PYTHON% -c "from flake8.main import main; main()"
goto :eof
)
goto :help
:error
@echo ------------------------------------------------
@echo last command exited with error code %errorlevel%
@echo ------------------------------------------------
@exit /b %errorlevel%
goto :eof

View 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

View 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

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@
psutil

View File

@ -1,5 +0,0 @@
API REFERENCES
==============
- psutil.sensors_battery:
https://github.com/Kentzo/Power/

File diff suppressed because it is too large Load Diff

View File

@ -1,95 +1,36 @@
# /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.
"""Common objects shared by __init__.py and _ps*.py modules."""
# Note: this module is imported by setup.py so it should not import
# psutil or third-party modules.
"""Common objects shared by all _ps* modules."""
from __future__ import division
import contextlib
import errno
import functools
import os
import socket
import stat
import sys
import threading
import warnings
from collections import defaultdict
from collections import namedtuple
from socket import AF_INET
from socket import SOCK_DGRAM
from socket import SOCK_STREAM
from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM
try:
from socket import AF_INET6
import threading
except ImportError:
AF_INET6 = None
try:
from socket import AF_UNIX
except ImportError:
AF_UNIX = None
import dummy_threading as threading
if sys.version_info >= (3, 4):
import enum
else:
enum = None
# can't take it from _common.py as this script is imported by setup.py
PY3 = sys.version_info[0] == 3
__all__ = [
# constants
'FREEBSD', 'BSD', 'LINUX', 'NETBSD', 'OPENBSD', 'OSX', 'POSIX', 'SUNOS',
'WINDOWS',
'ENCODING', 'ENCODING_ERRS', 'AF_INET6',
# connection constants
'CONN_CLOSE', 'CONN_CLOSE_WAIT', 'CONN_CLOSING', 'CONN_ESTABLISHED',
'CONN_FIN_WAIT1', 'CONN_FIN_WAIT2', 'CONN_LAST_ACK', 'CONN_LISTEN',
'CONN_NONE', 'CONN_SYN_RECV', 'CONN_SYN_SENT', 'CONN_TIME_WAIT',
# net constants
'NIC_DUPLEX_FULL', 'NIC_DUPLEX_HALF', 'NIC_DUPLEX_UNKNOWN',
# process status constants
'STATUS_DEAD', 'STATUS_DISK_SLEEP', 'STATUS_IDLE', 'STATUS_LOCKED',
'STATUS_RUNNING', 'STATUS_SLEEPING', 'STATUS_STOPPED', 'STATUS_SUSPENDED',
'STATUS_TRACING_STOP', 'STATUS_WAITING', 'STATUS_WAKE_KILL',
'STATUS_WAKING', 'STATUS_ZOMBIE',
# named tuples
'pconn', 'pcputimes', 'pctxsw', 'pgids', 'pio', 'pionice', 'popenfile',
'pthread', 'puids', 'sconn', 'scpustats', 'sdiskio', 'sdiskpart',
'sdiskusage', 'snetio', 'snic', 'snicstats', 'sswap', 'suser',
# utility functions
'conn_tmap', 'deprecated_method', 'isfile_strict', 'memoize',
'parse_environ_block', 'path_exists_strict', 'usage_percent',
'supports_ipv6', 'sockfam_to_enum', 'socktype_to_enum', "wrap_numbers",
]
# --- constants
AF_INET6 = getattr(socket, 'AF_INET6', None)
AF_UNIX = getattr(socket, 'AF_UNIX', None)
# ===================================================================
# --- OS constants
# ===================================================================
POSIX = os.name == "posix"
WINDOWS = os.name == "nt"
LINUX = sys.platform.startswith("linux")
OSX = sys.platform.startswith("darwin")
FREEBSD = sys.platform.startswith("freebsd")
OPENBSD = sys.platform.startswith("openbsd")
NETBSD = sys.platform.startswith("netbsd")
BSD = FREEBSD or OPENBSD or NETBSD
SUNOS = sys.platform.startswith("sunos") or sys.platform.startswith("solaris")
AIX = sys.platform.startswith("aix")
# ===================================================================
# --- API constants
# ===================================================================
# Process.status()
STATUS_RUNNING = "running"
STATUS_SLEEPING = "sleeping"
STATUS_DISK_SLEEP = "disk-sleep"
@ -99,12 +40,10 @@ STATUS_ZOMBIE = "zombie"
STATUS_DEAD = "dead"
STATUS_WAKE_KILL = "wake-kill"
STATUS_WAKING = "waking"
STATUS_IDLE = "idle" # FreeBSD, OSX
STATUS_LOCKED = "locked" # FreeBSD
STATUS_WAITING = "waiting" # FreeBSD
STATUS_SUSPENDED = "suspended" # NetBSD
STATUS_IDLE = "idle" # BSD
STATUS_LOCKED = "locked" # BSD
STATUS_WAITING = "waiting" # BSD
# Process.connections() and psutil.net_connections()
CONN_ESTABLISHED = "ESTABLISHED"
CONN_SYN_SENT = "SYN_SENT"
CONN_SYN_RECV = "SYN_RECV"
@ -118,7 +57,6 @@ CONN_LISTEN = "LISTEN"
CONN_CLOSING = "CLOSING"
CONN_NONE = "NONE"
# net_if_stats()
if enum is None:
NIC_DUPLEX_FULL = 2
NIC_DUPLEX_HALF = 1
@ -131,105 +69,102 @@ else:
globals().update(NicDuplex.__members__)
# sensors_battery()
if enum is None:
POWER_TIME_UNKNOWN = -1
POWER_TIME_UNLIMITED = -2
else:
class BatteryTime(enum.IntEnum):
POWER_TIME_UNKNOWN = -1
POWER_TIME_UNLIMITED = -2
globals().update(BatteryTime.__members__)
# --- functions
# --- others
ENCODING = sys.getfilesystemencoding()
if not PY3:
ENCODING_ERRS = "replace"
else:
def usage_percent(used, total, _round=None):
"""Calculate percentage usage of 'used' against 'total'."""
try:
ENCODING_ERRS = sys.getfilesystemencodeerrors() # py 3.6
except AttributeError:
ENCODING_ERRS = "surrogateescape" if POSIX else "replace"
ret = (used / total) * 100
except ZeroDivisionError:
ret = 0
if _round is not None:
return round(ret, _round)
else:
return ret
# ===================================================================
# --- namedtuples
# ===================================================================
def memoize(fun):
"""A simple memoize decorator for functions supporting (hashable)
positional arguments.
It also provides a cache_clear() function for clearing the cache:
# --- for system functions
>>> @memoize
... def foo()
... return 1
...
>>> foo()
1
>>> foo.cache_clear()
>>>
"""
@functools.wraps(fun)
def wrapper(*args, **kwargs):
key = (args, frozenset(sorted(kwargs.items())))
lock.acquire()
try:
try:
return cache[key]
except KeyError:
ret = cache[key] = fun(*args, **kwargs)
finally:
lock.release()
return ret
# psutil.swap_memory()
sswap = namedtuple('sswap', ['total', 'used', 'free', 'percent', 'sin',
'sout'])
# psutil.disk_usage()
sdiskusage = namedtuple('sdiskusage', ['total', 'used', 'free', 'percent'])
# psutil.disk_io_counters()
sdiskio = namedtuple('sdiskio', ['read_count', 'write_count',
'read_bytes', 'write_bytes',
'read_time', 'write_time'])
# psutil.disk_partitions()
sdiskpart = namedtuple('sdiskpart', ['device', 'mountpoint', 'fstype', 'opts'])
# psutil.net_io_counters()
snetio = namedtuple('snetio', ['bytes_sent', 'bytes_recv',
'packets_sent', 'packets_recv',
'errin', 'errout',
'dropin', 'dropout'])
# psutil.users()
suser = namedtuple('suser', ['name', 'terminal', 'host', 'started', 'pid'])
# psutil.net_connections()
sconn = namedtuple('sconn', ['fd', 'family', 'type', 'laddr', 'raddr',
'status', 'pid'])
# psutil.net_if_addrs()
snic = namedtuple('snic', ['family', 'address', 'netmask', 'broadcast', 'ptp'])
# psutil.net_if_stats()
snicstats = namedtuple('snicstats', ['isup', 'duplex', 'speed', 'mtu'])
# psutil.cpu_stats()
scpustats = namedtuple(
'scpustats', ['ctx_switches', 'interrupts', 'soft_interrupts', 'syscalls'])
# psutil.cpu_freq()
scpufreq = namedtuple('scpufreq', ['current', 'min', 'max'])
# psutil.sensors_temperatures()
shwtemp = namedtuple(
'shwtemp', ['label', 'current', 'high', 'critical'])
# psutil.sensors_battery()
sbattery = namedtuple('sbattery', ['percent', 'secsleft', 'power_plugged'])
# psutil.sensors_battery()
sfan = namedtuple('sfan', ['label', 'current'])
def cache_clear():
"""Clear cache."""
lock.acquire()
try:
cache.clear()
finally:
lock.release()
# --- for Process methods
# psutil.Process.cpu_times()
pcputimes = namedtuple('pcputimes',
['user', 'system', 'children_user', 'children_system'])
# psutil.Process.open_files()
popenfile = namedtuple('popenfile', ['path', 'fd'])
# psutil.Process.threads()
pthread = namedtuple('pthread', ['id', 'user_time', 'system_time'])
# psutil.Process.uids()
puids = namedtuple('puids', ['real', 'effective', 'saved'])
# psutil.Process.gids()
pgids = namedtuple('pgids', ['real', 'effective', 'saved'])
# psutil.Process.io_counters()
pio = namedtuple('pio', ['read_count', 'write_count',
'read_bytes', 'write_bytes'])
# psutil.Process.ionice()
pionice = namedtuple('pionice', ['ioclass', 'value'])
# psutil.Process.ctx_switches()
pctxsw = namedtuple('pctxsw', ['voluntary', 'involuntary'])
# psutil.Process.connections()
pconn = namedtuple('pconn', ['fd', 'family', 'type', 'laddr', 'raddr',
'status'])
# psutil.connections() and psutil.Process.connections()
addr = namedtuple('addr', ['ip', 'port'])
lock = threading.RLock()
cache = {}
wrapper.cache_clear = cache_clear
return wrapper
def isfile_strict(path):
"""Same as os.path.isfile() but does not swallow EACCES / EPERM
exceptions, see:
http://mail.python.org/pipermail/python-dev/2012-June/120787.html
"""
try:
st = os.stat(path)
except OSError as err:
if err.errno in (errno.EPERM, errno.EACCES):
raise
return False
else:
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 = {
"all": ([AF_INET, AF_INET6, AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]),
@ -253,323 +188,59 @@ if AF_UNIX is not None:
"unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]),
})
del AF_INET, AF_UNIX, SOCK_STREAM, SOCK_DGRAM
del AF_INET, AF_INET6, AF_UNIX, SOCK_STREAM, SOCK_DGRAM
# ===================================================================
# --- utils
# ===================================================================
# --- namedtuples for psutil.* system-related functions
# psutil.swap_memory()
sswap = namedtuple('sswap', ['total', 'used', 'free', 'percent', 'sin',
'sout'])
# psutil.disk_usage()
sdiskusage = namedtuple('sdiskusage', ['total', 'used', 'free', 'percent'])
# psutil.disk_io_counters()
sdiskio = namedtuple('sdiskio', ['read_count', 'write_count',
'read_bytes', 'write_bytes',
'read_time', 'write_time'])
# psutil.disk_partitions()
sdiskpart = namedtuple('sdiskpart', ['device', 'mountpoint', 'fstype', 'opts'])
# psutil.net_io_counters()
snetio = namedtuple('snetio', ['bytes_sent', 'bytes_recv',
'packets_sent', 'packets_recv',
'errin', 'errout',
'dropin', 'dropout'])
# psutil.users()
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'])
def usage_percent(used, total, _round=None):
"""Calculate percentage usage of 'used' against 'total'."""
try:
ret = (used / total) * 100
except ZeroDivisionError:
ret = 0.0 if isinstance(used, float) or isinstance(total, float) else 0
if _round is not None:
return round(ret, _round)
else:
return ret
# --- namedtuples for psutil.Process methods
def memoize(fun):
"""A simple memoize decorator for functions supporting (hashable)
positional arguments.
It also provides a cache_clear() function for clearing the cache:
>>> @memoize
... def foo()
... return 1
...
>>> foo()
1
>>> foo.cache_clear()
>>>
"""
@functools.wraps(fun)
def wrapper(*args, **kwargs):
key = (args, frozenset(sorted(kwargs.items())))
try:
return cache[key]
except KeyError:
ret = cache[key] = fun(*args, **kwargs)
return ret
def cache_clear():
"""Clear cache."""
cache.clear()
cache = {}
wrapper.cache_clear = cache_clear
return wrapper
def memoize_when_activated(fun):
"""A memoize decorator which is disabled by default. It can be
activated and deactivated on request.
For efficiency reasons it can be used only against class methods
accepting no arguments.
>>> class Foo:
... @memoize
... def foo()
... print(1)
...
>>> f = Foo()
>>> # deactivated (default)
>>> foo()
1
>>> foo()
1
>>>
>>> # activated
>>> foo.cache_activate()
>>> foo()
1
>>> foo()
>>> foo()
>>>
"""
@functools.wraps(fun)
def wrapper(self):
if not wrapper.cache_activated:
return fun(self)
else:
try:
ret = cache[fun]
except KeyError:
ret = cache[fun] = fun(self)
return ret
def cache_activate():
"""Activate cache."""
wrapper.cache_activated = True
def cache_deactivate():
"""Deactivate and clear cache."""
wrapper.cache_activated = False
cache.clear()
cache = {}
wrapper.cache_activated = False
wrapper.cache_activate = cache_activate
wrapper.cache_deactivate = cache_deactivate
return wrapper
def isfile_strict(path):
"""Same as os.path.isfile() but does not swallow EACCES / EPERM
exceptions, see:
http://mail.python.org/pipermail/python-dev/2012-June/120787.html
"""
try:
st = os.stat(path)
except OSError as err:
if err.errno in (errno.EPERM, errno.EACCES):
raise
return False
else:
return stat.S_ISREG(st.st_mode)
def path_exists_strict(path):
"""Same as os.path.exists() but does not swallow EACCES / EPERM
exceptions, see:
http://mail.python.org/pipermail/python-dev/2012-June/120787.html
"""
try:
os.stat(path)
except OSError as err:
if err.errno in (errno.EPERM, errno.EACCES):
raise
return False
else:
return True
@memoize
def supports_ipv6():
"""Return True if IPv6 is supported on this platform."""
if not socket.has_ipv6 or AF_INET6 is None:
return False
try:
sock = socket.socket(AF_INET6, socket.SOCK_STREAM)
with contextlib.closing(sock):
sock.bind(("::1", 0))
return True
except socket.error:
return False
def parse_environ_block(data):
"""Parse a C environ block of environment variables into a dictionary."""
# The block is usually raw data from the target process. It might contain
# trailing garbage and lines that do not look like assignments.
ret = {}
pos = 0
# localize global variable to speed up access.
WINDOWS_ = WINDOWS
while True:
next_pos = data.find("\0", pos)
# nul byte at the beginning or double nul byte means finish
if next_pos <= pos:
break
# there might not be an equals sign
equal_pos = data.find("=", pos, next_pos)
if equal_pos > pos:
key = data[pos:equal_pos]
value = data[equal_pos + 1:next_pos]
# Windows expects environment variables to be uppercase only
if WINDOWS_:
key = key.upper()
ret[key] = value
pos = next_pos + 1
return ret
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
else: # pragma: no cover
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
else: # pragma: no cover
try:
return socket.AddressType(num)
except (ValueError, AttributeError):
return num
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 and will be removed; use %s() instead" % (
fun.__name__, replacement)
if fun.__doc__ is None:
fun.__doc__ = msg
@functools.wraps(fun)
def inner(self, *args, **kwargs):
warnings.warn(msg, category=FutureWarning, stacklevel=2)
return getattr(self, replacement)(*args, **kwargs)
return inner
return outer
class _WrapNumbers:
"""Watches numbers so that they don't overflow and wrap
(reset to zero).
"""
def __init__(self):
self.lock = threading.Lock()
self.cache = {}
self.reminders = {}
self.reminder_keys = {}
def _add_dict(self, input_dict, name):
assert name not in self.cache
assert name not in self.reminders
assert name not in self.reminder_keys
self.cache[name] = input_dict
self.reminders[name] = defaultdict(int)
self.reminder_keys[name] = defaultdict(set)
def _remove_dead_reminders(self, input_dict, name):
"""In case the number of keys changed between calls (e.g. a
disk disappears) this removes the entry from self.reminders.
"""
old_dict = self.cache[name]
gone_keys = set(old_dict.keys()) - set(input_dict.keys())
for gone_key in gone_keys:
for remkey in self.reminder_keys[name][gone_key]:
del self.reminders[name][remkey]
del self.reminder_keys[name][gone_key]
def run(self, input_dict, name):
"""Cache dict and sum numbers which overflow and wrap.
Return an updated copy of `input_dict`
"""
if name not in self.cache:
# This was the first call.
self._add_dict(input_dict, name)
return input_dict
self._remove_dead_reminders(input_dict, name)
old_dict = self.cache[name]
new_dict = {}
for key in input_dict.keys():
input_tuple = input_dict[key]
try:
old_tuple = old_dict[key]
except KeyError:
# The input dict has a new key (e.g. a new disk or NIC)
# which didn't exist in the previous call.
new_dict[key] = input_tuple
continue
bits = []
for i in range(len(input_tuple)):
input_value = input_tuple[i]
old_value = old_tuple[i]
remkey = (key, i)
if input_value < old_value:
# it wrapped!
self.reminders[name][remkey] += old_value
self.reminder_keys[name][key].add(remkey)
bits.append(input_value + self.reminders[name][remkey])
new_dict[key] = tuple(bits)
self.cache[name] = input_dict
return new_dict
def cache_clear(self, name=None):
"""Clear the internal cache, optionally only for function 'name'."""
with self.lock:
if name is None:
self.cache.clear()
self.reminders.clear()
self.reminder_keys.clear()
else:
self.cache.pop(name, None)
self.reminders.pop(name, None)
self.reminder_keys.pop(name, None)
def cache_info(self):
"""Return internal cache dicts as a tuple of 3 elements."""
with self.lock:
return (self.cache, self.reminders, self.reminder_keys)
def wrap_numbers(input_dict, name):
"""Given an `input_dict` and a function `name`, adjust the numbers
which "wrap" (restart from zero) across different calls by adding
"old value" to "new value" and return an updated dict.
"""
with _wn.lock:
return _wn.run(input_dict, name)
_wn = _WrapNumbers()
wrap_numbers.cache_clear = _wn.cache_clear
wrap_numbers.cache_info = _wn.cache_info
# psutil.Process.memory_info()
pmem = namedtuple('pmem', ['rss', 'vms'])
# psutil.Process.cpu_times()
pcputimes = namedtuple('pcputimes', ['user', 'system'])
# psutil.Process.open_files()
popenfile = namedtuple('popenfile', ['path', 'fd'])
# psutil.Process.threads()
pthread = namedtuple('pthread', ['id', 'user_time', 'system_time'])
# psutil.Process.uids()
puids = namedtuple('puids', ['real', 'effective', 'saved'])
# psutil.Process.gids()
pgids = namedtuple('pgids', ['real', 'effective', 'saved'])
# psutil.Process.io_counters()
pio = namedtuple('pio', ['read_count', 'write_count',
'read_bytes', 'write_bytes'])
# psutil.Process.ionice()
pionice = namedtuple('pionice', ['ioclass', 'value'])
# psutil.Process.ctx_switches()
pctxsw = namedtuple('pctxsw', ['voluntary', 'involuntary'])
# psutil.Process.connections()
pconn = namedtuple('pconn', ['fd', 'family', 'type', 'laddr', 'raddr',
'status'])

View File

@ -1,3 +1,5 @@
#!/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.
@ -6,11 +8,9 @@
import collections
import functools
import os
import sys
__all__ = ["PY3", "long", "xrange", "unicode", "basestring", "u", "b",
"callable", "lru_cache", "which"]
__all__ = ["PY3", "long", "xrange", "unicode", "callable", "lru_cache"]
PY3 = sys.version_info[0] == 3
@ -18,25 +18,17 @@ if PY3:
long = int
xrange = range
unicode = str
basestring = str
def u(s):
return s
def b(s):
return s.encode("latin-1")
else:
long = long
xrange = xrange
unicode = unicode
basestring = basestring
def u(s):
return unicode(s, "unicode_escape")
def b(s):
return s
# removed in 3.0, reintroduced in 3.2
try:
@ -195,55 +187,3 @@ except ImportError:
return functools.update_wrapper(wrapper, user_function)
return decorating_function
# python 3.3
try:
from shutil import which
except ImportError:
def which(cmd, mode=os.F_OK | os.X_OK, path=None):
"""Given a command, mode, and a PATH string, return the path which
conforms to the given mode on the PATH, or None if there is no such
file.
`mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
of os.environ.get("PATH"), or can be overridden with a custom search
path.
"""
def _access_check(fn, mode):
return (os.path.exists(fn) and os.access(fn, mode) and
not os.path.isdir(fn))
if os.path.dirname(cmd):
if _access_check(cmd, mode):
return cmd
return None
if path is None:
path = os.environ.get("PATH", os.defpath)
if not path:
return None
path = path.split(os.pathsep)
if sys.platform == "win32":
if os.curdir not in path:
path.insert(0, os.curdir)
pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
files = [cmd]
else:
files = [cmd + ext for ext in pathext]
else:
files = [cmd]
seen = set()
for dir in path:
normdir = os.path.normcase(dir)
if normdir not in seen:
seen.add(normdir)
for thefile in files:
name = os.path.join(dir, thefile)
if _access_check(name, mode):
return name
return None

View File

@ -1,94 +0,0 @@
# 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.
class Error(Exception):
"""Base exception class. All other psutil exceptions inherit
from this one.
"""
def __init__(self, msg=""):
Exception.__init__(self, msg)
self.msg = msg
def __repr__(self):
ret = "psutil.%s %s" % (self.__class__.__name__, self.msg)
return ret.strip()
__str__ = __repr__
class NoSuchProcess(Error):
"""Exception raised when a process with a certain PID doesn't
or no longer exists.
"""
def __init__(self, pid, name=None, msg=None):
Error.__init__(self, msg)
self.pid = pid
self.name = name
self.msg = msg
if msg is None:
if name:
details = "(pid=%s, name=%s)" % (self.pid, repr(self.name))
else:
details = "(pid=%s)" % self.pid
self.msg = "process no longer exists " + details
class ZombieProcess(NoSuchProcess):
"""Exception raised when querying a zombie process. This is
raised on OSX, BSD and Solaris only, and not always: depending
on the query the OS may be able to succeed anyway.
On Linux all zombie processes are querable (hence this is never
raised). Windows doesn't have zombie processes.
"""
def __init__(self, pid, name=None, ppid=None, msg=None):
NoSuchProcess.__init__(self, msg)
self.pid = pid
self.ppid = ppid
self.name = name
self.msg = msg
if msg is None:
args = ["pid=%s" % pid]
if name:
args.append("name=%s" % repr(self.name))
if ppid:
args.append("ppid=%s" % self.ppid)
details = "(%s)" % ", ".join(args)
self.msg = "process still exists but it's a zombie " + details
class AccessDenied(Error):
"""Exception raised when permission to perform an action is denied."""
def __init__(self, pid=None, name=None, msg=None):
Error.__init__(self, msg)
self.pid = pid
self.name = name
self.msg = msg
if msg is None:
if (pid is not None) and (name is not None):
self.msg = "(pid=%s, name=%s)" % (pid, repr(name))
elif (pid is not None):
self.msg = "(pid=%s)" % self.pid
else:
self.msg = ""
class TimeoutExpired(Error):
"""Raised on Process.wait(timeout) if timeout expires and process
is still alive.
"""
def __init__(self, seconds, pid=None, name=None):
Error.__init__(self, "timeout after %s seconds" % seconds)
self.seconds = seconds
self.pid = pid
self.name = name
if (pid is not None) and (name is not None):
self.msg += " (pid=%s, name=%s)" % (pid, repr(name))
elif (pid is not None):
self.msg += " (pid=%s)" % self.pid

View File

@ -1,573 +0,0 @@
# Copyright (c) 2009, Giampaolo Rodola'
# Copyright (c) 2017, Arnon Yaari
# All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""AIX platform implementation."""
import errno
import glob
import os
import re
import subprocess
import sys
from collections import namedtuple
from socket import AF_INET
from . import _common
from . import _psposix
from . import _psutil_aix as cext
from . import _psutil_posix as cext_posix
from ._common import AF_INET6
from ._common import memoize_when_activated
from ._common import NIC_DUPLEX_FULL
from ._common import NIC_DUPLEX_HALF
from ._common import NIC_DUPLEX_UNKNOWN
from ._common import sockfam_to_enum
from ._common import socktype_to_enum
from ._common import usage_percent
from ._compat import PY3
from ._exceptions import AccessDenied
from ._exceptions import NoSuchProcess
from ._exceptions import ZombieProcess
__extra__all__ = ["PROCFS_PATH"]
# =====================================================================
# --- globals
# =====================================================================
HAS_THREADS = hasattr(cext, "proc_threads")
PAGE_SIZE = os.sysconf('SC_PAGE_SIZE')
AF_LINK = cext_posix.AF_LINK
PROC_STATUSES = {
cext.SIDL: _common.STATUS_IDLE,
cext.SZOMB: _common.STATUS_ZOMBIE,
cext.SACTIVE: _common.STATUS_RUNNING,
cext.SSWAP: _common.STATUS_RUNNING, # TODO what status is this?
cext.SSTOP: _common.STATUS_STOPPED,
}
TCP_STATUSES = {
cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT,
cext.TCPS_SYN_RCVD: _common.CONN_SYN_RECV,
cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1,
cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2,
cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT,
cext.TCPS_CLOSED: _common.CONN_CLOSE,
cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT,
cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK,
cext.TCPS_LISTEN: _common.CONN_LISTEN,
cext.TCPS_CLOSING: _common.CONN_CLOSING,
cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
}
proc_info_map = dict(
ppid=0,
rss=1,
vms=2,
create_time=3,
nice=4,
num_threads=5,
status=6,
ttynr=7)
# =====================================================================
# --- named tuples
# =====================================================================
# psutil.Process.memory_info()
pmem = namedtuple('pmem', ['rss', 'vms'])
# psutil.Process.memory_full_info()
pfullmem = pmem
# psutil.Process.cpu_times()
scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait'])
# psutil.virtual_memory()
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
# psutil.Process.memory_maps(grouped=True)
pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss', 'anon', 'locked'])
# psutil.Process.memory_maps(grouped=False)
pmmap_ext = namedtuple(
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
# =====================================================================
# --- utils
# =====================================================================
def get_procfs_path():
"""Return updated psutil.PROCFS_PATH constant."""
return sys.modules['psutil'].PROCFS_PATH
# =====================================================================
# --- memory
# =====================================================================
def virtual_memory():
total, avail, free, pinned, inuse = cext.virtual_mem()
percent = usage_percent((total - avail), total, _round=1)
return svmem(total, avail, percent, inuse, free)
def swap_memory():
"""Swap system memory as a (total, used, free, sin, sout) tuple."""
total, free, sin, sout = cext.swap_mem()
used = total - free
percent = usage_percent(used, total, _round=1)
return _common.sswap(total, used, free, percent, sin, sout)
# =====================================================================
# --- CPU
# =====================================================================
def cpu_times():
"""Return system-wide CPU times as a named tuple"""
ret = cext.per_cpu_times()
return scputimes(*[sum(x) for x in zip(*ret)])
def per_cpu_times():
"""Return system per-CPU times as a list of named tuples"""
ret = cext.per_cpu_times()
return [scputimes(*x) for x in ret]
def cpu_count_logical():
"""Return the number of logical CPUs in the system."""
try:
return os.sysconf("SC_NPROCESSORS_ONLN")
except ValueError:
# mimic os.cpu_count() behavior
return None
def cpu_count_physical():
cmd = "lsdev -Cc processor"
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if PY3:
stdout, stderr = [x.decode(sys.stdout.encoding)
for x in (stdout, stderr)]
if p.returncode != 0:
raise RuntimeError("%r command error\n%s" % (cmd, stderr))
processors = stdout.strip().splitlines()
return len(processors) or None
def cpu_stats():
"""Return various CPU stats as a named tuple."""
ctx_switches, interrupts, soft_interrupts, syscalls = cext.cpu_stats()
return _common.scpustats(
ctx_switches, interrupts, soft_interrupts, syscalls)
# =====================================================================
# --- disks
# =====================================================================
disk_io_counters = cext.disk_io_counters
disk_usage = _psposix.disk_usage
def disk_partitions(all=False):
"""Return system disk partitions."""
# TODO - the filtering logic should be better checked so that
# it tries to reflect 'df' as much as possible
retlist = []
partitions = cext.disk_partitions()
for partition in partitions:
device, mountpoint, fstype, opts = partition
if device == 'none':
device = ''
if not all:
# Differently from, say, Linux, we don't have a list of
# common fs types so the best we can do, AFAIK, is to
# filter by filesystem having a total size > 0.
if not disk_usage(mountpoint).total:
continue
ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
retlist.append(ntuple)
return retlist
# =====================================================================
# --- network
# =====================================================================
net_if_addrs = cext_posix.net_if_addrs
net_io_counters = cext.net_io_counters
def net_connections(kind, _pid=-1):
"""Return socket connections. If pid == -1 return system-wide
connections (as opposed to connections opened by one process only).
"""
cmap = _common.conn_tmap
if kind not in cmap:
raise ValueError("invalid %r kind argument; choose between %s"
% (kind, ', '.join([repr(x) for x in cmap])))
families, types = _common.conn_tmap[kind]
rawlist = cext.net_connections(_pid)
ret = set()
for item in rawlist:
fd, fam, type_, laddr, raddr, status, pid = item
if fam not in families:
continue
if type_ not in types:
continue
status = TCP_STATUSES[status]
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
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.add(nt)
return list(ret)
def net_if_stats():
"""Get NIC stats (isup, duplex, speed, mtu)."""
duplex_map = {"Full": NIC_DUPLEX_FULL,
"Half": NIC_DUPLEX_HALF}
names = set([x[0] for x in net_if_addrs()])
ret = {}
for name in names:
isup, mtu = cext.net_if_stats(name)
# try to get speed and duplex
# TODO: rewrite this in C (entstat forks, so use truss -f to follow.
# looks like it is using an undocumented ioctl?)
duplex = ""
speed = 0
p = subprocess.Popen(["/usr/bin/entstat", "-d", name],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if PY3:
stdout, stderr = [x.decode(sys.stdout.encoding)
for x in (stdout, stderr)]
if p.returncode == 0:
re_result = re.search("Running: (\d+) Mbps.*?(\w+) Duplex", stdout)
if re_result is not None:
speed = int(re_result.group(1))
duplex = re_result.group(2)
duplex = duplex_map.get(duplex, NIC_DUPLEX_UNKNOWN)
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
return ret
# =====================================================================
# --- other system functions
# =====================================================================
def boot_time():
"""The system boot time expressed in seconds since the epoch."""
return cext.boot_time()
def users():
"""Return currently connected users as a list of namedtuples."""
retlist = []
rawlist = cext.users()
localhost = (':0.0', ':0')
for item in rawlist:
user, tty, hostname, tstamp, user_process, pid = item
# note: the underlying C function includes entries about
# system boot, run level and others. We might want
# to use them in the future.
if not user_process:
continue
if hostname in localhost:
hostname = 'localhost'
nt = _common.suser(user, tty, hostname, tstamp, pid)
retlist.append(nt)
return retlist
# =====================================================================
# --- processes
# =====================================================================
def pids():
"""Returns a list of PIDs currently running on the system."""
return [int(x) for x in os.listdir(get_procfs_path()) if x.isdigit()]
def pid_exists(pid):
"""Check for the existence of a unix pid."""
return os.path.exists(os.path.join(get_procfs_path(), str(pid), "psinfo"))
def wrap_exceptions(fun):
"""Call callable into a try/except clause and translate ENOENT,
EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
"""
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except EnvironmentError as err:
# support for private module import
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.
if err.errno in (errno.ENOENT, errno.ESRCH):
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
return wrapper
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_name", "_ppid", "_procfs_path"]
def __init__(self, pid):
self.pid = pid
self._name = None
self._ppid = None
self._procfs_path = get_procfs_path()
def oneshot_enter(self):
self._proc_name_and_args.cache_activate()
self._proc_basic_info.cache_activate()
self._proc_cred.cache_activate()
def oneshot_exit(self):
self._proc_name_and_args.cache_deactivate()
self._proc_basic_info.cache_deactivate()
self._proc_cred.cache_deactivate()
@memoize_when_activated
def _proc_name_and_args(self):
return cext.proc_name_and_args(self.pid, self._procfs_path)
@memoize_when_activated
def _proc_basic_info(self):
return cext.proc_basic_info(self.pid, self._procfs_path)
@memoize_when_activated
def _proc_cred(self):
return cext.proc_cred(self.pid, self._procfs_path)
@wrap_exceptions
def name(self):
if self.pid == 0:
return "swapper"
# note: this is limited to 15 characters
return self._proc_name_and_args()[0].rstrip("\x00")
@wrap_exceptions
def exe(self):
# there is no way to get executable path in AIX other than to guess,
# and guessing is more complex than what's in the wrapping class
exe = self.cmdline()[0]
if os.path.sep in exe:
# relative or absolute path
if not os.path.isabs(exe):
# if cwd has changed, we're out of luck - this may be wrong!
exe = os.path.abspath(os.path.join(self.cwd(), exe))
if (os.path.isabs(exe) and
os.path.isfile(exe) and
os.access(exe, os.X_OK)):
return exe
# not found, move to search in PATH using basename only
exe = os.path.basename(exe)
# search for exe name PATH
for path in os.environ["PATH"].split(":"):
possible_exe = os.path.abspath(os.path.join(path, exe))
if (os.path.isfile(possible_exe) and
os.access(possible_exe, os.X_OK)):
return possible_exe
return ''
@wrap_exceptions
def cmdline(self):
return self._proc_name_and_args()[1].split(' ')
@wrap_exceptions
def create_time(self):
return self._proc_basic_info()[proc_info_map['create_time']]
@wrap_exceptions
def num_threads(self):
return self._proc_basic_info()[proc_info_map['num_threads']]
if HAS_THREADS:
@wrap_exceptions
def threads(self):
rawlist = cext.proc_threads(self.pid)
retlist = []
for thread_id, utime, stime in rawlist:
ntuple = _common.pthread(thread_id, utime, stime)
retlist.append(ntuple)
# The underlying C implementation retrieves all OS threads
# and filters them by PID. At this point we can't tell whether
# an empty list means there were no connections for process or
# process is no longer active so we force NSP in case the PID
# is no longer there.
if not retlist:
# will raise NSP if process is gone
os.stat('%s/%s' % (self._procfs_path, self.pid))
return retlist
@wrap_exceptions
def connections(self, kind='inet'):
ret = net_connections(kind, _pid=self.pid)
# The underlying C implementation retrieves all OS connections
# and filters them by PID. At this point we can't tell whether
# an empty list means there were no connections for process or
# process is no longer active so we force NSP in case the PID
# is no longer there.
if not ret:
# will raise NSP if process is gone
os.stat('%s/%s' % (self._procfs_path, self.pid))
return ret
@wrap_exceptions
def nice_get(self):
return cext_posix.getpriority(self.pid)
@wrap_exceptions
def nice_set(self, value):
return cext_posix.setpriority(self.pid, value)
@wrap_exceptions
def ppid(self):
self._ppid = self._proc_basic_info()[proc_info_map['ppid']]
return self._ppid
@wrap_exceptions
def uids(self):
real, effective, saved, _, _, _ = self._proc_cred()
return _common.puids(real, effective, saved)
@wrap_exceptions
def gids(self):
_, _, _, real, effective, saved = self._proc_cred()
return _common.puids(real, effective, saved)
@wrap_exceptions
def cpu_times(self):
cpu_times = cext.proc_cpu_times(self.pid, self._procfs_path)
return _common.pcputimes(*cpu_times)
@wrap_exceptions
def terminal(self):
ttydev = self._proc_basic_info()[proc_info_map['ttynr']]
# convert from 64-bit dev_t to 32-bit dev_t and then map the device
ttydev = (((ttydev & 0x0000FFFF00000000) >> 16) | (ttydev & 0xFFFF))
# try to match rdev of /dev/pts/* files ttydev
for dev in glob.glob("/dev/**/*"):
if os.stat(dev).st_rdev == ttydev:
return dev
return None
@wrap_exceptions
def cwd(self):
procfs_path = self._procfs_path
try:
result = os.readlink("%s/%s/cwd" % (procfs_path, self.pid))
return result.rstrip('/')
except OSError as err:
if err.errno == errno.ENOENT:
os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD
return None
raise
@wrap_exceptions
def memory_info(self):
ret = self._proc_basic_info()
rss = ret[proc_info_map['rss']] * 1024
vms = ret[proc_info_map['vms']] * 1024
return pmem(rss, vms)
memory_full_info = memory_info
@wrap_exceptions
def status(self):
code = self._proc_basic_info()[proc_info_map['status']]
# XXX is '?' legit? (we're not supposed to return it anyway)
return PROC_STATUSES.get(code, '?')
def open_files(self):
# TODO rewrite without using procfiles (stat /proc/pid/fd/* and then
# find matching name of the inode)
p = subprocess.Popen(["/usr/bin/procfiles", "-n", str(self.pid)],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if PY3:
stdout, stderr = [x.decode(sys.stdout.encoding)
for x in (stdout, stderr)]
if "no such process" in stderr.lower():
raise NoSuchProcess(self.pid, self._name)
procfiles = re.findall("(\d+): S_IFREG.*\s*.*name:(.*)\n", stdout)
retlist = []
for fd, path in procfiles:
path = path.strip()
if path.startswith("//"):
path = path[1:]
if path.lower() == "cannot be retrieved":
continue
retlist.append(_common.popenfile(path, int(fd)))
return retlist
@wrap_exceptions
def num_fds(self):
if self.pid == 0: # no /proc/0/fd
return 0
return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid)))
@wrap_exceptions
def num_ctx_switches(self):
return _common.pctxsw(
*cext.proc_num_ctx_switches(self.pid))
@wrap_exceptions
def wait(self, timeout=None):
return _psposix.wait_pid(self.pid, timeout, self._name)
@wrap_exceptions
def io_counters(self):
try:
rc, wc, rb, wb = cext.proc_io_counters(self.pid)
except OSError:
# if process is terminated, proc_io_counters returns OSError
# instead of NSP
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
raise
return _common.pio(rc, wc, rb, wb)

View File

@ -1,86 +1,38 @@
#!/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.
"""FreeBSD, OpenBSD and NetBSD platforms implementation."""
"""FreeBSD platform implementation."""
import contextlib
import errno
import functools
import os
import xml.etree.ElementTree as ET
from collections import namedtuple
from socket import AF_INET
from . import _common
from . import _psposix
from . import _psutil_bsd as cext
from . import _psutil_posix as cext_posix
from ._common import AF_INET6
from ._common import conn_tmap
from ._common import FREEBSD
from ._common import memoize
from ._common import memoize_when_activated
from ._common import NETBSD
from ._common import OPENBSD
from ._common import sockfam_to_enum
from ._common import conn_tmap, usage_percent, sockfam_to_enum
from ._common import socktype_to_enum
from ._common import usage_percent
from ._compat import which
from ._exceptions import AccessDenied
from ._exceptions import NoSuchProcess
from ._exceptions import ZombieProcess
__extra__all__ = []
# --- constants
# =====================================================================
# --- globals
# =====================================================================
if FREEBSD:
PROC_STATUSES = {
cext.SIDL: _common.STATUS_IDLE,
cext.SRUN: _common.STATUS_RUNNING,
cext.SSLEEP: _common.STATUS_SLEEPING,
cext.SSTOP: _common.STATUS_STOPPED,
cext.SZOMB: _common.STATUS_ZOMBIE,
cext.SWAIT: _common.STATUS_WAITING,
cext.SLOCK: _common.STATUS_LOCKED,
}
elif OPENBSD or NETBSD:
PROC_STATUSES = {
cext.SIDL: _common.STATUS_IDLE,
cext.SSLEEP: _common.STATUS_SLEEPING,
cext.SSTOP: _common.STATUS_STOPPED,
# According to /usr/include/sys/proc.h SZOMB is unused.
# test_zombie_process() shows that SDEAD is the right
# equivalent. Also it appears there's no equivalent of
# psutil.STATUS_DEAD. SDEAD really means STATUS_ZOMBIE.
# cext.SZOMB: _common.STATUS_ZOMBIE,
cext.SDEAD: _common.STATUS_ZOMBIE,
cext.SZOMB: _common.STATUS_ZOMBIE,
# From http://www.eecs.harvard.edu/~margo/cs161/videos/proc.h.txt
# OpenBSD has SRUN and SONPROC: SRUN indicates that a process
# is runnable but *not* yet running, i.e. is on a run queue.
# SONPROC indicates that the process is actually executing on
# a CPU, i.e. it is no longer on a run queue.
# As such we'll map SRUN to STATUS_WAKING and SONPROC to
# STATUS_RUNNING
cext.SRUN: _common.STATUS_WAKING,
cext.SONPROC: _common.STATUS_RUNNING,
}
elif NETBSD:
PROC_STATUSES = {
cext.SIDL: _common.STATUS_IDLE,
cext.SACTIVE: _common.STATUS_RUNNING,
cext.SDYING: _common.STATUS_ZOMBIE,
cext.SSTOP: _common.STATUS_STOPPED,
cext.SZOMB: _common.STATUS_ZOMBIE,
cext.SDEAD: _common.STATUS_DEAD,
cext.SSUSPENDED: _common.STATUS_SUSPENDED, # unique to NetBSD
}
PROC_STATUSES = {
cext.SSTOP: _common.STATUS_STOPPED,
cext.SSLEEP: _common.STATUS_SLEEPING,
cext.SRUN: _common.STATUS_RUNNING,
cext.SIDL: _common.STATUS_IDLE,
cext.SWAIT: _common.STATUS_WAITING,
cext.SLOCK: _common.STATUS_LOCKED,
cext.SZOMB: _common.STATUS_ZOMBIE,
}
TCP_STATUSES = {
cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
@ -97,95 +49,32 @@ TCP_STATUSES = {
cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
}
if NETBSD:
PAGESIZE = os.sysconf("SC_PAGESIZE")
else:
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
AF_LINK = cext_posix.AF_LINK
kinfo_proc_map = dict(
ppid=0,
status=1,
real_uid=2,
effective_uid=3,
saved_uid=4,
real_gid=5,
effective_gid=6,
saved_gid=7,
ttynr=8,
create_time=9,
ctx_switches_vol=10,
ctx_switches_unvol=11,
read_io_count=12,
write_io_count=13,
user_time=14,
sys_time=15,
ch_user_time=16,
ch_sys_time=17,
rss=18,
vms=19,
memtext=20,
memdata=21,
memstack=22,
cpunum=23,
name=24,
)
# =====================================================================
# --- named tuples
# =====================================================================
# psutil.virtual_memory()
# extend base mem ntuple with BSD-specific memory metrics
svmem = namedtuple(
'svmem', ['total', 'available', 'percent', 'used', 'free',
'active', 'inactive', 'buffers', 'cached', 'shared', 'wired'])
# psutil.cpu_times()
scputimes = namedtuple(
'scputimes', ['user', 'nice', 'system', 'idle', 'irq'])
# psutil.Process.memory_info()
pmem = namedtuple('pmem', ['rss', 'vms', 'text', 'data', 'stack'])
# psutil.Process.memory_full_info()
pfullmem = pmem
# psutil.Process.cpu_times()
pcputimes = namedtuple('pcputimes',
['user', 'system', 'children_user', 'children_system'])
# psutil.Process.memory_maps(grouped=True)
pextmem = namedtuple('pextmem', ['rss', 'vms', 'text', 'data', 'stack'])
pmmap_grouped = namedtuple(
'pmmap_grouped', 'path rss, private, ref_count, shadow_count')
# psutil.Process.memory_maps(grouped=False)
pmmap_ext = namedtuple(
'pmmap_ext', 'addr, perms path rss, private, ref_count, shadow_count')
# psutil.disk_io_counters()
if FREEBSD:
sdiskio = namedtuple('sdiskio', ['read_count', 'write_count',
'read_bytes', 'write_bytes',
'read_time', 'write_time',
'busy_time'])
else:
sdiskio = namedtuple('sdiskio', ['read_count', 'write_count',
'read_bytes', 'write_bytes'])
# =====================================================================
# --- memory
# =====================================================================
# set later from __init__.py
NoSuchProcess = None
ZombieProcess = None
AccessDenied = None
TimeoutExpired = None
def virtual_memory():
"""System virtual memory as a namedtuple."""
mem = cext.virtual_mem()
total, free, active, inactive, wired, cached, buffers, shared = mem
if NETBSD:
# On NetBSD buffers and shared mem is determined via /proc.
# The C ext set them to 0.
with open('/proc/meminfo', 'rb') as f:
for line in f:
if line.startswith(b'Buffers:'):
buffers = int(line.split()[1]) * 1024
elif line.startswith(b'MemShared:'):
shared = int(line.split()[1]) * 1024
avail = inactive + cached + free
used = active + wired + cached
percent = usage_percent((total - avail), total, _round=1)
@ -195,16 +84,11 @@ def virtual_memory():
def swap_memory():
"""System swap memory as (total, used, free, sin, sout) namedtuple."""
total, used, free, sin, sout = cext.swap_mem()
total, used, free, sin, sout = [x * PAGESIZE for x in cext.swap_mem()]
percent = usage_percent(used, total, _round=1)
return _common.sswap(total, used, free, percent, sin, sout)
# =====================================================================
# --- CPU
# =====================================================================
def cpu_times():
"""Return system per-CPU times as a namedtuple"""
user, nice, system, idle, irq = cext.cpu_times()
@ -229,7 +113,6 @@ else:
# crash at psutil import time.
# Next calls will fail with NotImplementedError
def per_cpu_times():
"""Return system CPU times as a namedtuple"""
if cpu_count_logical() == 1:
return [cpu_times()]
if per_cpu_times.__called__:
@ -245,140 +128,73 @@ def cpu_count_logical():
return cext.cpu_count_logical()
if OPENBSD or NETBSD:
def cpu_count_physical():
# OpenBSD and NetBSD do not implement this.
return 1 if cpu_count_logical() == 1 else None
else:
def cpu_count_physical():
"""Return the number of physical CPUs in the system."""
# From the C module we'll get an XML string similar to this:
# http://manpages.ubuntu.com/manpages/precise/man4/smp.4freebsd.html
# 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]
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 cpu_count_physical():
"""Return the number of physical CPUs in the system."""
# From the C module we'll get an XML string similar to this:
# http://manpages.ubuntu.com/manpages/precise/man4/smp.4freebsd.html
# 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]
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 cpu_stats():
"""Return various CPU stats as a named tuple."""
if FREEBSD:
# Note: the C ext is returning some metrics we are not exposing:
# traps.
ctxsw, intrs, soft_intrs, syscalls, traps = cext.cpu_stats()
elif NETBSD:
# XXX
# Note about intrs: the C extension returns 0. intrs
# can be determined via /proc/stat; it has the same value as
# soft_intrs thought so the kernel is faking it (?).
#
# Note about syscalls: the C extension always sets it to 0 (?).
#
# Note: the C ext is returning some metrics we are not exposing:
# traps, faults and forks.
ctxsw, intrs, soft_intrs, syscalls, traps, faults, forks = \
cext.cpu_stats()
with open('/proc/stat', 'rb') as f:
for line in f:
if line.startswith(b'intr'):
intrs = int(line.split()[1])
elif OPENBSD:
# Note: the C ext is returning some metrics we are not exposing:
# traps, faults and forks.
ctxsw, intrs, soft_intrs, syscalls, traps, faults, forks = \
cext.cpu_stats()
return _common.scpustats(ctxsw, intrs, soft_intrs, syscalls)
# =====================================================================
# --- disks
# =====================================================================
def boot_time():
"""The system boot time expressed in seconds since the epoch."""
return cext.boot_time()
def disk_partitions(all=False):
"""Return mounted disk partitions as a list of namedtuples.
'all' argument is ignored, see:
https://github.com/giampaolo/psutil/issues/906
"""
retlist = []
partitions = cext.disk_partitions()
for partition in partitions:
device, mountpoint, fstype, opts = partition
if device == 'none':
device = ''
if not all:
if not os.path.isabs(device) or not os.path.exists(device):
continue
ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
retlist.append(ntuple)
return retlist
disk_usage = _psposix.disk_usage
disk_io_counters = cext.disk_io_counters
# =====================================================================
# --- network
# =====================================================================
net_io_counters = cext.net_io_counters
net_if_addrs = cext_posix.net_if_addrs
def net_if_stats():
"""Get NIC stats (isup, duplex, speed, mtu)."""
names = net_io_counters().keys()
ret = {}
for name in names:
mtu = cext_posix.net_if_mtu(name)
isup = cext_posix.net_if_flags(name)
duplex, speed = cext_posix.net_if_duplex_speed(name)
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
return ret
def users():
retlist = []
rawlist = cext.users()
for item in rawlist:
user, tty, hostname, tstamp = item
if tty == '~':
continue # reboot or shutdown
nt = _common.suser(user, tty or None, hostname, tstamp)
retlist.append(nt)
return retlist
def net_connections(kind):
"""System-wide network connections."""
if OPENBSD:
ret = []
for pid in pids():
try:
cons = Process(pid).connections(kind)
except (NoSuchProcess, ZombieProcess):
continue
else:
for conn in cons:
conn = list(conn)
conn.append(pid)
ret.append(_common.sconn(*conn))
return ret
if kind not in _common.conn_tmap:
raise ValueError("invalid %r kind argument; choose between %s"
% (kind, ', '.join([repr(x) for x in conn_tmap])))
families, types = conn_tmap[kind]
ret = set()
if NETBSD:
rawlist = cext.net_connections(-1)
else:
rawlist = cext.net_connections()
rawlist = cext.net_connections()
for item in rawlist:
fd, fam, type, laddr, raddr, status, pid = item
# TODO: apply filter at C level
@ -391,11 +207,6 @@ def net_connections(kind):
# have a very short lifetime so maybe the kernel
# can't initialize their status?
status = TCP_STATUSES[cext.PSUTIL_CONN_NONE]
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
fam = sockfam_to_enum(fam)
type = socktype_to_enum(type)
nt = _common.sconn(fd, fam, type, laddr, raddr, status, pid)
@ -403,95 +214,24 @@ def net_connections(kind):
return list(ret)
# =====================================================================
# --- sensors
# =====================================================================
if FREEBSD:
def sensors_battery():
"""Return battery info."""
try:
percent, minsleft, power_plugged = cext.sensors_battery()
except NotImplementedError:
# See: https://github.com/giampaolo/psutil/issues/1074
return None
power_plugged = power_plugged == 1
if power_plugged:
secsleft = _common.POWER_TIME_UNLIMITED
elif minsleft == -1:
secsleft = _common.POWER_TIME_UNKNOWN
else:
secsleft = minsleft * 60
return _common.sbattery(percent, secsleft, power_plugged)
# =====================================================================
# --- other system functions
# =====================================================================
def boot_time():
"""The system boot time expressed in seconds since the epoch."""
return cext.boot_time()
def users():
"""Return currently connected users as a list of namedtuples."""
retlist = []
rawlist = cext.users()
for item in rawlist:
user, tty, hostname, tstamp, pid = item
if pid == -1:
assert OPENBSD
pid = None
if tty == '~':
continue # reboot or shutdown
nt = _common.suser(user, tty or None, hostname, tstamp, pid)
retlist.append(nt)
return retlist
# =====================================================================
# --- processes
# =====================================================================
@memoize
def _pid_0_exists():
try:
Process(0).name()
except NoSuchProcess:
return False
except AccessDenied:
return True
else:
return True
def pids():
"""Returns a list of PIDs currently running on the system."""
ret = cext.pids()
if OPENBSD and (0 not in ret) and _pid_0_exists():
# On OpenBSD the kernel does not return PID 0 (neither does
# ps) but it's actually querable (Process(0) will succeed).
ret.insert(0, 0)
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
if OPENBSD or NETBSD:
def pid_exists(pid):
"""Return True if pid exists."""
exists = _psposix.pid_exists(pid)
if not exists:
# We do this because _psposix.pid_exists() lies in case of
# zombie processes.
return pid in pids()
else:
return True
else:
pid_exists = _psposix.pid_exists
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):
@ -503,11 +243,10 @@ def wrap_exceptions(fun):
try:
return fun(self, *args, **kwargs)
except OSError as err:
if self.pid == 0:
if 0 in pids():
raise AccessDenied(self.pid, self._name)
else:
raise
# support for private module import
if (NoSuchProcess is None or AccessDenied is None or
ZombieProcess is None):
raise
if err.errno == errno.ESRCH:
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
@ -519,25 +258,6 @@ def wrap_exceptions(fun):
return wrapper
@contextlib.contextmanager
def wrap_exceptions_procfs(inst):
"""Same as above, for routines relying on reading /proc fs."""
try:
yield
except EnvironmentError as err:
# ENOENT (no such file or directory) gets raised on open().
# ESRCH (no such process) can get raised on read() if
# process is gone in meantime.
if err.errno in (errno.ENOENT, errno.ESRCH):
if not pid_exists(inst.pid):
raise NoSuchProcess(inst.pid, inst._name)
else:
raise ZombieProcess(inst.pid, inst._name, inst._ppid)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(inst.pid, inst._name)
raise
class Process(object):
"""Wrapper class around underlying C implementation."""
@ -548,72 +268,22 @@ class Process(object):
self._name = None
self._ppid = None
@memoize_when_activated
def oneshot(self):
"""Retrieves multiple process info in one shot as a raw tuple."""
ret = cext.proc_oneshot_info(self.pid)
assert len(ret) == len(kinfo_proc_map)
return ret
def oneshot_enter(self):
self.oneshot.cache_activate()
def oneshot_exit(self):
self.oneshot.cache_deactivate()
@wrap_exceptions
def name(self):
name = self.oneshot()[kinfo_proc_map['name']]
return name if name is not None else cext.proc_name(self.pid)
return cext.proc_name(self.pid)
@wrap_exceptions
def exe(self):
if FREEBSD:
return cext.proc_exe(self.pid)
elif NETBSD:
if self.pid == 0:
# /proc/0 dir exists but /proc/0/exe doesn't
return ""
with wrap_exceptions_procfs(self):
return os.readlink("/proc/%s/exe" % self.pid)
else:
# OpenBSD: exe cannot be determined; references:
# https://chromium.googlesource.com/chromium/src/base/+/
# master/base_paths_posix.cc
# We try our best guess by using which against the first
# cmdline arg (may return None).
cmdline = self.cmdline()
if cmdline:
return which(cmdline[0])
else:
return ""
return cext.proc_exe(self.pid)
@wrap_exceptions
def cmdline(self):
if OPENBSD and self.pid == 0:
return [] # ...else it crashes
elif NETBSD:
# XXX - most of the times the underlying sysctl() call on Net
# and Open BSD returns a truncated string.
# Also /proc/pid/cmdline behaves the same so it looks
# like this is a kernel bug.
try:
return cext.proc_cmdline(self.pid)
except OSError as err:
if err.errno == errno.EINVAL:
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
else:
raise
else:
return cext.proc_cmdline(self.pid)
return cext.proc_cmdline(self.pid)
@wrap_exceptions
def terminal(self):
tty_nr = self.oneshot()[kinfo_proc_map['ttynr']]
tmap = _psposix.get_terminal_map()
tty_nr = cext.proc_tty_nr(self.pid)
tmap = _psposix._get_terminal_map()
try:
return tmap[tty_nr]
except KeyError:
@ -621,83 +291,51 @@ class Process(object):
@wrap_exceptions
def ppid(self):
self._ppid = self.oneshot()[kinfo_proc_map['ppid']]
return self._ppid
return cext.proc_ppid(self.pid)
@wrap_exceptions
def uids(self):
rawtuple = self.oneshot()
return _common.puids(
rawtuple[kinfo_proc_map['real_uid']],
rawtuple[kinfo_proc_map['effective_uid']],
rawtuple[kinfo_proc_map['saved_uid']])
real, effective, saved = cext.proc_uids(self.pid)
return _common.puids(real, effective, saved)
@wrap_exceptions
def gids(self):
rawtuple = self.oneshot()
return _common.pgids(
rawtuple[kinfo_proc_map['real_gid']],
rawtuple[kinfo_proc_map['effective_gid']],
rawtuple[kinfo_proc_map['saved_gid']])
real, effective, saved = cext.proc_gids(self.pid)
return _common.pgids(real, effective, saved)
@wrap_exceptions
def cpu_times(self):
rawtuple = self.oneshot()
return _common.pcputimes(
rawtuple[kinfo_proc_map['user_time']],
rawtuple[kinfo_proc_map['sys_time']],
rawtuple[kinfo_proc_map['ch_user_time']],
rawtuple[kinfo_proc_map['ch_sys_time']])
if FREEBSD:
@wrap_exceptions
def cpu_num(self):
return self.oneshot()[kinfo_proc_map['cpunum']]
user, system = cext.proc_cpu_times(self.pid)
return _common.pcputimes(user, system)
@wrap_exceptions
def memory_info(self):
rawtuple = self.oneshot()
return pmem(
rawtuple[kinfo_proc_map['rss']],
rawtuple[kinfo_proc_map['vms']],
rawtuple[kinfo_proc_map['memtext']],
rawtuple[kinfo_proc_map['memdata']],
rawtuple[kinfo_proc_map['memstack']])
rss, vms = cext.proc_memory_info(self.pid)[:2]
return _common.pmem(rss, vms)
memory_full_info = memory_info
@wrap_exceptions
def memory_info_ex(self):
return pextmem(*cext.proc_memory_info(self.pid))
@wrap_exceptions
def create_time(self):
return self.oneshot()[kinfo_proc_map['create_time']]
return cext.proc_create_time(self.pid)
@wrap_exceptions
def num_threads(self):
if hasattr(cext, "proc_num_threads"):
# FreeBSD
return cext.proc_num_threads(self.pid)
else:
return len(self.threads())
return cext.proc_num_threads(self.pid)
@wrap_exceptions
def num_ctx_switches(self):
rawtuple = self.oneshot()
return _common.pctxsw(
rawtuple[kinfo_proc_map['ctx_switches_vol']],
rawtuple[kinfo_proc_map['ctx_switches_unvol']])
return _common.pctxsw(*cext.proc_num_ctx_switches(self.pid))
@wrap_exceptions
def threads(self):
# Note: on OpenSBD this (/dev/mem) requires root access.
rawlist = cext.proc_threads(self.pid)
retlist = []
for thread_id, utime, stime in rawlist:
ntuple = _common.pthread(thread_id, utime, stime)
retlist.append(ntuple)
if OPENBSD:
# On OpenBSD the underlying C function does not raise NSP
# in case the process is gone (and the returned list may
# incomplete).
self.name() # raise NSP if the process disappeared on us
return retlist
@wrap_exceptions
@ -705,59 +343,27 @@ class Process(object):
if kind not in conn_tmap:
raise ValueError("invalid %r kind argument; choose between %s"
% (kind, ', '.join([repr(x) for x in conn_tmap])))
if NETBSD:
families, types = conn_tmap[kind]
ret = set()
rawlist = cext.net_connections(self.pid)
for item in rawlist:
fd, fam, type, laddr, raddr, status, pid = item
assert pid == self.pid
if fam in families and type in types:
try:
status = TCP_STATUSES[status]
except KeyError:
status = TCP_STATUSES[cext.PSUTIL_CONN_NONE]
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
fam = sockfam_to_enum(fam)
type = socktype_to_enum(type)
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
ret.add(nt)
# On NetBSD the underlying C function does not raise NSP
# in case the process is gone (and the returned list may
# incomplete).
self.name() # raise NSP if the process disappeared on us
return list(ret)
families, types = conn_tmap[kind]
rawlist = cext.proc_connections(self.pid, families, types)
ret = []
for item in rawlist:
fd, fam, type, laddr, raddr, status = item
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
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)
if OPENBSD:
# On OpenBSD the underlying C function does not raise NSP
# in case the process is gone (and the returned list may
# incomplete).
self.name() # raise NSP if the process disappeared on us
return ret
@wrap_exceptions
def wait(self, timeout=None):
return _psposix.wait_pid(self.pid, timeout, self._name)
try:
return _psposix.wait_pid(self.pid, timeout)
except _psposix.TimeoutExpired:
# support for private module import
if TimeoutExpired is None:
raise
raise TimeoutExpired(timeout, self.pid, self._name)
@wrap_exceptions
def nice_get(self):
@ -769,105 +375,81 @@ class Process(object):
@wrap_exceptions
def status(self):
code = self.oneshot()[kinfo_proc_map['status']]
# XXX is '?' legit? (we're not supposed to return it anyway)
return PROC_STATUSES.get(code, '?')
code = cext.proc_status(self.pid)
if code in PROC_STATUSES:
return PROC_STATUSES[code]
# XXX is this legit? will we even ever get here?
return "?"
@wrap_exceptions
def io_counters(self):
rawtuple = self.oneshot()
return _common.pio(
rawtuple[kinfo_proc_map['read_io_count']],
rawtuple[kinfo_proc_map['write_io_count']],
-1,
-1)
@wrap_exceptions
def cwd(self):
"""Return process current working directory."""
# sometimes we get an empty string, in which case we turn
# it into None
if OPENBSD and self.pid == 0:
return None # ...else it would raise EINVAL
elif NETBSD:
with wrap_exceptions_procfs(self):
return os.readlink("/proc/%s/cwd" % self.pid)
elif hasattr(cext, 'proc_open_files'):
# FreeBSD < 8 does not support functions based on
# kinfo_getfile() and kinfo_getvmmap()
return cext.proc_cwd(self.pid) or None
else:
raise NotImplementedError(
"supported only starting from FreeBSD 8" if
FREEBSD else "")
rc, wc, rb, wb = cext.proc_io_counters(self.pid)
return _common.pio(rc, wc, rb, wb)
nt_mmap_grouped = namedtuple(
'mmap', 'path rss, private, ref_count, shadow_count')
nt_mmap_ext = namedtuple(
'mmap', 'addr, perms path rss, private, ref_count, shadow_count')
def _not_implemented(self):
raise NotImplementedError
# FreeBSD < 8 does not support functions based on kinfo_getfile()
# and kinfo_getvmmap()
if hasattr(cext, 'proc_open_files'):
@wrap_exceptions
def open_files(self):
"""Return files opened by process as a list of namedtuples."""
rawlist = cext.proc_open_files(self.pid)
return [_common.popenfile(path, fd) for path, fd in rawlist]
else:
open_files = _not_implemented
# FreeBSD < 8 does not support functions based on kinfo_getfile()
# and kinfo_getvmmap()
if hasattr(cext, 'proc_num_fds'):
@wrap_exceptions
def num_fds(self):
"""Return the number of file descriptors opened by this process."""
ret = cext.proc_num_fds(self.pid)
if NETBSD:
# On NetBSD the underlying C function does not raise NSP
# in case the process is gone.
self.name() # raise NSP if the process disappeared on us
return ret
else:
num_fds = _not_implemented
# --- FreeBSD only APIs
if FREEBSD:
@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
def cwd(self):
"""Return process current working directory."""
# sometimes we get an empty string, in which case we turn
# it into None
return cext.proc_cwd(self.pid) or None
@wrap_exceptions
def memory_maps(self):
return cext.proc_memory_maps(self.pid)
@wrap_exceptions
def num_fds(self):
"""Return the number of file descriptors opened by this process."""
return cext.proc_num_fds(self.pid)
else:
def _not_implemented(self):
raise NotImplementedError("supported only starting from FreeBSD 8")
open_files = _not_implemented
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

View File

@ -1,44 +1,32 @@
#!/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.
"""OSX platform implementation."""
import contextlib
import errno
import functools
import os
from socket import AF_INET
from collections import namedtuple
from . import _common
from . import _psposix
from . import _psutil_osx as cext
from . import _psutil_posix as cext_posix
from ._common import AF_INET6
from ._common import conn_tmap
from ._common import isfile_strict
from ._common import memoize_when_activated
from ._common import parse_environ_block
from ._common import sockfam_to_enum
from ._common import socktype_to_enum
from ._common import usage_percent
from ._exceptions import AccessDenied
from ._exceptions import NoSuchProcess
from ._exceptions import ZombieProcess
from ._common import conn_tmap, usage_percent, isfile_strict
from ._common import sockfam_to_enum, socktype_to_enum
__extra__all__ = []
# =====================================================================
# --- globals
# =====================================================================
# --- 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 = {
cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT,
@ -62,60 +50,29 @@ PROC_STATUSES = {
cext.SZOMB: _common.STATUS_ZOMBIE,
}
kinfo_proc_map = dict(
ppid=0,
ruid=1,
euid=2,
suid=3,
rgid=4,
egid=5,
sgid=6,
ttynr=7,
ctime=8,
status=9,
name=10,
)
pidtaskinfo_map = dict(
cpuutime=0,
cpustime=1,
rss=2,
vms=3,
pfaults=4,
pageins=5,
numthreads=6,
volctxsw=7,
)
# =====================================================================
# --- named tuples
# =====================================================================
# psutil.cpu_times()
scputimes = namedtuple('scputimes', ['user', 'nice', 'system', 'idle'])
# psutil.virtual_memory()
svmem = namedtuple(
'svmem', ['total', 'available', 'percent', 'used', 'free',
'active', 'inactive', 'wired'])
# psutil.Process.memory_info()
pmem = namedtuple('pmem', ['rss', 'vms', 'pfaults', 'pageins'])
# psutil.Process.memory_full_info()
pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', ))
# psutil.Process.memory_maps(grouped=True)
pextmem = namedtuple('pextmem', ['rss', 'vms', 'pfaults', 'pageins'])
pmmap_grouped = namedtuple(
'pmmap_grouped',
'path rss private swapped dirtied ref_count shadow_depth')
# psutil.Process.memory_maps(grouped=False)
pmmap_ext = namedtuple(
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
# set later from __init__.py
NoSuchProcess = None
ZombieProcess = None
AccessDenied = None
TimeoutExpired = None
# =====================================================================
# --- memory
# =====================================================================
# --- functions
def virtual_memory():
"""System virtual memory as a namedtuple."""
@ -134,11 +91,6 @@ def swap_memory():
return _common.sswap(total, used, free, percent, sin, sout)
# =====================================================================
# --- CPU
# =====================================================================
def cpu_times():
"""Return system CPU times as a namedtuple."""
user, nice, system, idle = cext.cpu_times()
@ -165,34 +117,12 @@ def cpu_count_physical():
return cext.cpu_count_phys()
def cpu_stats():
ctx_switches, interrupts, soft_interrupts, syscalls, traps = \
cext.cpu_stats()
return _common.scpustats(
ctx_switches, interrupts, soft_interrupts, syscalls)
def cpu_freq():
"""Return CPU frequency.
On OSX per-cpu frequency is not supported.
Also, the returned frequency never changes, see:
https://arstechnica.com/civis/viewtopic.php?f=19&t=465002
"""
curr, min_, max_ = cext.cpu_freq()
return [_common.scpufreq(curr, min_, max_)]
# =====================================================================
# --- disks
# =====================================================================
disk_usage = _psposix.disk_usage
disk_io_counters = cext.disk_io_counters
def boot_time():
"""The system boot time expressed in seconds since the epoch."""
return cext.boot_time()
def disk_partitions(all=False):
"""Return mounted disk partitions as a list of namedtuples."""
retlist = []
partitions = cext.disk_partitions()
for partition in partitions:
@ -207,40 +137,21 @@ def disk_partitions(all=False):
return retlist
# =====================================================================
# --- sensors
# =====================================================================
def sensors_battery():
"""Return battery information.
"""
try:
percent, minsleft, power_plugged = cext.sensors_battery()
except NotImplementedError:
# no power source - return None according to interface
return None
power_plugged = power_plugged == 1
if power_plugged:
secsleft = _common.POWER_TIME_UNLIMITED
elif minsleft == -1:
secsleft = _common.POWER_TIME_UNKNOWN
else:
secsleft = minsleft * 60
return _common.sbattery(percent, secsleft, power_plugged)
# =====================================================================
# --- network
# =====================================================================
net_io_counters = cext.net_io_counters
net_if_addrs = cext_posix.net_if_addrs
def users():
retlist = []
rawlist = cext.users()
for item in rawlist:
user, tty, hostname, tstamp = item
if tty == '~':
continue # reboot or shutdown
if not tstamp:
continue
nt = _common.suser(user, tty or None, hostname or None, tstamp)
retlist.append(nt)
return retlist
def net_connections(kind='inet'):
"""System-wide network connections."""
# Note: on OSX this will fail with AccessDenied unless
# the process is owned by root.
ret = []
@ -262,62 +173,19 @@ def net_if_stats():
names = net_io_counters().keys()
ret = {}
for name in names:
mtu = cext_posix.net_if_mtu(name)
isup = cext_posix.net_if_flags(name)
duplex, speed = cext_posix.net_if_duplex_speed(name)
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
# =====================================================================
# --- other system functions
# =====================================================================
def boot_time():
"""The system boot time expressed in seconds since the epoch."""
return cext.boot_time()
def users():
"""Return currently connected users as a list of namedtuples."""
retlist = []
rawlist = cext.users()
for item in rawlist:
user, tty, hostname, tstamp, pid = item
if tty == '~':
continue # reboot or shutdown
if not tstamp:
continue
nt = _common.suser(user, tty or None, hostname or None, tstamp, pid)
retlist.append(nt)
return retlist
# =====================================================================
# --- processes
# =====================================================================
def pids():
ls = cext.pids()
if 0 not in ls:
# On certain OSX versions pids() C doesn't return PID 0 but
# "ps" does and the process is querable via sysctl():
# https://travis-ci.org/giampaolo/psutil/jobs/309619941
try:
Process(0).create_time()
ls.append(0)
except NoSuchProcess:
pass
except AccessDenied:
ls.append(0)
return ls
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):
@ -329,40 +197,21 @@ def wrap_exceptions(fun):
try:
return fun(self, *args, **kwargs)
except OSError as err:
# support for private module import
if (NoSuchProcess is None or AccessDenied is None or
ZombieProcess is None):
raise
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
return wrapper
@contextlib.contextmanager
def catch_zombie(proc):
"""There are some poor C APIs which incorrectly raise ESRCH when
the process is still alive or it's a zombie, or even RuntimeError
(those who don't set errno). This is here in order to solve:
https://github.com/giampaolo/psutil/issues/1044
"""
try:
yield
except (OSError, RuntimeError) as err:
if isinstance(err, RuntimeError) or err.errno == errno.ESRCH:
try:
# status() is not supposed to lie and correctly detect
# zombies so if it raises ESRCH it's true.
status = proc.status()
except NoSuchProcess:
raise err
else:
if status == _common.STATUS_ZOMBIE:
raise ZombieProcess(proc.pid, proc._name, proc._ppid)
else:
raise AccessDenied(proc.pid, proc._name)
else:
raise
class Process(object):
"""Wrapper class around underlying C implementation."""
@ -373,79 +222,42 @@ class Process(object):
self._name = None
self._ppid = None
@memoize_when_activated
def _get_kinfo_proc(self):
# Note: should work with all PIDs without permission issues.
ret = cext.proc_kinfo_oneshot(self.pid)
assert len(ret) == len(kinfo_proc_map)
return ret
@memoize_when_activated
def _get_pidtaskinfo(self):
# Note: should work for PIDs owned by user only.
with catch_zombie(self):
ret = cext.proc_pidtaskinfo_oneshot(self.pid)
assert len(ret) == len(pidtaskinfo_map)
return ret
def oneshot_enter(self):
self._get_kinfo_proc.cache_activate()
self._get_pidtaskinfo.cache_activate()
def oneshot_exit(self):
self._get_kinfo_proc.cache_deactivate()
self._get_pidtaskinfo.cache_deactivate()
@wrap_exceptions
def name(self):
name = self._get_kinfo_proc()[kinfo_proc_map['name']]
return name if name is not None else cext.proc_name(self.pid)
return cext.proc_name(self.pid)
@wrap_exceptions
def exe(self):
with catch_zombie(self):
return cext.proc_exe(self.pid)
return cext.proc_exe(self.pid)
@wrap_exceptions
def cmdline(self):
with catch_zombie(self):
return cext.proc_cmdline(self.pid)
@wrap_exceptions
def environ(self):
with catch_zombie(self):
return parse_environ_block(cext.proc_environ(self.pid))
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
return cext.proc_cmdline(self.pid)
@wrap_exceptions
def ppid(self):
self._ppid = self._get_kinfo_proc()[kinfo_proc_map['ppid']]
return self._ppid
return cext.proc_ppid(self.pid)
@wrap_exceptions
def cwd(self):
with catch_zombie(self):
return cext.proc_cwd(self.pid)
return cext.proc_cwd(self.pid)
@wrap_exceptions
def uids(self):
rawtuple = self._get_kinfo_proc()
return _common.puids(
rawtuple[kinfo_proc_map['ruid']],
rawtuple[kinfo_proc_map['euid']],
rawtuple[kinfo_proc_map['suid']])
real, effective, saved = cext.proc_uids(self.pid)
return _common.puids(real, effective, saved)
@wrap_exceptions
def gids(self):
rawtuple = self._get_kinfo_proc()
return _common.puids(
rawtuple[kinfo_proc_map['rgid']],
rawtuple[kinfo_proc_map['egid']],
rawtuple[kinfo_proc_map['sgid']])
real, effective, saved = cext.proc_gids(self.pid)
return _common.pgids(real, effective, saved)
@wrap_exceptions
def terminal(self):
tty_nr = self._get_kinfo_proc()[kinfo_proc_map['ttynr']]
tmap = _psposix.get_terminal_map()
tty_nr = cext.proc_tty_nr(self.pid)
tmap = _psposix._get_terminal_map()
try:
return tmap[tty_nr]
except KeyError:
@ -453,52 +265,37 @@ class Process(object):
@wrap_exceptions
def memory_info(self):
rawtuple = self._get_pidtaskinfo()
return pmem(
rawtuple[pidtaskinfo_map['rss']],
rawtuple[pidtaskinfo_map['vms']],
rawtuple[pidtaskinfo_map['pfaults']],
rawtuple[pidtaskinfo_map['pageins']],
)
rss, vms = cext.proc_memory_info(self.pid)[:2]
return _common.pmem(rss, vms)
@wrap_exceptions
def memory_full_info(self):
basic_mem = self.memory_info()
uss = cext.proc_memory_uss(self.pid)
return pfullmem(*basic_mem + (uss, ))
def memory_info_ex(self):
rss, vms, pfaults, pageins = cext.proc_memory_info(self.pid)
return pextmem(rss, vms, pfaults * PAGESIZE, pageins * PAGESIZE)
@wrap_exceptions
def cpu_times(self):
rawtuple = self._get_pidtaskinfo()
return _common.pcputimes(
rawtuple[pidtaskinfo_map['cpuutime']],
rawtuple[pidtaskinfo_map['cpustime']],
# children user / system times are not retrievable (set to 0)
0.0, 0.0)
user, system = cext.proc_cpu_times(self.pid)
return _common.pcputimes(user, system)
@wrap_exceptions
def create_time(self):
return self._get_kinfo_proc()[kinfo_proc_map['ctime']]
return cext.proc_create_time(self.pid)
@wrap_exceptions
def num_ctx_switches(self):
# Unvoluntary value seems not to be available;
# getrusage() numbers seems to confirm this theory.
# We set it to 0.
vol = self._get_pidtaskinfo()[pidtaskinfo_map['volctxsw']]
return _common.pctxsw(vol, 0)
return _common.pctxsw(*cext.proc_num_ctx_switches(self.pid))
@wrap_exceptions
def num_threads(self):
return self._get_pidtaskinfo()[pidtaskinfo_map['numthreads']]
return cext.proc_num_threads(self.pid)
@wrap_exceptions
def open_files(self):
if self.pid == 0:
return []
files = []
with catch_zombie(self):
rawlist = cext.proc_open_files(self.pid)
rawlist = cext.proc_open_files(self.pid)
for path, fd in rawlist:
if isfile_strict(path):
ntuple = _common.popenfile(path, fd)
@ -511,19 +308,13 @@ class Process(object):
raise ValueError("invalid %r kind argument; choose between %s"
% (kind, ', '.join([repr(x) for x in conn_tmap])))
families, types = conn_tmap[kind]
with catch_zombie(self):
rawlist = cext.proc_connections(self.pid, families, types)
rawlist = cext.proc_connections(self.pid, families, types)
ret = []
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)
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
ret.append(nt)
return ret
@ -532,33 +323,35 @@ class Process(object):
def num_fds(self):
if self.pid == 0:
return 0
with catch_zombie(self):
return cext.proc_num_fds(self.pid)
return cext.proc_num_fds(self.pid)
@wrap_exceptions
def wait(self, timeout=None):
return _psposix.wait_pid(self.pid, timeout, self._name)
try:
return _psposix.wait_pid(self.pid, timeout)
except _psposix.TimeoutExpired:
# support for private module import
if TimeoutExpired is None:
raise
raise TimeoutExpired(timeout, self.pid, self._name)
@wrap_exceptions
def nice_get(self):
with catch_zombie(self):
return cext_posix.getpriority(self.pid)
return cext_posix.getpriority(self.pid)
@wrap_exceptions
def nice_set(self, value):
with catch_zombie(self):
return cext_posix.setpriority(self.pid, value)
return cext_posix.setpriority(self.pid, value)
@wrap_exceptions
def status(self):
code = self._get_kinfo_proc()[kinfo_proc_map['status']]
code = cext.proc_status(self.pid)
# XXX is '?' legit? (we're not supposed to return it anyway)
return PROC_STATUSES.get(code, '?')
@wrap_exceptions
def threads(self):
with catch_zombie(self):
rawlist = cext.proc_threads(self.pid)
rawlist = cext.proc_threads(self.pid)
retlist = []
for thread_id, utime, stime in rawlist:
ntuple = _common.pthread(thread_id, utime, stime)
@ -567,5 +360,4 @@ class Process(object):
@wrap_exceptions
def memory_maps(self):
with catch_zombie(self):
return cext.proc_memory_maps(self.pid)
return cext.proc_memory_maps(self.pid)

View File

@ -1,3 +1,5 @@
#!/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.
@ -10,15 +12,12 @@ import os
import sys
import time
from ._common import memoize
from ._common import sdiskusage
from ._common import usage_percent
from ._compat import PY3
from ._compat import unicode
from ._exceptions import TimeoutExpired
from ._common import sdiskusage, usage_percent, memoize
from ._compat import PY3, unicode
__all__ = ['pid_exists', 'wait_pid', 'disk_usage', 'get_terminal_map']
class TimeoutExpired(Exception):
pass
def pid_exists(pid):
@ -49,7 +48,7 @@ def pid_exists(pid):
return True
def wait_pid(pid, timeout=None, proc_name=None):
def wait_pid(pid, timeout=None):
"""Wait for process with pid 'pid' to terminate and return its
exit status code as an integer.
@ -63,7 +62,7 @@ def wait_pid(pid, timeout=None, proc_name=None):
def check_timeout(delay):
if timeout is not None:
if timer() >= stop_at:
raise TimeoutExpired(timeout, pid=pid, name=proc_name)
raise TimeoutExpired()
time.sleep(delay)
return min(delay * 2, 0.04)
@ -106,74 +105,49 @@ def wait_pid(pid, timeout=None, proc_name=None):
# process exited due to a signal; return the integer of
# that signal
if os.WIFSIGNALED(status):
return -os.WTERMSIG(status)
return os.WTERMSIG(status)
# process exited using exit(2) system call; return the
# integer exit(2) system call has been called with
elif os.WIFEXITED(status):
return os.WEXITSTATUS(status)
else:
# should never happen
raise ValueError("unknown process exit status %r" % status)
raise RuntimeError("unknown process exit status")
def disk_usage(path):
"""Return disk usage associated with path.
Note: UNIX usually reserves 5% disk space which is not accessible
by user. In this function "total" and "used" values reflect the
total and used disk space whereas "free" and "percent" represent
the "free" and "used percent" user disk space.
"""
if PY3:
"""Return disk usage associated with path."""
try:
st = os.statvfs(path)
else:
# os.statvfs() does not support unicode on Python 2:
# - https://github.com/giampaolo/psutil/issues/416
# - http://bugs.python.org/issue18695
try:
except UnicodeEncodeError:
if not PY3 and isinstance(path, unicode):
# this is a bug with os.statvfs() and unicode on
# Python 2, see:
# - https://github.com/giampaolo/psutil/issues/416
# - http://bugs.python.org/issue18695
try:
path = path.encode(sys.getfilesystemencoding())
except UnicodeEncodeError:
pass
st = os.statvfs(path)
except UnicodeEncodeError:
if isinstance(path, unicode):
try:
path = path.encode(sys.getfilesystemencoding())
except UnicodeEncodeError:
pass
st = os.statvfs(path)
else:
raise
# Total space which is only available to root (unless changed
# at system level).
else:
raise
free = (st.f_bavail * st.f_frsize)
total = (st.f_blocks * st.f_frsize)
# Remaining free space usable by root.
avail_to_root = (st.f_bfree * st.f_frsize)
# Remaining free space usable by user.
avail_to_user = (st.f_bavail * st.f_frsize)
# Total space being used in general.
used = (total - avail_to_root)
# Total space which is available to user (same as 'total' but
# for the user).
total_user = used + avail_to_user
# User usage percent compared to the total amount of space
# the user can use. This number would be higher if compared
# to root's because the user has less space (usually -5%).
usage_percent_user = usage_percent(used, total_user, _round=1)
used = (st.f_blocks - st.f_bfree) * st.f_frsize
percent = usage_percent(used, total, _round=1)
# NB: the percentage is -5% than what shown by df due to
# reserved blocks that we are currently not considering:
# https://github.com/giampaolo/psutil/issues/829#issuecomment-223750462
return sdiskusage(
total=total, used=used, free=avail_to_user, percent=usage_percent_user)
# http://goo.gl/sWGbH
return sdiskusage(total, used, free, percent)
@memoize
def get_terminal_map():
"""Get a map of device-id -> path as a dict.
Used by Process.terminal()
"""
def _get_terminal_map():
ret = {}
ls = glob.glob('/dev/tty*') + glob.glob('/dev/pts/*')
for name in ls:
assert name not in ret, name
assert name not in ret
try:
ret[os.stat(name).st_rdev] = name
except OSError as err:

View File

@ -1,3 +1,5 @@
#!/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.
@ -10,36 +12,20 @@ import socket
import subprocess
import sys
from collections import namedtuple
from socket import AF_INET
from . import _common
from . import _psposix
from . import _psutil_posix as cext_posix
from . import _psutil_sunos as cext
from ._common import AF_INET6
from ._common import isfile_strict
from ._common import memoize_when_activated
from ._common import sockfam_to_enum
from ._common import socktype_to_enum
from ._common import isfile_strict, socktype_to_enum, sockfam_to_enum
from ._common import usage_percent
from ._compat import b
from ._compat import PY3
from ._exceptions import AccessDenied
from ._exceptions import NoSuchProcess
from ._exceptions import ZombieProcess
__extra__all__ = ["CONN_IDLE", "CONN_BOUND", "PROCFS_PATH"]
# =====================================================================
# --- globals
# =====================================================================
__extra__all__ = ["CONN_IDLE", "CONN_BOUND"]
PAGE_SIZE = os.sysconf('SC_PAGE_SIZE')
AF_LINK = cext_posix.AF_LINK
IS_64_BIT = sys.maxsize > 2**32
CONN_IDLE = "IDLE"
CONN_BOUND = "BOUND"
@ -71,58 +57,29 @@ TCP_STATUSES = {
cext.TCPS_BOUND: CONN_BOUND, # sunos specific
}
proc_info_map = dict(
ppid=0,
rss=1,
vms=2,
create_time=3,
nice=4,
num_threads=5,
status=6,
ttynr=7)
# =====================================================================
# --- named tuples
# =====================================================================
# psutil.cpu_times()
scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait'])
# psutil.cpu_times(percpu=True)
pcputimes = namedtuple('pcputimes',
['user', 'system', 'children_user', 'children_system'])
# psutil.virtual_memory()
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
# psutil.Process.memory_info()
pmem = namedtuple('pmem', ['rss', 'vms'])
pfullmem = pmem
# psutil.Process.memory_maps(grouped=True)
pmmap_grouped = namedtuple('pmmap_grouped',
['path', 'rss', 'anonymous', 'locked'])
# psutil.Process.memory_maps(grouped=False)
pextmem = namedtuple('pextmem', ['rss', 'vms'])
pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss', 'anon', 'locked'])
pmmap_ext = namedtuple(
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
# set later from __init__.py
NoSuchProcess = None
ZombieProcess = None
AccessDenied = None
TimeoutExpired = None
# =====================================================================
# --- utils
# =====================================================================
# --- functions
def get_procfs_path():
"""Return updated psutil.PROCFS_PATH constant."""
return sys.modules['psutil'].PROCFS_PATH
# =====================================================================
# --- memory
# =====================================================================
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():
"""Report virtual memory metrics."""
# we could have done this with kstat, but IMHO this is good enough
# we could have done this with kstat, but imho this is good enough
total = os.sysconf('SC_PHYS_PAGES') * PAGE_SIZE
# note: there's no difference on Solaris
free = avail = os.sysconf('SC_AVPHYS_PAGES') * PAGE_SIZE
@ -132,7 +89,6 @@ def virtual_memory():
def swap_memory():
"""Report swap memory metrics."""
sin, sout = cext.swap_mem()
# XXX
# we are supposed to get total/free by doing so:
@ -141,13 +97,13 @@ def swap_memory():
# ...nevertheless I can't manage to obtain the same numbers as 'swap'
# cmdline utility, so let's parse its output (sigh!)
p = subprocess.Popen(['/usr/bin/env', 'PATH=/usr/sbin:/sbin:%s' %
os.environ['PATH'], 'swap', '-l'],
os.environ['PATH'], 'swap', '-l', '-k'],
stdout=subprocess.PIPE)
stdout, stderr = p.communicate()
if PY3:
stdout = stdout.decode(sys.stdout.encoding)
if p.returncode != 0:
raise RuntimeError("'swap -l' failed (retcode=%s)" % p.returncode)
raise RuntimeError("'swap -l -k' failed (retcode=%s)" % p.returncode)
lines = stdout.strip().split('\n')[1:]
if not lines:
@ -156,17 +112,24 @@ def swap_memory():
for line in lines:
line = line.split()
t, f = line[-2:]
total += int(int(t) * 512)
free += int(int(f) * 512)
t = t.replace('K', '')
f = f.replace('K', '')
total += int(int(t) * 1024)
free += int(int(f) * 1024)
used = total - free
percent = usage_percent(used, total, _round=1)
return _common.sswap(total, used, free, percent,
sin * PAGE_SIZE, sout * PAGE_SIZE)
# =====================================================================
# --- CPU
# =====================================================================
def pids():
"""Returns a list of PIDs currently running on the system."""
return [int(x) for x in os.listdir('/proc') if x.isdigit()]
def pid_exists(pid):
"""Check for the existence of a unix pid."""
return _psposix.pid_exists(pid)
def cpu_times():
@ -195,21 +158,28 @@ def cpu_count_physical():
return cext.cpu_count_phys()
def cpu_stats():
"""Return various CPU stats as a named tuple."""
ctx_switches, interrupts, syscalls, traps = cext.cpu_stats()
soft_interrupts = 0
return _common.scpustats(ctx_switches, interrupts, soft_interrupts,
syscalls)
def boot_time():
"""The system boot time expressed in seconds since the epoch."""
return cext.boot_time()
# =====================================================================
# --- disks
# =====================================================================
disk_io_counters = cext.disk_io_counters
disk_usage = _psposix.disk_usage
def users():
"""Return currently connected users as a list of namedtuples."""
retlist = []
rawlist = cext.users()
localhost = (':0.0', ':0')
for item in rawlist:
user, tty, hostname, tstamp, user_process = item
# note: the underlying C function includes entries about
# system boot, run level and others. We might want
# to use them in the future.
if not user_process:
continue
if hostname in localhost:
hostname = 'localhost'
nt = _common.suser(user, tty, hostname, tstamp)
retlist.append(nt)
return retlist
def disk_partitions(all=False):
@ -233,15 +203,6 @@ def disk_partitions(all=False):
return retlist
# =====================================================================
# --- network
# =====================================================================
net_io_counters = cext.net_io_counters
net_if_addrs = cext_posix.net_if_addrs
def net_connections(kind, _pid=-1):
"""Return socket connections. If pid == -1 return system-wide
connections (as opposed to connections opened by one process only).
@ -254,7 +215,7 @@ def net_connections(kind, _pid=-1):
raise ValueError("invalid %r kind argument; choose between %s"
% (kind, ', '.join([repr(x) for x in cmap])))
families, types = _common.conn_tmap[kind]
rawlist = cext.net_connections(_pid)
rawlist = cext.net_connections(_pid, families, types)
ret = set()
for item in rawlist:
fd, fam, type_, laddr, raddr, status, pid = item
@ -262,11 +223,6 @@ def net_connections(kind, _pid=-1):
continue
if type_ not in types:
continue
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
status = TCP_STATUSES[status]
fam = sockfam_to_enum(fam)
type_ = socktype_to_enum(type_)
@ -289,64 +245,18 @@ def net_if_stats():
return ret
# =====================================================================
# --- other system functions
# =====================================================================
def boot_time():
"""The system boot time expressed in seconds since the epoch."""
return cext.boot_time()
def users():
"""Return currently connected users as a list of namedtuples."""
retlist = []
rawlist = cext.users()
localhost = (':0.0', ':0')
for item in rawlist:
user, tty, hostname, tstamp, user_process, pid = item
# note: the underlying C function includes entries about
# system boot, run level and others. We might want
# to use them in the future.
if not user_process:
continue
if hostname in localhost:
hostname = 'localhost'
nt = _common.suser(user, tty, hostname, tstamp, pid)
retlist.append(nt)
return retlist
# =====================================================================
# --- processes
# =====================================================================
def pids():
"""Returns a list of PIDs currently running on the system."""
return [int(x) for x in os.listdir(b(get_procfs_path())) if x.isdigit()]
def pid_exists(pid):
"""Check for the existence of a unix pid."""
return _psposix.pid_exists(pid)
def wrap_exceptions(fun):
"""Call callable into a try/except clause and translate ENOENT,
EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
"""
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except EnvironmentError as err:
if self.pid == 0:
if 0 in pids():
raise AccessDenied(self.pid, self._name)
else:
raise
# support for private module import
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.
@ -364,51 +274,21 @@ def wrap_exceptions(fun):
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_name", "_ppid", "_procfs_path"]
__slots__ = ["pid", "_name", "_ppid"]
def __init__(self, pid):
self.pid = pid
self._name = None
self._ppid = None
self._procfs_path = get_procfs_path()
def oneshot_enter(self):
self._proc_name_and_args.cache_activate()
self._proc_basic_info.cache_activate()
self._proc_cred.cache_activate()
def oneshot_exit(self):
self._proc_name_and_args.cache_deactivate()
self._proc_basic_info.cache_deactivate()
self._proc_cred.cache_deactivate()
@memoize_when_activated
def _proc_name_and_args(self):
return cext.proc_name_and_args(self.pid, self._procfs_path)
@memoize_when_activated
def _proc_basic_info(self):
ret = cext.proc_basic_info(self.pid, self._procfs_path)
assert len(ret) == len(proc_info_map)
return ret
@memoize_when_activated
def _proc_cred(self):
return cext.proc_cred(self.pid, self._procfs_path)
@wrap_exceptions
def name(self):
# note: max len == 15
return self._proc_name_and_args()[0]
return cext.proc_name_and_args(self.pid)[0]
@wrap_exceptions
def exe(self):
try:
return os.readlink(
"%s/%s/path/a.out" % (self._procfs_path, self.pid))
except OSError:
pass # continue and guess the exe name from the cmdline
# Will be guessed later from cmdline but we want to explicitly
# Will be guess later from cmdline but we want to explicitly
# invoke cmdline here in order to get an AccessDenied
# exception if the user has not enough privileges.
self.cmdline()
@ -416,34 +296,25 @@ class Process(object):
@wrap_exceptions
def cmdline(self):
return self._proc_name_and_args()[1].split(' ')
@wrap_exceptions
def environ(self):
return cext.proc_environ(self.pid, self._procfs_path)
return cext.proc_name_and_args(self.pid)[1].split(' ')
@wrap_exceptions
def create_time(self):
return self._proc_basic_info()[proc_info_map['create_time']]
return cext.proc_basic_info(self.pid)[3]
@wrap_exceptions
def num_threads(self):
return self._proc_basic_info()[proc_info_map['num_threads']]
return cext.proc_basic_info(self.pid)[5]
@wrap_exceptions
def nice_get(self):
# Note #1: for some reason getpriority(3) return ESRCH (no such
# process) for certain low-pid processes, no matter what (even
# as root).
# For some reason getpriority(3) return ESRCH (no such process)
# for certain low-pid processes, no matter what (even as root).
# The process actually exists though, as it has a name,
# creation time, etc.
# The best thing we can do here appears to be raising AD.
# Note: tested on Solaris 11; on Open Solaris 5 everything is
# fine.
#
# Note #2: we also can get niceness from /proc/pid/psinfo
# but it's wrong, see:
# https://github.com/giampaolo/psutil/issues/1082
try:
return cext_posix.getpriority(self.pid)
except EnvironmentError as err:
@ -466,52 +337,32 @@ class Process(object):
@wrap_exceptions
def ppid(self):
self._ppid = self._proc_basic_info()[proc_info_map['ppid']]
return self._ppid
return cext.proc_basic_info(self.pid)[0]
@wrap_exceptions
def uids(self):
real, effective, saved, _, _, _ = self._proc_cred()
real, effective, saved, _, _, _ = cext.proc_cred(self.pid)
return _common.puids(real, effective, saved)
@wrap_exceptions
def gids(self):
_, _, _, real, effective, saved = self._proc_cred()
_, _, _, real, effective, saved = cext.proc_cred(self.pid)
return _common.puids(real, effective, saved)
@wrap_exceptions
def cpu_times(self):
try:
times = cext.proc_cpu_times(self.pid, self._procfs_path)
except OSError as err:
if err.errno == errno.EOVERFLOW and not IS_64_BIT:
# We may get here if we attempt to query a 64bit process
# with a 32bit python.
# Error originates from read() and also tools like "cat"
# fail in the same way (!).
# Since there simply is no way to determine CPU times we
# return 0.0 as a fallback. See:
# https://github.com/giampaolo/psutil/issues/857
times = (0.0, 0.0, 0.0, 0.0)
else:
raise
return _common.pcputimes(*times)
@wrap_exceptions
def cpu_num(self):
return cext.proc_cpu_num(self.pid, self._procfs_path)
user, system = cext.proc_cpu_times(self.pid)
return _common.pcputimes(user, system)
@wrap_exceptions
def terminal(self):
procfs_path = self._procfs_path
hit_enoent = False
tty = wrap_exceptions(
self._proc_basic_info()[proc_info_map['ttynr']])
cext.proc_basic_info(self.pid)[0])
if tty != cext.PRNODEV:
for x in (0, 1, 2, 255):
try:
return os.readlink(
'%s/%d/path/%d' % (procfs_path, self.pid, x))
return os.readlink('/proc/%d/path/%d' % (self.pid, x))
except OSError as err:
if err.errno == errno.ENOENT:
hit_enoent = True
@ -519,7 +370,7 @@ class Process(object):
raise
if hit_enoent:
# raise NSP if the process disappeared on us
os.stat('%s/%s' % (procfs_path, self.pid))
os.stat('/proc/%s' % self.pid)
@wrap_exceptions
def cwd(self):
@ -527,51 +378,40 @@ class Process(object):
# it exists (ls shows it). If that's the case and the process
# is still alive return None (we can return None also on BSD).
# Reference: http://goo.gl/55XgO
procfs_path = self._procfs_path
try:
return os.readlink("%s/%s/path/cwd" % (procfs_path, self.pid))
return os.readlink("/proc/%s/path/cwd" % self.pid)
except OSError as err:
if err.errno == errno.ENOENT:
os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD
os.stat("/proc/%s" % self.pid)
return None
raise
@wrap_exceptions
def memory_info(self):
ret = self._proc_basic_info()
rss = ret[proc_info_map['rss']] * 1024
vms = ret[proc_info_map['vms']] * 1024
return pmem(rss, vms)
ret = cext.proc_basic_info(self.pid)
rss, vms = ret[1] * 1024, ret[2] * 1024
return _common.pmem(rss, vms)
memory_full_info = memory_info
# it seems Solaris uses rss and vms only
memory_info_ex = memory_info
@wrap_exceptions
def status(self):
code = self._proc_basic_info()[proc_info_map['status']]
code = cext.proc_basic_info(self.pid)[6]
# XXX is '?' legit? (we're not supposed to return it anyway)
return PROC_STATUSES.get(code, '?')
@wrap_exceptions
def threads(self):
procfs_path = self._procfs_path
ret = []
tids = os.listdir('%s/%d/lwp' % (procfs_path, self.pid))
tids = os.listdir('/proc/%d/lwp' % self.pid)
hit_enoent = False
for tid in tids:
tid = int(tid)
try:
utime, stime = cext.query_process_thread(
self.pid, tid, procfs_path)
self.pid, tid)
except EnvironmentError as err:
if err.errno == errno.EOVERFLOW and not IS_64_BIT:
# We may get here if we attempt to query a 64bit process
# with a 32bit python.
# Error originates from read() and also tools like "cat"
# fail in the same way (!).
# Since there simply is no way to determine CPU times we
# return 0.0 as a fallback. See:
# https://github.com/giampaolo/psutil/issues/857
continue
# ENOENT == thread gone in meantime
if err.errno == errno.ENOENT:
hit_enoent = True
@ -582,16 +422,15 @@ class Process(object):
ret.append(nt)
if hit_enoent:
# raise NSP if the process disappeared on us
os.stat('%s/%s' % (procfs_path, self.pid))
os.stat('/proc/%s' % self.pid)
return ret
@wrap_exceptions
def open_files(self):
retlist = []
hit_enoent = False
procfs_path = self._procfs_path
pathdir = '%s/%d/path' % (procfs_path, self.pid)
for fd in os.listdir('%s/%d/fd' % (procfs_path, self.pid)):
pathdir = '/proc/%d/path' % self.pid
for fd in os.listdir('/proc/%d/fd' % self.pid):
path = os.path.join(pathdir, fd)
if os.path.islink(path):
try:
@ -607,7 +446,7 @@ class Process(object):
retlist.append(_common.popenfile(file, int(fd)))
if hit_enoent:
# raise NSP if the process disappeared on us
os.stat('%s/%s' % (procfs_path, self.pid))
os.stat('/proc/%s' % self.pid)
return retlist
def _get_unix_sockets(self, pid):
@ -651,8 +490,7 @@ class Process(object):
# process is no longer active so we force NSP in case the PID
# is no longer there.
if not ret:
# will raise NSP if process is gone
os.stat('%s/%s' % (self._procfs_path, self.pid))
os.stat('/proc/%s' % self.pid) # will raise NSP if process is gone
# UNIX sockets
if kind in ('all', 'unix'):
@ -669,30 +507,15 @@ class Process(object):
return '%s-%s' % (hex(start)[2:].strip('L'),
hex(end)[2:].strip('L'))
procfs_path = self._procfs_path
retlist = []
try:
rawlist = cext.proc_memory_maps(self.pid, procfs_path)
except OSError as err:
if err.errno == errno.EOVERFLOW and not IS_64_BIT:
# We may get here if we attempt to query a 64bit process
# with a 32bit python.
# Error originates from read() and also tools like "cat"
# fail in the same way (!).
# Since there simply is no way to determine CPU times we
# return 0.0 as a fallback. See:
# https://github.com/giampaolo/psutil/issues/857
return []
else:
raise
rawlist = cext.proc_memory_maps(self.pid)
hit_enoent = False
for item in rawlist:
addr, addrsize, perm, name, rss, anon, locked = item
addr = toaddr(addr, addrsize)
if not name.startswith('['):
try:
name = os.readlink(
'%s/%s/path/%s' % (procfs_path, self.pid, name))
name = os.readlink('/proc/%s/path/%s' % (self.pid, name))
except OSError as err:
if err.errno == errno.ENOENT:
# sometimes the link may not be resolved by
@ -701,25 +524,30 @@ class Process(object):
# unresolved link path.
# This seems an incosistency with /proc similar
# to: http://goo.gl/55XgO
name = '%s/%s/path/%s' % (procfs_path, self.pid, name)
name = '/proc/%s/path/%s' % (self.pid, name)
hit_enoent = True
else:
raise
retlist.append((addr, perm, name, rss, anon, locked))
if hit_enoent:
# raise NSP if the process disappeared on us
os.stat('%s/%s' % (procfs_path, self.pid))
os.stat('/proc/%s' % self.pid)
return retlist
@wrap_exceptions
def num_fds(self):
return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid)))
return len(os.listdir("/proc/%s/fd" % self.pid))
@wrap_exceptions
def num_ctx_switches(self):
return _common.pctxsw(
*cext.proc_num_ctx_switches(self.pid, self._procfs_path))
return _common.pctxsw(*cext.proc_num_ctx_switches(self.pid))
@wrap_exceptions
def wait(self, timeout=None):
return _psposix.wait_pid(self.pid, timeout, self._name)
try:
return _psposix.wait_pid(self.pid, timeout)
except _psposix.TimeoutExpired:
# support for private module import
if TimeoutExpired is None:
raise
raise TimeoutExpired(timeout, self.pid, self._name)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,53 @@
/*
* 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.
*/
#include <Python.h>
// --- per-process functions
static PyObject* psutil_proc_cmdline(PyObject* self, PyObject* args);
static PyObject* psutil_proc_connections(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_proc_create_time(PyObject* self, PyObject* args);
static PyObject* psutil_proc_exe(PyObject* self, PyObject* args);
static PyObject* psutil_proc_gids(PyObject* self, PyObject* args);
static PyObject* psutil_proc_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_proc_memory_info(PyObject* self, PyObject* args);
static PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args);
static PyObject* psutil_proc_name(PyObject* self, PyObject* args);
static PyObject* psutil_proc_num_ctx_switches(PyObject* self, PyObject* args);
static PyObject* psutil_proc_num_fds(PyObject* self, PyObject* args);
static PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args);
static PyObject* psutil_proc_ppid(PyObject* self, PyObject* args);
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);
static PyObject* psutil_proc_cwd(PyObject* self, PyObject* args);
#endif
// --- system-related functions
static PyObject* psutil_boot_time(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_count_logical(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args);
static PyObject* psutil_net_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_pids(PyObject* self, PyObject* args);
static PyObject* psutil_swap_mem(PyObject* self, PyObject* args);
static PyObject* psutil_users(PyObject* self, PyObject* args);
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

View File

@ -7,43 +7,16 @@
*/
#include <Python.h>
#include <stdio.h>
// Global vars.
int PSUTIL_DEBUG = 0;
int PSUTIL_TESTING = 0;
/*
* Backport of unicode FS APIs from Python 3.
* On Python 2 we just return a plain byte string
* which is never supposed to raise decoding errors.
* See: https://github.com/giampaolo/psutil/issues/1040
*/
#if PY_MAJOR_VERSION < 3
PyObject *
PyUnicode_DecodeFSDefault(char *s) {
return PyString_FromString(s);
}
PyObject *
PyUnicode_DecodeFSDefaultAndSize(char *s, Py_ssize_t size) {
return PyString_FromStringAndSize(s, size);
}
#endif
/*
* Set OSError(errno=ESRCH, strerror="No such process") Python exception.
* If msg != "" the exception message will change in accordance.
*/
PyObject *
NoSuchProcess(char *msg) {
NoSuchProcess(void) {
PyObject *exc;
exc = PyObject_CallFunction(
PyExc_OSError, "(is)", ESRCH, strlen(msg) ? msg : strerror(ESRCH));
char *msg = strerror(ESRCH);
exc = PyObject_CallFunction(PyExc_OSError, "(is)", ESRCH, msg);
PyErr_SetObject(PyExc_OSError, exc);
Py_XDECREF(exc);
return NULL;
@ -52,53 +25,13 @@ NoSuchProcess(char *msg) {
/*
* Set OSError(errno=EACCES, strerror="Permission denied") Python exception.
* If msg != "" the exception message will change in accordance.
*/
PyObject *
AccessDenied(char *msg) {
AccessDenied(void) {
PyObject *exc;
exc = PyObject_CallFunction(
PyExc_OSError, "(is)", EACCES, strlen(msg) ? msg : strerror(EACCES));
char *msg = strerror(EACCES);
exc = PyObject_CallFunction(PyExc_OSError, "(is)", EACCES, msg);
PyErr_SetObject(PyExc_OSError, exc);
Py_XDECREF(exc);
return NULL;
}
/*
* Enable testing mode. This has the same effect as setting PSUTIL_TESTING
* env var. This dual method exists because updating os.environ on
* Windows has no effect. Called on unit tests setup.
*/
PyObject *
psutil_set_testing(PyObject *self, PyObject *args) {
PSUTIL_TESTING = 1;
Py_INCREF(Py_None);
return Py_None;
}
/*
* Print a debug message on stderr. No-op if PSUTIL_DEBUG env var is not set.
*/
void
psutil_debug(const char* format, ...) {
va_list argptr;
va_start(argptr, format);
fprintf(stderr, "psutil-dubug> ");
vfprintf(stderr, format, argptr);
fprintf(stderr, "\n");
va_end(argptr);
}
/*
* Called on module import on all platforms.
*/
void
psutil_setup(void) {
if (getenv("PSUTIL_DEBUG") != NULL)
PSUTIL_DEBUG = 1;
if (getenv("PSUTIL_TESTING") != NULL)
PSUTIL_TESTING = 1;
}

View File

@ -6,20 +6,5 @@
#include <Python.h>
extern int PSUTIL_TESTING;
extern int PSUTIL_DEBUG;
// a signaler for connections without an actual status
static const int PSUTIL_CONN_NONE = 128;
#if PY_MAJOR_VERSION < 3
PyObject* PyUnicode_DecodeFSDefault(char *s);
PyObject* PyUnicode_DecodeFSDefaultAndSize(char *s, Py_ssize_t size);
#endif
PyObject* AccessDenied(char *msg);
PyObject* NoSuchProcess(char *msg);
PyObject* psutil_set_testing(PyObject *self, PyObject *args);
void psutil_debug(const char* format, ...);
void psutil_setup(void);
PyObject* AccessDenied(void);
PyObject* NoSuchProcess(void);

View File

@ -23,19 +23,10 @@
#include <sys/socket.h>
#include <linux/sockios.h>
#include <linux/if.h>
// see: https://github.com/giampaolo/psutil/issues/659
#ifdef PSUTIL_ETHTOOL_MISSING_TYPES
#include <linux/types.h>
typedef __u64 u64;
typedef __u32 u32;
typedef __u16 u16;
typedef __u8 u8;
#endif
/* Avoid redefinition of struct sysinfo with musl libc */
#define _LINUX_SYSINFO_H
#include <linux/ethtool.h>
#include "_psutil_linux.h"
/* The minimum number of CPUs allocated in a cpu_set_t */
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
@ -54,8 +45,11 @@ static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
#include <sys/resource.h>
#endif
#include "_psutil_common.h"
#include "_psutil_posix.h"
#if PSUTIL_HAVE_IOPRIO
enum {
IOPRIO_WHO_PROCESS = 1,
};
// May happen on old RedHat versions, see:
// https://github.com/giampaolo/psutil/issues/607
@ -63,19 +57,15 @@ static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
#define DUPLEX_UNKNOWN 0xff
#endif
#if PSUTIL_HAVE_IOPRIO
enum {
IOPRIO_WHO_PROCESS = 1,
};
static inline int
ioprio_get(int which, int who) {
ioprio_get(int which, int who)
{
return syscall(__NR_ioprio_get, which, who);
}
static inline int
ioprio_set(int which, int who, int ioprio) {
ioprio_set(int which, int who, int ioprio)
{
return syscall(__NR_ioprio_set, which, who, ioprio);
}
@ -91,7 +81,8 @@ ioprio_set(int which, int who, int ioprio) {
* Return a (ioclass, iodata) Python tuple representing process I/O priority.
*/
static PyObject *
psutil_proc_ioprio_get(PyObject *self, PyObject *args) {
psutil_proc_ioprio_get(PyObject *self, PyObject *args)
{
long pid;
int ioprio, ioclass, iodata;
if (! PyArg_ParseTuple(args, "l", &pid))
@ -111,7 +102,8 @@ psutil_proc_ioprio_get(PyObject *self, PyObject *args) {
* or 0. iodata goes from 0 to 7 depending on ioclass specified.
*/
static PyObject *
psutil_proc_ioprio_set(PyObject *self, PyObject *args) {
psutil_proc_ioprio_set(PyObject *self, PyObject *args)
{
long pid;
int ioprio, ioclass, iodata;
int retval;
@ -134,19 +126,20 @@ psutil_proc_ioprio_set(PyObject *self, PyObject *args) {
* 'soft' and 'hard' args must be provided.
*/
static PyObject *
psutil_linux_prlimit(PyObject *self, PyObject *args) {
psutil_linux_prlimit(PyObject *self, PyObject *args)
{
long pid;
int ret, resource;
struct rlimit old, new;
struct rlimit *newp = NULL;
PyObject *py_soft = NULL;
PyObject *py_hard = NULL;
PyObject *soft = NULL;
PyObject *hard = NULL;
if (! PyArg_ParseTuple(args, "li|OO", &pid, &resource, &py_soft, &py_hard))
if (! PyArg_ParseTuple(args, "li|OO", &pid, &resource, &soft, &hard))
return NULL;
// get
if (py_soft == NULL && py_hard == NULL) {
if (soft == NULL && hard == NULL) {
ret = prlimit(pid, resource, NULL, &old);
if (ret == -1)
return PyErr_SetFromErrno(PyExc_OSError);
@ -163,17 +156,17 @@ psutil_linux_prlimit(PyObject *self, PyObject *args) {
// set
else {
#if defined(PSUTIL_HAVE_LARGEFILE_SUPPORT)
new.rlim_cur = PyLong_AsLongLong(py_soft);
new.rlim_cur = PyLong_AsLongLong(soft);
if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred())
return NULL;
new.rlim_max = PyLong_AsLongLong(py_hard);
new.rlim_max = PyLong_AsLongLong(hard);
if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred())
return NULL;
#else
new.rlim_cur = PyLong_AsLong(py_soft);
new.rlim_cur = PyLong_AsLong(soft);
if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred())
return NULL;
new.rlim_max = PyLong_AsLong(py_hard);
new.rlim_max = PyLong_AsLong(hard);
if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred())
return NULL;
#endif
@ -192,13 +185,12 @@ psutil_linux_prlimit(PyObject *self, PyObject *args) {
* mount point and filesystem type
*/
static PyObject *
psutil_disk_partitions(PyObject *self, PyObject *args) {
psutil_disk_partitions(PyObject *self, PyObject *args)
{
FILE *file = NULL;
struct mntent *entry;
PyObject *py_dev = NULL;
PyObject *py_mountp = NULL;
PyObject *py_tuple = NULL;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
if (py_retlist == NULL)
return NULL;
@ -214,26 +206,18 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
while ((entry = getmntent(file))) {
if (entry == NULL) {
PyErr_Format(PyExc_RuntimeError, "getmntent() syscall failed");
PyErr_Format(PyExc_RuntimeError, "getmntent() failed");
goto error;
}
py_dev = PyUnicode_DecodeFSDefault(entry->mnt_fsname);
if (! py_dev)
goto error;
py_mountp = PyUnicode_DecodeFSDefault(entry->mnt_dir);
if (! py_mountp)
goto error;
py_tuple = Py_BuildValue("(OOss)",
py_dev, // device
py_mountp, // mount point
py_tuple = Py_BuildValue("(ssss)",
entry->mnt_fsname, // device
entry->mnt_dir, // mount point
entry->mnt_type, // fs type
entry->mnt_opts); // options
if (! py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_dev);
Py_DECREF(py_mountp);
Py_DECREF(py_tuple);
}
endmntent(file);
@ -242,8 +226,6 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
error:
if (file != NULL)
endmntent(file);
Py_XDECREF(py_dev);
Py_XDECREF(py_mountp);
Py_XDECREF(py_tuple);
Py_DECREF(py_retlist);
return NULL;
@ -254,22 +236,21 @@ error:
* A wrapper around sysinfo(), return system memory usage statistics.
*/
static PyObject *
psutil_linux_sysinfo(PyObject *self, PyObject *args) {
psutil_linux_sysinfo(PyObject *self, PyObject *args)
{
struct sysinfo info;
if (sysinfo(&info) != 0)
return PyErr_SetFromErrno(PyExc_OSError);
// note: boot time might also be determined from here
return Py_BuildValue(
"(kkkkkkI)",
info.totalram, // total
info.freeram, // free
info.bufferram, // buffer
info.sharedram, // shared
info.totalswap, // swap tot
info.freeswap, // swap free
info.mem_unit // multiplier
);
"(KKKKKK)",
(unsigned long long)info.totalram * info.mem_unit, // total
(unsigned long long)info.freeram * info.mem_unit, // free
(unsigned long long)info.bufferram * info.mem_unit, // buffer
(unsigned long long)info.sharedram * info.mem_unit, // shared
(unsigned long long)info.totalswap * info.mem_unit, // swap tot
(unsigned long long)info.freeswap * info.mem_unit); // swap free
}
@ -282,14 +263,15 @@ psutil_linux_sysinfo(PyObject *self, PyObject *args) {
#ifdef CPU_ALLOC
static PyObject *
psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) {
psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args)
{
int cpu, ncpus, count, cpucount_s;
long pid;
size_t setsize;
cpu_set_t *mask = NULL;
PyObject *py_list = NULL;
PyObject *res = NULL;
if (!PyArg_ParseTuple(args, "l", &pid))
if (!PyArg_ParseTuple(args, "i", &pid))
return NULL;
ncpus = NCPUS_START;
while (1) {
@ -310,8 +292,8 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) {
ncpus = ncpus * 2;
}
py_list = PyList_New(0);
if (py_list == NULL)
res = PyList_New(0);
if (res == NULL)
goto error;
cpucount_s = CPU_COUNT_S(setsize, mask);
@ -324,7 +306,7 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) {
#endif
if (cpu_num == NULL)
goto error;
if (PyList_Append(py_list, cpu_num)) {
if (PyList_Append(res, cpu_num)) {
Py_DECREF(cpu_num);
goto error;
}
@ -333,12 +315,12 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) {
}
}
CPU_FREE(mask);
return py_list;
return res;
error:
if (mask)
CPU_FREE(mask);
Py_XDECREF(py_list);
Py_XDECREF(res);
return NULL;
}
#else
@ -348,7 +330,8 @@ error:
* Alternative implementation in case CPU_ALLOC is not defined.
*/
static PyObject *
psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) {
psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args)
{
cpu_set_t cpuset;
unsigned int len = sizeof(cpu_set_t);
long pid;
@ -356,7 +339,7 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) {
PyObject* py_retlist = NULL;
PyObject *py_cpu_num = NULL;
if (!PyArg_ParseTuple(args, "l", &pid))
if (!PyArg_ParseTuple(args, "i", &pid))
return NULL;
CPU_ZERO(&cpuset);
if (sched_getaffinity(pid, len, &cpuset) < 0)
@ -380,7 +363,7 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) {
error:
Py_XDECREF(py_cpu_num);
Py_XDECREF(py_retlist);
Py_DECREF(py_retlist);
return NULL;
}
#endif
@ -389,7 +372,8 @@ error:
* Set process CPU affinity; expects a bitmask
*/
static PyObject *
psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) {
psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args)
{
cpu_set_t cpu_set;
size_t len;
long pid;
@ -418,15 +402,11 @@ psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) {
#else
long value = PyInt_AsLong(item);
#endif
if ((value == -1) || PyErr_Occurred()) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_ValueError, "invalid CPU value");
if (value == -1 && PyErr_Occurred())
goto error;
}
CPU_SET(value, &cpu_set);
}
len = sizeof(cpu_set);
if (sched_setaffinity(pid, len, &cpu_set)) {
PyErr_SetFromErrno(PyExc_OSError);
@ -447,61 +427,44 @@ error:
* Return currently connected users as a list of tuples.
*/
static PyObject *
psutil_users(PyObject *self, PyObject *args) {
psutil_users(PyObject *self, PyObject *args)
{
PyObject *ret_list = PyList_New(0);
PyObject *tuple = NULL;
PyObject *user_proc = NULL;
struct utmp *ut;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
PyObject *py_username = NULL;
PyObject *py_tty = NULL;
PyObject *py_hostname = NULL;
PyObject *py_user_proc = NULL;
if (py_retlist == NULL)
if (ret_list == NULL)
return NULL;
setutent();
while (NULL != (ut = getutent())) {
py_tuple = NULL;
py_user_proc = NULL;
tuple = NULL;
user_proc = NULL;
if (ut->ut_type == USER_PROCESS)
py_user_proc = Py_True;
user_proc = Py_True;
else
py_user_proc = Py_False;
py_username = PyUnicode_DecodeFSDefault(ut->ut_user);
if (! py_username)
goto error;
py_tty = PyUnicode_DecodeFSDefault(ut->ut_line);
if (! py_tty)
goto error;
py_hostname = PyUnicode_DecodeFSDefault(ut->ut_host);
if (! py_hostname)
goto error;
py_tuple = Py_BuildValue(
"(OOOfOi)",
py_username, // username
py_tty, // tty
py_hostname, // hostname
user_proc = Py_False;
tuple = Py_BuildValue(
"(sssfO)",
ut->ut_user, // username
ut->ut_line, // tty
ut->ut_host, // hostname
(float)ut->ut_tv.tv_sec, // tstamp
py_user_proc, // (bool) user process
ut->ut_pid // process id
user_proc // (bool) user process
);
if (! py_tuple)
if (! tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
if (PyList_Append(ret_list, tuple))
goto error;
Py_DECREF(py_username);
Py_DECREF(py_tty);
Py_DECREF(py_hostname);
Py_DECREF(py_tuple);
Py_DECREF(tuple);
}
endutent();
return py_retlist;
return ret_list;
error:
Py_XDECREF(py_username);
Py_XDECREF(py_tty);
Py_XDECREF(py_hostname);
Py_XDECREF(py_tuple);
Py_DECREF(py_retlist);
Py_XDECREF(tuple);
Py_XDECREF(user_proc);
Py_DECREF(ret_list);
endutent();
return NULL;
}
@ -514,15 +477,18 @@ error:
* http://www.i-scream.org/libstatgrab/
*/
static PyObject*
psutil_net_if_duplex_speed(PyObject* self, PyObject* args) {
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_retlist = NULL;
PyObject *py_is_up = NULL;
PyObject *py_ret = NULL;
if (! PyArg_ParseTuple(args, "s", &nic_name))
return NULL;
@ -532,10 +498,26 @@ psutil_net_if_duplex_speed(PyObject* self, PyObject* args) {
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(&ethcmd, 0, sizeof ethcmd);
ethcmd.cmd = ETHTOOL_GSET;
ifr.ifr_data = (void *)&ethcmd;
ifr.ifr_data = (caddr_t)&ethcmd;
ret = ioctl(sock, SIOCETHTOOL, &ifr);
if (ret != -1) {
@ -543,11 +525,8 @@ psutil_net_if_duplex_speed(PyObject* self, PyObject* args) {
speed = ethcmd.speed;
}
else {
if ((errno == EOPNOTSUPP) || (errno == EINVAL)) {
// EOPNOTSUPP may occur in case of wi-fi cards.
// For EINVAL see:
// https://github.com/giampaolo/psutil/issues/797
// #issuecomment-202999532
if (errno == EOPNOTSUPP) {
// we typically get here in case of wi-fi cards
duplex = DUPLEX_UNKNOWN;
speed = 0;
}
@ -557,15 +536,18 @@ psutil_net_if_duplex_speed(PyObject* self, PyObject* args) {
}
close(sock);
py_retlist = Py_BuildValue("[ii]", duplex, speed);
if (!py_retlist)
py_ret = Py_BuildValue("[Oiii]", py_is_up, duplex, speed, mtu);
if (!py_ret)
goto error;
return py_retlist;
Py_DECREF(py_is_up);
return py_ret;
error:
if (sock != -1)
Py_XDECREF(py_is_up);
if (sock != 0)
close(sock);
return PyErr_SetFromErrno(PyExc_OSError);
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
@ -573,7 +555,8 @@ error:
* Define the psutil C module methods and initialize the module.
*/
static PyMethodDef
PsutilMethods[] = {
PsutilMethods[] =
{
// --- per-process functions
#if PSUTIL_HAVE_IOPRIO
@ -594,8 +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_duplex_speed", psutil_net_if_duplex_speed, METH_VARARGS,
"Return duplex and speed info about a NIC"},
{"net_if_stats", psutil_net_if_stats, METH_VARARGS,
"Return NIC stats (isup, duplex, speed, mtu)"},
// --- linux specific
@ -606,9 +589,6 @@ PsutilMethods[] = {
"Get or set process resource limits."},
#endif
// --- others
{"set_testing", psutil_set_testing, METH_NOARGS,
"Set psutil in testing mode"},
{NULL, NULL, 0, NULL}
};
@ -660,15 +640,16 @@ PyMODINIT_FUNC PyInit__psutil_linux(void)
void init_psutil_linux(void)
#endif
{
PyObject *v;
#if PY_MAJOR_VERSION >= 3
PyObject *module = PyModule_Create(&moduledef);
#else
PyObject *module = Py_InitModule("_psutil_linux", PsutilMethods);
#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);
PyModule_AddIntConstant(module, "RLIMIT_CORE", RLIMIT_CORE);
PyModule_AddIntConstant(module, "RLIMIT_CPU", RLIMIT_CPU);
@ -680,19 +661,6 @@ void init_psutil_linux(void)
PyModule_AddIntConstant(module, "RLIMIT_NPROC", RLIMIT_NPROC);
PyModule_AddIntConstant(module, "RLIMIT_RSS", RLIMIT_RSS);
PyModule_AddIntConstant(module, "RLIMIT_STACK", RLIMIT_STACK);
#if defined(HAVE_LONG_LONG)
if (sizeof(RLIM_INFINITY) > sizeof(long)) {
v = PyLong_FromLongLong((PY_LONG_LONG) RLIM_INFINITY);
} else
#endif
{
v = PyLong_FromLong((long) RLIM_INFINITY);
}
if (v) {
PyModule_AddObject(module, "RLIM_INFINITY", v);
}
#ifdef RLIMIT_MSGQUEUE
PyModule_AddIntConstant(module, "RLIMIT_MSGQUEUE", RLIMIT_MSGQUEUE);
#endif
@ -713,8 +681,6 @@ void init_psutil_linux(void)
PyModule_AddIntConstant(module, "DUPLEX_FULL", DUPLEX_FULL);
PyModule_AddIntConstant(module, "DUPLEX_UNKNOWN", DUPLEX_UNKNOWN);
psutil_setup();
if (module == NULL)
INITERROR;
#if PY_MAJOR_VERSION >= 3

View File

@ -0,0 +1,21 @@
/*
* 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.
*/
#include <Python.h>
// process
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_ioprio_get(PyObject* self, PyObject* args);
static PyObject* psutil_proc_ioprio_get(PyObject* self, PyObject* args);
// system
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);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2009, Jay Loden, 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.
*/
#include <Python.h>
// --- per-process functions
static PyObject* psutil_proc_cmdline(PyObject* self, PyObject* args);
static PyObject* psutil_proc_connections(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_proc_create_time(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_gids(PyObject* self, PyObject* args);
static PyObject* psutil_proc_memory_info(PyObject* self, PyObject* args);
static PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args);
static PyObject* psutil_proc_name(PyObject* self, PyObject* args);
static PyObject* psutil_proc_num_fds(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_ppid(PyObject* self, PyObject* args);
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);
// --- system-related functions
static PyObject* psutil_boot_time(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_count_logical(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args);
static PyObject* psutil_net_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_pids(PyObject* self, PyObject* args);
static PyObject* psutil_swap_mem(PyObject* self, PyObject* args);
static PyObject* psutil_users(PyObject* self, PyObject* args);
static PyObject* psutil_virtual_mem(PyObject* self, PyObject* args);

View File

@ -11,143 +11,40 @@
#include <stdlib.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <ifaddrs.h>
#ifdef PSUTIL_SUNOS10
#include "arch/solaris/v10/ifaddrs.h"
#elif PSUTIL_AIX
#include "arch/aix/ifaddrs.h"
#else
#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(PSUTIL_LINUX)
#include <netdb.h>
#include <linux/types.h>
#include <linux/if_packet.h>
#elif defined(PSUTIL_BSD) || defined(PSUTIL_OSX)
#include <netdb.h>
#include <netinet/in.h>
#include <net/if_dl.h>
#include <sys/sockio.h>
#include <net/if_media.h>
#include <net/if.h>
#elif defined(PSUTIL_SUNOS)
#include <netdb.h>
#include <sys/sockio.h>
#elif defined(PSUTIL_AIX)
#include <netdb.h>
#if defined(__sun)
#include <netdb.h>
#endif
#include "_psutil_common.h"
/*
* Check if PID exists. Return values:
* 1: exists
* 0: does not exist
* -1: error (Python exception is set)
*/
int
psutil_pid_exists(long pid) {
int ret;
// No negative PID exists, plus -1 is an alias for sending signal
// too all processes except system ones. Not what we want.
if (pid < 0)
return 0;
// As per "man 2 kill" PID 0 is an alias for sending the signal to
// every process in the process group of the calling process.
// Not what we want. Some platforms have PID 0, some do not.
// We decide that at runtime.
if (pid == 0) {
#if defined(PSUTIL_LINUX) || defined(PSUTIL_FREEBSD)
return 0;
#else
return 1;
#endif
}
#if defined(PSUTIL_OSX)
ret = kill((pid_t)pid , 0);
#else
ret = kill(pid , 0);
#endif
if (ret == 0)
return 1;
else {
if (errno == ESRCH) {
// ESRCH == No such process
return 0;
}
else if (errno == EPERM) {
// EPERM clearly indicates there's a process to deny
// access to.
return 1;
}
else {
// According to "man 2 kill" possible error values are
// (EINVAL, EPERM, ESRCH) therefore we should never get
// here. If we do let's be explicit in considering this
// an error.
PyErr_SetFromErrno(PyExc_OSError);
return -1;
}
}
}
/*
* Utility used for those syscalls which do not return a meaningful
* error that we can translate into an exception which makes sense.
* As such, we'll have to guess.
* On UNIX, if errno is set, we return that one (OSError).
* Else, if PID does not exist we assume the syscall failed because
* of that so we raise NoSuchProcess.
* If none of this is true we giveup and raise RuntimeError(msg).
* This will always set a Python exception and return NULL.
*/
int
psutil_raise_for_pid(long pid, char *syscall_name) {
// Set exception to AccessDenied if pid exists else NoSuchProcess.
if (errno != 0) {
// Unlikely we get here.
PyErr_SetFromErrno(PyExc_OSError);
return 0;
}
else if (psutil_pid_exists(pid) == 0) {
psutil_debug("%s syscall failed and PID %i no longer exists; "
"assume NoSuchProcess", syscall_name, pid);
NoSuchProcess("");
}
else {
PyErr_Format(PyExc_RuntimeError, "%s syscall failed", syscall_name);
}
return 0;
}
#include "_psutil_posix.h"
/*
* Given a PID return process priority as a Python integer.
*/
static PyObject *
psutil_posix_getpriority(PyObject *self, PyObject *args) {
psutil_posix_getpriority(PyObject *self, PyObject *args)
{
long pid;
int priority;
errno = 0;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
#ifdef PSUTIL_OSX
priority = getpriority(PRIO_PROCESS, (id_t)pid);
#else
priority = getpriority(PRIO_PROCESS, pid);
#endif
if (errno != 0)
return PyErr_SetFromErrno(PyExc_OSError);
return Py_BuildValue("i", priority);
@ -158,19 +55,15 @@ psutil_posix_getpriority(PyObject *self, PyObject *args) {
* Given a PID and a value change process priority.
*/
static PyObject *
psutil_posix_setpriority(PyObject *self, PyObject *args) {
psutil_posix_setpriority(PyObject *self, PyObject *args)
{
long pid;
int priority;
int retval;
if (! PyArg_ParseTuple(args, "li", &pid, &priority))
return NULL;
#ifdef PSUTIL_OSX
retval = setpriority(PRIO_PROCESS, (id_t)pid, priority);
#else
retval = setpriority(PRIO_PROCESS, pid, priority);
#endif
if (retval == -1)
return PyErr_SetFromErrno(PyExc_OSError);
Py_RETURN_NONE;
@ -182,11 +75,12 @@ psutil_posix_setpriority(PyObject *self, PyObject *args) {
* Return None if address family is not AF_INET* or AF_PACKET.
*/
static PyObject *
psutil_convert_ipaddr(struct sockaddr *addr, int family) {
psutil_convert_ipaddr(struct sockaddr *addr, int family)
{
char buf[NI_MAXHOST];
int err;
int addrlen;
size_t n;
int n;
size_t len;
const char *data;
char *ptr;
@ -215,13 +109,14 @@ psutil_convert_ipaddr(struct sockaddr *addr, int family) {
return Py_BuildValue("s", buf);
}
}
#ifdef PSUTIL_LINUX
#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;
}
#elif defined(PSUTIL_BSD) || defined(PSUTIL_OSX)
#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.
@ -258,7 +153,8 @@ psutil_convert_ipaddr(struct sockaddr *addr, int family) {
* TODO: on Solaris we won't get any MAC address.
*/
static PyObject*
psutil_net_if_addrs(PyObject* self, PyObject* args) {
psutil_net_if_addrs(PyObject* self, PyObject* args)
{
struct ifaddrs *ifaddr, *ifa;
int family;
@ -267,7 +163,6 @@ psutil_net_if_addrs(PyObject* self, PyObject* args) {
PyObject *py_address = NULL;
PyObject *py_netmask = NULL;
PyObject *py_broadcast = NULL;
PyObject *py_ptp = NULL;
if (py_retlist == NULL)
return NULL;
@ -290,34 +185,20 @@ psutil_net_if_addrs(PyObject* self, PyObject* args) {
py_netmask = psutil_convert_ipaddr(ifa->ifa_netmask, family);
if (py_netmask == NULL)
goto error;
if (ifa->ifa_flags & IFF_BROADCAST) {
py_broadcast = psutil_convert_ipaddr(ifa->ifa_broadaddr, family);
Py_INCREF(Py_None);
py_ptp = Py_None;
}
else if (ifa->ifa_flags & IFF_POINTOPOINT) {
py_ptp = psutil_convert_ipaddr(ifa->ifa_dstaddr, family);
Py_INCREF(Py_None);
py_broadcast = Py_None;
}
else {
Py_INCREF(Py_None);
Py_INCREF(Py_None);
py_broadcast = Py_None;
py_ptp = Py_None;
}
if ((py_broadcast == NULL) || (py_ptp == NULL))
#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(
"(siOOOO)",
"(siOOO)",
ifa->ifa_name,
family,
py_address,
py_netmask,
py_broadcast,
py_ptp
py_broadcast
);
if (! py_tuple)
@ -328,7 +209,6 @@ psutil_net_if_addrs(PyObject* self, PyObject* args) {
Py_DECREF(py_address);
Py_DECREF(py_netmask);
Py_DECREF(py_broadcast);
Py_DECREF(py_ptp);
}
freeifaddrs(ifaddr);
@ -342,98 +222,19 @@ error:
Py_XDECREF(py_address);
Py_XDECREF(py_netmask);
Py_XDECREF(py_broadcast);
Py_XDECREF(py_ptp);
return NULL;
}
/*
* Return NIC MTU. References:
* http://www.i-scream.org/libstatgrab/
* 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.
*/
static PyObject *
psutil_net_if_mtu(PyObject *self, PyObject *args) {
char *nic_name;
int sock = 0;
int ret;
#ifdef PSUTIL_SUNOS10
struct lifreq lifr;
#else
struct ifreq ifr;
#endif
#if defined(__FreeBSD__) || defined(__APPLE__)
if (! PyArg_ParseTuple(args, "s", &nic_name))
return NULL;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1)
goto error;
#ifdef PSUTIL_SUNOS10
strncpy(lifr.lifr_name, nic_name, sizeof(lifr.lifr_name));
ret = ioctl(sock, SIOCGIFMTU, &lifr);
#else
strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name));
ret = ioctl(sock, SIOCGIFMTU, &ifr);
#endif
if (ret == -1)
goto error;
close(sock);
#ifdef PSUTIL_SUNOS10
return Py_BuildValue("i", lifr.lifr_mtu);
#else
return Py_BuildValue("i", ifr.ifr_mtu);
#endif
error:
if (sock != 0)
close(sock);
return PyErr_SetFromErrno(PyExc_OSError);
}
/*
* Inspect NIC flags, returns a bool indicating whether the NIC is
* running. References:
* http://www.i-scream.org/libstatgrab/
*/
static PyObject *
psutil_net_if_flags(PyObject *self, PyObject *args) {
char *nic_name;
int sock = 0;
int ret;
struct ifreq ifr;
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));
ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
if (ret == -1)
goto error;
close(sock);
if ((ifr.ifr_flags & IFF_UP) != 0)
return Py_BuildValue("O", Py_True);
else
return Py_BuildValue("O", Py_False);
error:
if (sock != 0)
close(sock);
return PyErr_SetFromErrno(PyExc_OSError);
}
/*
* net_if_stats() OSX/BSD implementation.
*/
#if defined(PSUTIL_BSD) || defined(PSUTIL_OSX)
#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:
@ -466,8 +267,8 @@ int psutil_get_nic_speed(int ifm_active) {
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(PSUTIL_OPENBSD)
// FreeBSD 4 and others (but NOT OpenBSD) -> #define IFM_1000_T in net/if_media.h
#if defined(IFM_1000_TX) && !defined(OPENBSD)
// FreeBSD 4 and others (but NOT OpenBSD)?
case(IFM_1000_TX):
#endif
#ifdef IFM_1000_FX
@ -577,15 +378,19 @@ int psutil_get_nic_speed(int ifm_active) {
* http://www.i-scream.org/libstatgrab/
*/
static PyObject *
psutil_net_if_duplex_speed(PyObject *self, PyObject *args) {
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;
@ -594,6 +399,22 @@ psutil_net_if_duplex_speed(PyObject *self, PyObject *args) {
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));
@ -613,33 +434,34 @@ psutil_net_if_duplex_speed(PyObject *self, PyObject *args) {
}
close(sock);
return Py_BuildValue("[ii]", duplex, speed);
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);
return PyErr_SetFromErrno(PyExc_OSError);
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
#endif // net_if_stats() OSX/BSD implementation
#endif // net_if_stats() implementation
/*
* define the psutil C module methods and initialize the module.
*/
static PyMethodDef
PsutilMethods[] = {
PsutilMethods[] =
{
{"getpriority", psutil_posix_getpriority, METH_VARARGS,
"Return process priority"},
{"setpriority", psutil_posix_setpriority, METH_VARARGS,
"Set process priority"},
{"net_if_addrs", psutil_net_if_addrs, METH_VARARGS,
"Retrieve NICs information"},
{"net_if_mtu", psutil_net_if_mtu, METH_VARARGS,
"Retrieve NIC MTU"},
{"net_if_flags", psutil_net_if_flags, METH_VARARGS,
"Retrieve NIC flags"},
#if defined(PSUTIL_BSD) || defined(PSUTIL_OSX)
{"net_if_duplex_speed", psutil_net_if_duplex_speed, METH_VARARGS,
#if defined(__FreeBSD__) || defined(__APPLE__)
{"net_if_stats", psutil_net_if_stats, METH_VARARGS,
"Return NIC stats."},
#endif
{NULL, NULL, 0, NULL}
@ -663,7 +485,6 @@ psutil_posix_traverse(PyObject *m, visitproc visit, void *arg) {
return 0;
}
static int
psutil_posix_clear(PyObject *m) {
Py_CLEAR(GETSTATE(m)->error);
@ -698,7 +519,7 @@ void init_psutil_posix(void)
PyObject *module = Py_InitModule("_psutil_posix", PsutilMethods);
#endif
#if defined(PSUTIL_BSD) || defined(PSUTIL_OSX) || defined(PSUTIL_SUNOS) || defined(PSUTIL_AIX)
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__sun)
PyModule_AddIntConstant(module, "AF_LINK", AF_LINK);
#endif

View File

@ -4,5 +4,12 @@
* found in the LICENSE file.
*/
int psutil_pid_exists(long pid);
void psutil_raise_for_pid(long pid, char *msg);
#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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
/*
* 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.
*/
#include <Python.h>
// processes
static PyObject* psutil_proc_basic_info(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cred(PyObject* self, PyObject* args);
static PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args);
static PyObject* psutil_proc_name_and_args(PyObject* self, PyObject* args);
static PyObject* psutil_proc_num_ctx_switches(PyObject* self, PyObject* args);
static PyObject* psutil_proc_query_thread(PyObject* self, PyObject* args);
// system
static PyObject* psutil_boot_time(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args);
static PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args);
static PyObject* psutil_net_io_counters(PyObject* self, PyObject* args);
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

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2009, Jay Loden, 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.
*/
#include <Python.h>
#include <windows.h>
// --- per-process functions
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_create_time(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_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_name(PyObject* self, PyObject* args);
static PyObject* psutil_proc_num_handles(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);
static PyObject* psutil_proc_resume(PyObject* self, PyObject* args);
static PyObject* psutil_proc_suspend(PyObject* self, PyObject* args);
static PyObject* psutil_proc_threads(PyObject* self, PyObject* args);
static PyObject* psutil_proc_username(PyObject* self, PyObject* args);
static PyObject* psutil_proc_wait(PyObject* self, PyObject* args);
#if (PSUTIL_WINVER >= 0x0600) // Windows Vista
static PyObject* psutil_proc_io_priority_get(PyObject* self, PyObject* args);
static PyObject* psutil_proc_io_priority_set(PyObject* self, PyObject* args);
#endif
// --- system-related functions
static PyObject* psutil_boot_time(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_count_logical(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args);
static PyObject* psutil_disk_usage(PyObject* self, PyObject* args);
static PyObject* psutil_net_connections(PyObject* self, PyObject* args);
static PyObject* psutil_net_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_pid_exists(PyObject* self, PyObject* args);
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
static PyObject* psutil_win32_QueryDosDevice(PyObject* self, PyObject* args);
// --- internal
int psutil_proc_suspend_or_resume(DWORD pid, int suspend);

View File

@ -1,10 +1,11 @@
#!/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.
"""Windows platform implementation."""
import contextlib
import errno
import functools
import os
@ -12,49 +13,16 @@ import sys
from collections import namedtuple
from . import _common
try:
from . import _psutil_windows as cext
except ImportError as err:
if str(err).lower().startswith("dll load failed") and \
sys.getwindowsversion()[0] < 6:
# We may get here if:
# 1) we are on an old Windows version
# 2) psutil was installed via pip + wheel
# See: https://github.com/giampaolo/psutil/issues/811
# It must be noted that psutil can still (kind of) work
# on outdated systems if compiled / installed from sources,
# but if we get here it means this this was a wheel (or exe).
msg = "this Windows version is too old (< Windows Vista); "
msg += "psutil 3.4.2 is the latest version which supports Windows "
msg += "2000, XP and 2003 server; it may be possible that psutil "
msg += "will work if compiled from sources though"
raise RuntimeError(msg)
else:
raise
from ._common import conn_tmap
from ._common import ENCODING
from ._common import ENCODING_ERRS
from ._common import isfile_strict
from ._common import memoize_when_activated
from ._common import parse_environ_block
from ._common import sockfam_to_enum
from ._common import socktype_to_enum
from ._common import usage_percent
from ._compat import long
from ._compat import lru_cache
from ._compat import PY3
from ._compat import unicode
from ._compat import xrange
from ._exceptions import AccessDenied
from ._exceptions import NoSuchProcess
from ._exceptions import TimeoutExpired
from ._psutil_windows import ABOVE_NORMAL_PRIORITY_CLASS
from ._psutil_windows import BELOW_NORMAL_PRIORITY_CLASS
from ._psutil_windows import HIGH_PRIORITY_CLASS
from ._psutil_windows import IDLE_PRIORITY_CLASS
from ._psutil_windows import NORMAL_PRIORITY_CLASS
from ._psutil_windows import REALTIME_PRIORITY_CLASS
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
@ -63,28 +31,19 @@ else:
# process priority constants, import from __init__.py:
# http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx
__extra__all__ = [
"win_service_iter", "win_service_get",
"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",
]
__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",
]
# =====================================================================
# --- globals
# =====================================================================
# --- module level constants (gets pushed up to psutil module)
CONN_DELETE_TCB = "DELETE_TCB"
WAIT_TIMEOUT = 0x00000102 # 258 in decimal
ACCESS_DENIED_ERRSET = frozenset([errno.EPERM, errno.EACCES,
cext.ERROR_ACCESS_DENIED])
NO_SUCH_SERVICE_ERRSET = frozenset([cext.ERROR_INVALID_NAME,
cext.ERROR_SERVICE_DOES_NOT_EXIST])
ACCESS_DENIED_SET = frozenset([errno.EPERM, errno.EACCES,
cext.ERROR_ACCESS_DENIED])
if enum is None:
AF_LINK = -1
else:
@ -118,94 +77,43 @@ if enum is not None:
globals().update(Priority.__members__)
pinfo_map = dict(
num_handles=0,
ctx_switches=1,
user_time=2,
kernel_time=3,
create_time=4,
num_threads=5,
io_rcount=6,
io_wcount=7,
io_rbytes=8,
io_wbytes=9,
io_count_others=10,
io_bytes_others=11,
num_page_faults=12,
peak_wset=13,
wset=14,
peak_paged_pool=15,
paged_pool=16,
peak_non_paged_pool=17,
non_paged_pool=18,
pagefile=19,
peak_pagefile=20,
mem_private=21,
)
# =====================================================================
# --- named tuples
# =====================================================================
# psutil.cpu_times()
scputimes = namedtuple('scputimes',
['user', 'system', 'idle', 'interrupt', 'dpc'])
# psutil.virtual_memory()
scputimes = namedtuple('scputimes', ['user', 'system', 'idle'])
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
# psutil.Process.memory_info()
pmem = namedtuple(
'pmem', ['rss', 'vms',
'num_page_faults', 'peak_wset', 'wset', 'peak_paged_pool',
'paged_pool', 'peak_nonpaged_pool', 'nonpaged_pool',
'pagefile', 'peak_pagefile', 'private'])
# psutil.Process.memory_full_info()
pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', ))
# psutil.Process.memory_maps(grouped=True)
pextmem = namedtuple(
'pextmem', ['num_page_faults', 'peak_wset', 'wset', 'peak_paged_pool',
'paged_pool', 'peak_nonpaged_pool', 'nonpaged_pool',
'pagefile', 'peak_pagefile', 'private'])
pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss'])
# psutil.Process.memory_maps(grouped=False)
pmmap_ext = namedtuple(
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
# psutil.Process.io_counters()
pio = namedtuple('pio', ['read_count', 'write_count',
'read_bytes', 'write_bytes',
'other_count', 'other_bytes'])
ntpinfo = namedtuple(
'ntpinfo', ['num_handles', 'ctx_switches', 'user_time', 'kernel_time',
'create_time', 'num_threads', 'io_rcount', 'io_wcount',
'io_rbytes', 'io_wbytes'])
# =====================================================================
# --- utils
# =====================================================================
# set later from __init__.py
NoSuchProcess = None
AccessDenied = None
TimeoutExpired = None
@lru_cache(maxsize=512)
def convert_dos_path(s):
r"""Convert paths using native DOS format like:
"\Device\HarddiskVolume1\Windows\systemew\file.txt"
into:
"C:\Windows\systemew\file.txt"
"""
def _win32_QueryDosDevice(s):
return cext.win32_QueryDosDevice(s)
def _convert_raw_path(s):
# convert paths using native DOS format like:
# "\Device\HarddiskVolume1\Windows\systemew\file.txt"
# into: "C:\Windows\systemew\file.txt"
if PY3 and not isinstance(s, str):
s = s.decode('utf8')
rawdrive = '\\'.join(s.split('\\')[:3])
driveletter = cext.win32_QueryDosDevice(rawdrive)
driveletter = _win32_QueryDosDevice(rawdrive)
return os.path.join(driveletter, s[len(rawdrive):])
def py2_strencode(s):
"""Encode a unicode string to a byte string by using the default fs
encoding + "replace" error handler.
"""
if PY3:
return s
else:
if isinstance(s, str):
return s
else:
return s.encode(ENCODING, errors=ENCODING_ERRS)
# =====================================================================
# --- memory
# =====================================================================
# --- public functions
def virtual_memory():
@ -231,21 +139,15 @@ def swap_memory():
return _common.sswap(total, used, free, percent, 0, 0)
# =====================================================================
# --- disk
# =====================================================================
disk_io_counters = cext.disk_io_counters
def disk_usage(path):
"""Return disk usage associated with path."""
if PY3 and isinstance(path, bytes):
# XXX: do we want to use "strict"? Probably yes, in order
# to fail immediately. After all we are accepting input here...
path = path.decode(ENCODING, errors="strict")
total, free = cext.disk_usage(path)
try:
total, free = cext.disk_usage(path)
except WindowsError:
if not os.path.exists(path):
msg = "No such file or directory: '%s'" % path
raise OSError(errno.ENOENT, msg)
raise
used = total - free
percent = usage_percent(used, total, _round=1)
return _common.sdiskusage(total, used, free, percent)
@ -257,27 +159,18 @@ def disk_partitions(all):
return [_common.sdiskpart(*x) for x in rawlist]
# =====================================================================
# --- CPU
# =====================================================================
def cpu_times():
"""Return system CPU times as a named tuple."""
user, system, idle = cext.cpu_times()
# Internally, GetSystemTimes() is used, and it doesn't return
# interrupt and dpc times. cext.per_cpu_times() does, so we
# rely on it to get those only.
percpu_summed = scputimes(*[sum(n) for n in zip(*cext.per_cpu_times())])
return scputimes(user, system, idle,
percpu_summed.interrupt, percpu_summed.dpc)
return scputimes(user, system, idle)
def per_cpu_times():
"""Return system per-CPU times as a list of named tuples."""
ret = []
for user, system, idle, interrupt, dpc in cext.per_cpu_times():
item = scputimes(user, system, idle, interrupt, dpc)
for cpu_t in cext.per_cpu_times():
user, system, idle = cpu_t
item = scputimes(user, system, idle)
ret.append(item)
return ret
@ -292,26 +185,9 @@ def cpu_count_physical():
return cext.cpu_count_phys()
def cpu_stats():
"""Return CPU statistics."""
ctx_switches, interrupts, dpcs, syscalls = cext.cpu_stats()
soft_interrupts = 0
return _common.scpustats(ctx_switches, interrupts, soft_interrupts,
syscalls)
def cpu_freq():
"""Return CPU frequency.
On Windows per-cpu frequency is not supported.
"""
curr, max_ = cext.cpu_freq()
min_ = 0.0
return [_common.scpufreq(float(curr), min_, float(max_))]
# =====================================================================
# --- network
# =====================================================================
def boot_time():
"""The system boot time expressed in seconds since the epoch."""
return cext.boot_time()
def net_connections(kind, _pid=-1):
@ -326,10 +202,6 @@ def net_connections(kind, _pid=-1):
ret = set()
for item in rawlist:
fd, fam, type, laddr, raddr, status, pid = item
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
status = TCP_STATUSES[status]
fam = sockfam_to_enum(fam)
type = socktype_to_enum(type)
@ -342,13 +214,8 @@ def net_connections(kind, _pid=-1):
def net_if_stats():
"""Get NIC stats (isup, duplex, speed, mtu)."""
ret = {}
rawdict = cext.net_if_stats()
for name, items in rawdict.items():
if not PY3:
assert isinstance(name, unicode), type(name)
name = py2_strencode(name)
ret = cext.net_if_stats()
for name, items in ret.items():
isup, duplex, speed, mtu = items
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
@ -356,273 +223,23 @@ def net_if_stats():
return ret
def net_io_counters():
"""Return network I/O statistics for every network interface
installed on the system as a dict of raw tuples.
"""
ret = cext.net_io_counters()
return dict([(py2_strencode(k), v) for k, v in ret.items()])
def net_if_addrs():
"""Return the addresses associated to each NIC."""
ret = []
for items in cext.net_if_addrs():
items = list(items)
items[0] = py2_strencode(items[0])
ret.append(items)
return ret
# =====================================================================
# --- sensors
# =====================================================================
def sensors_battery():
"""Return battery information."""
# For constants meaning see:
# https://msdn.microsoft.com/en-us/library/windows/desktop/
# aa373232(v=vs.85).aspx
acline_status, flags, percent, secsleft = cext.sensors_battery()
power_plugged = acline_status == 1
no_battery = bool(flags & 128)
charging = bool(flags & 8)
if no_battery:
return None
if power_plugged or charging:
secsleft = _common.POWER_TIME_UNLIMITED
elif secsleft == -1:
secsleft = _common.POWER_TIME_UNKNOWN
return _common.sbattery(percent, secsleft, power_plugged)
# =====================================================================
# --- other system functions
# =====================================================================
_last_btime = 0
def boot_time():
"""The system boot time expressed in seconds since the epoch."""
# This dirty hack is to adjust the precision of the returned
# value which may have a 1 second fluctuation, see:
# https://github.com/giampaolo/psutil/issues/1007
global _last_btime
ret = float(cext.boot_time())
if abs(ret - _last_btime) <= 1:
return _last_btime
else:
_last_btime = ret
return ret
def users():
"""Return currently connected users as a list of namedtuples."""
retlist = []
rawlist = cext.users()
for item in rawlist:
user, hostname, tstamp = item
user = py2_strencode(user)
nt = _common.suser(user, None, hostname, tstamp, None)
nt = _common.suser(user, None, hostname, tstamp)
retlist.append(nt)
return retlist
# =====================================================================
# --- Windows services
# =====================================================================
def win_service_iter():
"""Yields a list of WindowsService instances."""
for name, display_name in cext.winservice_enumerate():
yield WindowsService(py2_strencode(name), py2_strencode(display_name))
def win_service_get(name):
"""Open a Windows service and return it as a WindowsService instance."""
service = WindowsService(name, None)
service._display_name = service._query_config()['display_name']
return service
class WindowsService(object):
"""Represents an installed Windows service."""
def __init__(self, name, display_name):
self._name = name
self._display_name = display_name
def __str__(self):
details = "(name=%r, display_name=%r)" % (
self._name, self._display_name)
return "%s%s" % (self.__class__.__name__, details)
def __repr__(self):
return "<%s at %s>" % (self.__str__(), id(self))
def __eq__(self, other):
# Test for equality with another WindosService object based
# on name.
if not isinstance(other, WindowsService):
return NotImplemented
return self._name == other._name
def __ne__(self, other):
return not self == other
def _query_config(self):
with self._wrap_exceptions():
display_name, binpath, username, start_type = \
cext.winservice_query_config(self._name)
# XXX - update _self.display_name?
return dict(
display_name=py2_strencode(display_name),
binpath=py2_strencode(binpath),
username=py2_strencode(username),
start_type=py2_strencode(start_type))
def _query_status(self):
with self._wrap_exceptions():
status, pid = cext.winservice_query_status(self._name)
if pid == 0:
pid = None
return dict(status=status, pid=pid)
@contextlib.contextmanager
def _wrap_exceptions(self):
"""Ctx manager which translates bare OSError and WindowsError
exceptions into NoSuchProcess and AccessDenied.
"""
try:
yield
except WindowsError as err:
if err.errno in ACCESS_DENIED_ERRSET:
raise AccessDenied(
pid=None, name=self._name,
msg="service %r is not querable (not enough privileges)" %
self._name)
elif err.errno in NO_SUCH_SERVICE_ERRSET or \
err.winerror in NO_SUCH_SERVICE_ERRSET:
raise NoSuchProcess(
pid=None, name=self._name,
msg="service %r does not exist)" % self._name)
else:
raise
# config query
def name(self):
"""The service name. This string is how a service is referenced
and can be passed to win_service_get() to get a new
WindowsService instance.
"""
return self._name
def display_name(self):
"""The service display name. The value is cached when this class
is instantiated.
"""
return self._display_name
def binpath(self):
"""The fully qualified path to the service binary/exe file as
a string, including command line arguments.
"""
return self._query_config()['binpath']
def username(self):
"""The name of the user that owns this service."""
return self._query_config()['username']
def start_type(self):
"""A string which can either be "automatic", "manual" or
"disabled".
"""
return self._query_config()['start_type']
# status query
def pid(self):
"""The process PID, if any, else None. This can be passed
to Process class to control the service's process.
"""
return self._query_status()['pid']
def status(self):
"""Service status as a string."""
return self._query_status()['status']
def description(self):
"""Service long description."""
return py2_strencode(cext.winservice_query_descr(self.name()))
# utils
def as_dict(self):
"""Utility method retrieving all the information above as a
dictionary.
"""
d = self._query_config()
d.update(self._query_status())
d['name'] = self.name()
d['display_name'] = self.display_name()
d['description'] = self.description()
return d
# actions
# XXX: the necessary C bindings for start() and stop() are
# implemented but for now I prefer not to expose them.
# I may change my mind in the future. Reasons:
# - they require Administrator privileges
# - can't implement a timeout for stop() (unless by using a thread,
# which sucks)
# - would require adding ServiceAlreadyStarted and
# ServiceAlreadyStopped exceptions, adding two new APIs.
# - we might also want to have modify(), which would basically mean
# rewriting win32serviceutil.ChangeServiceConfig, which involves a
# lot of stuff (and API constants which would pollute the API), see:
# http://pyxr.sourceforge.net/PyXR/c/python24/lib/site-packages/
# win32/lib/win32serviceutil.py.html#0175
# - psutil is typically about "read only" monitoring stuff;
# win_service_* APIs should only be used to retrieve a service and
# check whether it's running
# def start(self, timeout=None):
# with self._wrap_exceptions():
# cext.winservice_start(self.name())
# if timeout:
# giveup_at = time.time() + timeout
# while True:
# if self.status() == "running":
# return
# else:
# if time.time() > giveup_at:
# raise TimeoutExpired(timeout)
# else:
# time.sleep(.1)
# def stop(self):
# # Note: timeout is not implemented because it's just not
# # possible, see:
# # http://stackoverflow.com/questions/11973228/
# with self._wrap_exceptions():
# return cext.winservice_stop(self.name())
# =====================================================================
# --- processes
# =====================================================================
pids = cext.pids
pid_exists = cext.pid_exists
ppid_map = cext.ppid_map # used internally by Process.children()
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):
@ -634,7 +251,10 @@ def wrap_exceptions(fun):
try:
return fun(self, *args, **kwargs)
except OSError as err:
if err.errno in ACCESS_DENIED_ERRSET:
# support for private module import
if NoSuchProcess is None or AccessDenied is None:
raise
if err.errno in ACCESS_DENIED_SET:
raise AccessDenied(self.pid, self._name)
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._name)
@ -652,23 +272,6 @@ class Process(object):
self._name = None
self._ppid = None
# --- oneshot() stuff
def oneshot_enter(self):
self.oneshot_info.cache_activate()
def oneshot_exit(self):
self.oneshot_info.cache_deactivate()
@memoize_when_activated
def oneshot_info(self):
"""Return multiple information about this process as a
raw tuple.
"""
ret = cext.proc_info(self.pid)
assert len(ret) == len(pinfo_map)
return ret
@wrap_exceptions
def name(self):
"""Return process name, which on Windows is always the final
@ -684,9 +287,9 @@ class Process(object):
try:
# Note: this will fail with AD for most PIDs owned
# by another user but it's faster.
return py2_strencode(os.path.basename(self.exe()))
return os.path.basename(self.exe())
except AccessDenied:
return py2_strencode(cext.proc_name(self.pid))
return cext.proc_name(self.pid)
@wrap_exceptions
def exe(self):
@ -698,22 +301,11 @@ class Process(object):
# see https://github.com/giampaolo/psutil/issues/528
if self.pid in (0, 4):
raise AccessDenied(self.pid, self._name)
return py2_strencode(convert_dos_path(cext.proc_exe(self.pid)))
return _convert_raw_path(cext.proc_exe(self.pid))
@wrap_exceptions
def cmdline(self):
ret = cext.proc_cmdline(self.pid)
if PY3:
return ret
else:
return [py2_strencode(s) for s in ret]
@wrap_exceptions
def environ(self):
ustr = cext.proc_environ(self.pid)
if ustr and not PY3:
assert isinstance(ustr, unicode), type(ustr)
return parse_environ_block(py2_strencode(ustr))
return cext.proc_cmdline(self.pid)
def ppid(self):
try:
@ -725,39 +317,24 @@ class Process(object):
try:
return cext.proc_memory_info(self.pid)
except OSError as err:
if err.errno in ACCESS_DENIED_ERRSET:
if err.errno in ACCESS_DENIED_SET:
# TODO: the C ext can probably be refactored in order
# to get this from cext.proc_info()
info = self.oneshot_info()
return (
info[pinfo_map['num_page_faults']],
info[pinfo_map['peak_wset']],
info[pinfo_map['wset']],
info[pinfo_map['peak_paged_pool']],
info[pinfo_map['paged_pool']],
info[pinfo_map['peak_non_paged_pool']],
info[pinfo_map['non_paged_pool']],
info[pinfo_map['pagefile']],
info[pinfo_map['peak_pagefile']],
info[pinfo_map['mem_private']],
)
return cext.proc_memory_info_2(self.pid)
raise
@wrap_exceptions
def memory_info(self):
# on Windows RSS == WorkingSetSize and VSM == PagefileUsage.
# Underlying C function returns fields of PROCESS_MEMORY_COUNTERS
# struct.
# on Windows RSS == WorkingSetSize and VSM == PagefileUsage
# fields of PROCESS_MEMORY_COUNTERS struct:
# http://msdn.microsoft.com/en-us/library/windows/desktop/
# ms684877(v=vs.85).aspx
t = self._get_raw_meminfo()
rss = t[2] # wset
vms = t[7] # pagefile
return pmem(*(rss, vms, ) + t)
return _common.pmem(t[2], t[7])
@wrap_exceptions
def memory_full_info(self):
basic_mem = self.memory_info()
uss = cext.proc_memory_uss(self.pid)
return pfullmem(*basic_mem + (uss, ))
def memory_info_ex(self):
return pextmem(*self._get_raw_meminfo())
def memory_maps(self):
try:
@ -765,17 +342,14 @@ class Process(object):
except OSError as err:
# XXX - can't use wrap_exceptions decorator as we're
# returning a generator; probably needs refactoring.
if err.errno in ACCESS_DENIED_ERRSET:
if err.errno in ACCESS_DENIED_SET:
raise AccessDenied(self.pid, self._name)
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._name)
raise
else:
for addr, perm, path, rss in raw:
path = convert_dos_path(path)
if not PY3:
assert isinstance(path, unicode), type(path)
path = py2_strencode(path)
path = _convert_raw_path(path)
addr = hex(addr)
yield (addr, perm, path, rss)
@ -783,34 +357,26 @@ class Process(object):
def kill(self):
return cext.proc_kill(self.pid)
@wrap_exceptions
def send_signal(self, sig):
os.kill(self.pid, sig)
@wrap_exceptions
def wait(self, timeout=None):
if timeout is None:
cext_timeout = cext.INFINITE
timeout = cext.INFINITE
else:
# WaitForSingleObject() expects time in milliseconds
cext_timeout = int(timeout * 1000)
while True:
ret = cext.proc_wait(self.pid, cext_timeout)
if ret == WAIT_TIMEOUT:
raise TimeoutExpired(timeout, self.pid, self._name)
if pid_exists(self.pid):
if timeout is None:
continue
else:
raise TimeoutExpired(timeout, self.pid, self._name)
return ret
timeout = int(timeout * 1000)
ret = cext.proc_wait(self.pid, timeout)
if ret == WAIT_TIMEOUT:
# support for private module import
if TimeoutExpired is None:
raise RuntimeError("timeout expired")
raise TimeoutExpired(timeout, self.pid, self._name)
return ret
@wrap_exceptions
def username(self):
if self.pid in (0, 4):
return 'NT AUTHORITY\\SYSTEM'
domain, user = cext.proc_username(self.pid)
return py2_strencode(domain) + '\\' + py2_strencode(user)
return cext.proc_username(self.pid)
@wrap_exceptions
def create_time(self):
@ -820,13 +386,13 @@ class Process(object):
try:
return cext.proc_create_time(self.pid)
except OSError as err:
if err.errno in ACCESS_DENIED_ERRSET:
return self.oneshot_info()[pinfo_map['create_time']]
if err.errno in ACCESS_DENIED_SET:
return ntpinfo(*cext.proc_info(self.pid)).create_time
raise
@wrap_exceptions
def num_threads(self):
return self.oneshot_info()[pinfo_map['num_threads']]
return ntpinfo(*cext.proc_info(self.pid)).num_threads
@wrap_exceptions
def threads(self):
@ -840,16 +406,14 @@ class Process(object):
@wrap_exceptions
def cpu_times(self):
try:
user, system = cext.proc_cpu_times(self.pid)
ret = cext.proc_cpu_times(self.pid)
except OSError as err:
if err.errno in ACCESS_DENIED_ERRSET:
info = self.oneshot_info()
user = info[pinfo_map['user_time']]
system = info[pinfo_map['kernel_time']]
if err.errno in ACCESS_DENIED_SET:
nt = ntpinfo(*cext.proc_info(self.pid))
ret = (nt.user_time, nt.kernel_time)
else:
raise
# Children user/system times are not retrievable (set to 0).
return _common.pcputimes(user, system, 0.0, 0.0)
return _common.pcputimes(*ret)
@wrap_exceptions
def suspend(self):
@ -866,26 +430,24 @@ class Process(object):
# return a normalized pathname since the native C function appends
# "\\" at the and of the path
path = cext.proc_cwd(self.pid)
return py2_strencode(os.path.normpath(path))
return os.path.normpath(path)
@wrap_exceptions
def open_files(self):
if self.pid in (0, 4):
return []
ret = set()
retlist = []
# Filenames come in in native format like:
# "\Device\HarddiskVolume1\Windows\systemew\file.txt"
# 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_dos_path(_file)
if isfile_strict(_file):
if not PY3:
_file = py2_strencode(_file)
_file = _convert_raw_path(_file)
if isfile_strict(_file) and _file not in retlist:
ntuple = _common.popenfile(_file, -1)
ret.add(ntuple)
return list(ret)
retlist.append(ntuple)
return retlist
@wrap_exceptions
def connections(self, kind='inet'):
@ -923,19 +485,12 @@ class Process(object):
try:
ret = cext.proc_io_counters(self.pid)
except OSError as err:
if err.errno in ACCESS_DENIED_ERRSET:
info = self.oneshot_info()
ret = (
info[pinfo_map['io_rcount']],
info[pinfo_map['io_wcount']],
info[pinfo_map['io_rbytes']],
info[pinfo_map['io_wbytes']],
info[pinfo_map['io_count_others']],
info[pinfo_map['io_bytes_others']],
)
if err.errno in ACCESS_DENIED_SET:
nt = ntpinfo(*cext.proc_info(self.pid))
ret = (nt.io_rcount, nt.io_wcount, nt.io_rbytes, nt.io_wbytes)
else:
raise
return pio(*ret)
return _common.pio(*ret)
@wrap_exceptions
def status(self):
@ -982,12 +537,12 @@ class Process(object):
try:
return cext.proc_num_handles(self.pid)
except OSError as err:
if err.errno in ACCESS_DENIED_ERRSET:
return self.oneshot_info()[pinfo_map['num_handles']]
if err.errno in ACCESS_DENIED_SET:
return ntpinfo(*cext.proc_info(self.pid)).num_handles
raise
@wrap_exceptions
def num_ctx_switches(self):
ctx_switches = self.oneshot_info()[pinfo_map['ctx_switches']]
ctx_switches = ntpinfo(*cext.proc_info(self.pid)).ctx_switches
# only voluntary ctx switches are supported
return _common.pctxsw(ctx_switches, 0)

View File

@ -1,79 +0,0 @@
/*
* Copyright (c) 2017, Arnon Yaari
* All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <Python.h>
#include <sys/core.h>
#include <stdlib.h>
#include "common.h"
/* psutil_kread() - read from kernel memory */
int
psutil_kread(
int Kd, /* kernel memory file descriptor */
KA_T addr, /* kernel memory address */
char *buf, /* buffer to receive data */
size_t len) { /* length to read */
int br;
if (lseek64(Kd, (off64_t)addr, L_SET) == (off64_t)-1) {
PyErr_SetFromErrno(PyExc_OSError);
return 1;
}
br = read(Kd, buf, len);
if (br == -1) {
PyErr_SetFromErrno(PyExc_OSError);
return 1;
}
if (br != len) {
PyErr_SetString(PyExc_RuntimeError,
"size mismatch when reading kernel memory fd");
return 1;
}
return 0;
}
struct procentry64 *
psutil_read_process_table(int * num) {
size_t msz;
pid32_t pid = 0;
struct procentry64 *processes = (struct procentry64 *)NULL;
struct procentry64 *p;
int Np = 0; /* number of processes allocated in 'processes' */
int np = 0; /* number of processes read into 'processes' */
int i; /* number of processes read in current iteration */
msz = (size_t)(PROCSIZE * PROCINFO_INCR);
processes = (struct procentry64 *)malloc(msz);
if (!processes) {
PyErr_NoMemory();
return NULL;
}
Np = PROCINFO_INCR;
p = processes;
while ((i = getprocs64(p, PROCSIZE, (struct fdsinfo64 *)NULL, 0, &pid,
PROCINFO_INCR))
== PROCINFO_INCR) {
np += PROCINFO_INCR;
if (np >= Np) {
msz = (size_t)(PROCSIZE * (Np + PROCINFO_INCR));
processes = (struct procentry64 *)realloc((char *)processes, msz);
if (!processes) {
PyErr_NoMemory();
return NULL;
}
Np += PROCINFO_INCR;
}
p = (struct procentry64 *)((char *)processes + (np * PROCSIZE));
}
/* add the number of processes read in the last iteration */
if (i > 0)
np += i;
*num = np;
return processes;
}

View File

@ -1,31 +0,0 @@
/*
* Copyright (c) 2017, Arnon Yaari
* All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef __PSUTIL_AIX_COMMON_H__
#define __PSUTIL_AIX_COMMON_H__
#include <sys/core.h>
#define PROCINFO_INCR (256)
#define PROCSIZE (sizeof(struct procentry64))
#define FDSINFOSIZE (sizeof(struct fdsinfo64))
#define KMEM "/dev/kmem"
typedef u_longlong_t KA_T;
/* psutil_kread() - read from kernel memory */
int psutil_kread(int Kd, /* kernel memory file descriptor */
KA_T addr, /* kernel memory address */
char *buf, /* buffer to receive data */
size_t len); /* length to read */
struct procentry64 *
psutil_read_process_table(
int * num /* out - number of processes read */
);
#endif /* __PSUTIL_AIX_COMMON_H__ */

View File

@ -1,149 +0,0 @@
/*
* Copyright (c) 2017, Arnon Yaari
* All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*! Based on code from
https://lists.samba.org/archive/samba-technical/2009-February/063079.html
!*/
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "ifaddrs.h"
#define MAX(x,y) ((x)>(y)?(x):(y))
#define SIZE(p) MAX((p).sa_len,sizeof(p))
static struct sockaddr *
sa_dup(struct sockaddr *sa1)
{
struct sockaddr *sa2;
size_t sz = sa1->sa_len;
sa2 = (struct sockaddr *) calloc(1, sz);
if (sa2 == NULL)
return NULL;
memcpy(sa2, sa1, sz);
return sa2;
}
void freeifaddrs(struct ifaddrs *ifp)
{
if (NULL == ifp) return;
free(ifp->ifa_name);
free(ifp->ifa_addr);
free(ifp->ifa_netmask);
free(ifp->ifa_dstaddr);
freeifaddrs(ifp->ifa_next);
free(ifp);
}
int getifaddrs(struct ifaddrs **ifap)
{
int sd, ifsize;
char *ccp, *ecp;
struct ifconf ifc;
struct ifreq *ifr;
struct ifaddrs *cifa = NULL; /* current */
struct ifaddrs *pifa = NULL; /* previous */
const size_t IFREQSZ = sizeof(struct ifreq);
int fam;
*ifap = NULL;
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd == -1)
goto error;
/* find how much memory to allocate for the SIOCGIFCONF call */
if (ioctl(sd, SIOCGSIZIFCONF, (caddr_t)&ifsize) < 0)
goto error;
ifc.ifc_req = (struct ifreq *) calloc(1, ifsize);
if (ifc.ifc_req == NULL)
goto error;
ifc.ifc_len = ifsize;
if (ioctl(sd, SIOCGIFCONF, &ifc) < 0)
goto error;
ccp = (char *)ifc.ifc_req;
ecp = ccp + ifsize;
while (ccp < ecp) {
ifr = (struct ifreq *) ccp;
ifsize = sizeof(ifr->ifr_name) + SIZE(ifr->ifr_addr);
fam = ifr->ifr_addr.sa_family;
if (fam == AF_INET || fam == AF_INET6) {
cifa = (struct ifaddrs *) calloc(1, sizeof(struct ifaddrs));
if (cifa == NULL)
goto error;
cifa->ifa_next = NULL;
if (pifa == NULL) *ifap = cifa; /* first one */
else pifa->ifa_next = cifa;
cifa->ifa_name = strdup(ifr->ifr_name);
if (cifa->ifa_name == NULL)
goto error;
cifa->ifa_flags = 0;
cifa->ifa_dstaddr = NULL;
cifa->ifa_addr = sa_dup(&ifr->ifr_addr);
if (cifa->ifa_addr == NULL)
goto error;
if (fam == AF_INET) {
if (ioctl(sd, SIOCGIFNETMASK, ifr, IFREQSZ) < 0)
goto error;
cifa->ifa_netmask = sa_dup(&ifr->ifr_addr);
if (cifa->ifa_netmask == NULL)
goto error;
}
if (0 == ioctl(sd, SIOCGIFFLAGS, ifr)) /* optional */
cifa->ifa_flags = ifr->ifr_flags;
if (fam == AF_INET) {
if (ioctl(sd, SIOCGIFDSTADDR, ifr, IFREQSZ) < 0) {
if (0 == ioctl(sd, SIOCGIFBRDADDR, ifr, IFREQSZ)) {
cifa->ifa_dstaddr = sa_dup(&ifr->ifr_addr);
if (cifa->ifa_dstaddr == NULL)
goto error;
}
}
else {
cifa->ifa_dstaddr = sa_dup(&ifr->ifr_addr);
if (cifa->ifa_dstaddr == NULL)
goto error;
}
}
pifa = cifa;
}
ccp += ifsize;
}
free(ifc.ifc_req);
close(sd);
return 0;
error:
if (ifc.ifc_req != NULL)
free(ifc.ifc_req);
if (sd != -1)
close(sd);
freeifaddrs(*ifap);
return (-1);
}

View File

@ -1,35 +0,0 @@
/*
* Copyright (c) 2017, Arnon Yaari
* All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*! Based on code from
https://lists.samba.org/archive/samba-technical/2009-February/063079.html
!*/
#ifndef GENERIC_AIX_IFADDRS_H
#define GENERIC_AIX_IFADDRS_H
#include <sys/socket.h>
#include <net/if.h>
#undef ifa_dstaddr
#undef ifa_broadaddr
#define ifa_broadaddr ifa_dstaddr
struct ifaddrs {
struct ifaddrs *ifa_next;
char *ifa_name;
unsigned int ifa_flags;
struct sockaddr *ifa_addr;
struct sockaddr *ifa_netmask;
struct sockaddr *ifa_dstaddr;
};
extern int getifaddrs(struct ifaddrs **);
extern void freeifaddrs(struct ifaddrs *);
#endif

View File

@ -1,287 +0,0 @@
/*
* Copyright (c) 2017, Arnon Yaari
* All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Baded on code from lsof:
* http://www.ibm.com/developerworks/aix/library/au-lsof.html
* - dialects/aix/dproc.c:gather_proc_info
* - lib/prfp.c:process_file
* - dialects/aix/dsock.c:process_socket
* - dialects/aix/dproc.c:get_kernel_access
*/
#include <Python.h>
#include <stdlib.h>
#include <fcntl.h>
#define _KERNEL
#include <sys/file.h>
#undef _KERNEL
#include <sys/types.h>
#include <sys/core.h>
#include <sys/domain.h>
#include <sys/un.h>
#include <netinet/in_pcb.h>
#include <arpa/inet.h>
#include "../../_psutil_common.h"
#include "net_kernel_structs.h"
#include "net_connections.h"
#include "common.h"
#define NO_SOCKET (PyObject *)(-1)
static int
read_unp_addr(
int Kd,
KA_T unp_addr,
char *buf,
size_t buflen
) {
struct sockaddr_un *ua = (struct sockaddr_un *)NULL;
struct sockaddr_un un;
struct mbuf64 mb;
int uo;
if (psutil_kread(Kd, unp_addr, (char *)&mb, sizeof(mb))) {
return 1;
}
uo = (int)(mb.m_hdr.mh_data - unp_addr);
if ((uo + sizeof(struct sockaddr)) <= sizeof(mb))
ua = (struct sockaddr_un *)((char *)&mb + uo);
else {
if (psutil_kread(Kd, (KA_T)mb.m_hdr.mh_data,
(char *)&un, sizeof(un))) {
return 1;
}
ua = &un;
}
if (ua && ua->sun_path[0]) {
if (mb.m_len > sizeof(struct sockaddr_un))
mb.m_len = sizeof(struct sockaddr_un);
*((char *)ua + mb.m_len - 1) = '\0';
snprintf(buf, buflen, "%s", ua->sun_path);
}
return 0;
}
static PyObject *
process_file(int Kd, pid32_t pid, int fd, KA_T fp) {
struct file64 f;
struct socket64 s;
struct protosw64 p;
struct domain d;
struct inpcb64 inp;
int fam;
struct tcpcb64 t;
int state = PSUTIL_CONN_NONE;
unsigned char *laddr = (unsigned char *)NULL;
unsigned char *raddr = (unsigned char *)NULL;
int rport, lport;
char laddr_str[INET6_ADDRSTRLEN];
char raddr_str[INET6_ADDRSTRLEN];
struct unpcb64 unp;
char unix_laddr_str[PATH_MAX] = { 0 };
char unix_raddr_str[PATH_MAX] = { 0 };
/* Read file structure */
if (psutil_kread(Kd, fp, (char *)&f, sizeof(f))) {
return NULL;
}
if (!f.f_count || f.f_type != DTYPE_SOCKET) {
return NO_SOCKET;
}
if (psutil_kread(Kd, (KA_T) f.f_data, (char *) &s, sizeof(s))) {
return NULL;
}
if (!s.so_type) {
return NO_SOCKET;
}
if (!s.so_proto) {
PyErr_SetString(PyExc_RuntimeError, "invalid socket protocol handle");
return NULL;
}
if (psutil_kread(Kd, (KA_T)s.so_proto, (char *)&p, sizeof(p))) {
return NULL;
}
if (!p.pr_domain) {
PyErr_SetString(PyExc_RuntimeError, "invalid socket protocol domain");
return NULL;
}
if (psutil_kread(Kd, (KA_T)p.pr_domain, (char *)&d, sizeof(d))) {
return NULL;
}
fam = d.dom_family;
if (fam == AF_INET || fam == AF_INET6) {
/* Read protocol control block */
if (!s.so_pcb) {
PyErr_SetString(PyExc_RuntimeError, "invalid socket PCB");
return NULL;
}
if (psutil_kread(Kd, (KA_T) s.so_pcb, (char *) &inp, sizeof(inp))) {
return NULL;
}
if (p.pr_protocol == IPPROTO_TCP) {
/* If this is a TCP socket, read its control block */
if (inp.inp_ppcb
&& !psutil_kread(Kd, (KA_T)inp.inp_ppcb,
(char *)&t, sizeof(t)))
state = t.t_state;
}
if (fam == AF_INET6) {
laddr = (unsigned char *)&inp.inp_laddr6;
if (!IN6_IS_ADDR_UNSPECIFIED(&inp.inp_faddr6)) {
raddr = (unsigned char *)&inp.inp_faddr6;
rport = (int)ntohs(inp.inp_fport);
}
}
if (fam == AF_INET) {
laddr = (unsigned char *)&inp.inp_laddr;
if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport != 0) {
raddr = (unsigned char *)&inp.inp_faddr;
rport = (int)ntohs(inp.inp_fport);
}
}
lport = (int)ntohs(inp.inp_lport);
inet_ntop(fam, laddr, laddr_str, sizeof(laddr_str));
if (raddr != NULL) {
inet_ntop(fam, raddr, raddr_str, sizeof(raddr_str));
return Py_BuildValue("(iii(si)(si)ii)", fd, fam,
s.so_type, laddr_str, lport, raddr_str,
rport, state, pid);
}
else {
return Py_BuildValue("(iii(si)()ii)", fd, fam,
s.so_type, laddr_str, lport, state,
pid);
}
}
if (fam == AF_UNIX) {
if (psutil_kread(Kd, (KA_T) s.so_pcb, (char *)&unp, sizeof(unp))) {
return NULL;
}
if ((KA_T) f.f_data != (KA_T) unp.unp_socket) {
PyErr_SetString(PyExc_RuntimeError, "unp_socket mismatch");
return NULL;
}
if (unp.unp_addr) {
if (read_unp_addr(Kd, unp.unp_addr, unix_laddr_str,
sizeof(unix_laddr_str))) {
return NULL;
}
}
if (unp.unp_conn) {
if (psutil_kread(Kd, (KA_T) unp.unp_conn, (char *)&unp,
sizeof(unp))) {
return NULL;
}
if (read_unp_addr(Kd, unp.unp_addr, unix_raddr_str,
sizeof(unix_raddr_str))) {
return NULL;
}
}
return Py_BuildValue("(iiissii)", fd, d.dom_family,
s.so_type, unix_laddr_str, unix_raddr_str, PSUTIL_CONN_NONE,
pid);
}
return NO_SOCKET;
}
PyObject *
psutil_net_connections(PyObject *self, PyObject *args) {
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
KA_T fp;
int Kd = -1;
int i, np;
struct procentry64 *p;
struct fdsinfo64 *fds = (struct fdsinfo64 *)NULL;
pid32_t requested_pid;
pid32_t pid;
struct procentry64 *processes = (struct procentry64 *)NULL;
/* the process table */
if (py_retlist == NULL)
goto error;
if (! PyArg_ParseTuple(args, "i", &requested_pid))
goto error;
Kd = open(KMEM, O_RDONLY, 0);
if (Kd < 0) {
PyErr_SetFromErrnoWithFilename(PyExc_OSError, KMEM);
goto error;
}
processes = psutil_read_process_table(&np);
if (!processes)
goto error;
/* Loop through processes */
for (p = processes; np > 0; np--, p++) {
pid = p->pi_pid;
if (requested_pid != -1 && requested_pid != pid)
continue;
if (p->pi_state == 0 || p->pi_state == SZOMB)
continue;
if (!fds) {
fds = (struct fdsinfo64 *)malloc((size_t)FDSINFOSIZE);
if (!fds) {
PyErr_NoMemory();
goto error;
}
}
if (getprocs64((struct procentry64 *)NULL, PROCSIZE, fds, FDSINFOSIZE,
&pid, 1)
!= 1)
continue;
/* loop over file descriptors */
for (i = 0; i < p->pi_maxofile; i++) {
fp = (KA_T)fds->pi_ufd[i].fp;
if (fp) {
py_tuple = process_file(Kd, p->pi_pid, i, fp);
if (py_tuple == NULL)
goto error;
if (py_tuple != NO_SOCKET) {
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
}
}
}
}
close(Kd);
free(processes);
if (fds != NULL)
free(fds);
return py_retlist;
error:
Py_XDECREF(py_tuple);
Py_DECREF(py_retlist);
if (Kd > 0)
close(Kd);
if (processes != NULL)
free(processes);
if (fds != NULL)
free(fds);
return NULL;
}

View File

@ -1,15 +0,0 @@
/*
* Copyright (c) 2017, Arnon Yaari
* All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef __NET_CONNECTIONS_H__
#define __NET_CONNECTIONS_H__
#include <Python.h>
PyObject* psutil_net_connections(PyObject *self, PyObject *args);
#endif /* __NET_CONNECTIONS_H__ */

View File

@ -1,110 +0,0 @@
/*
* Copyright (c) 2017, Arnon Yaari
* All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* The kernel is always 64 bit but Python is usually compiled as a 32 bit
* process. We're reading the kernel memory to get the network connections,
* so we need the structs we read to be defined with 64 bit "pointers".
* Here are the partial definitions of the structs we use, taken from the
* header files, with data type sizes converted to their 64 bit counterparts,
* and unused data truncated. */
#ifdef __64BIT__
/* In case we're in a 64 bit process after all */
#include <sys/socketvar.h>
#include <sys/protosw.h>
#include <sys/unpcb.h>
#include <sys/mbuf_base.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#define file64 file
#define socket64 socket
#define protosw64 protosw
#define inpcb64 inpcb
#define tcpcb64 tcpcb
#define unpcb64 unpcb
#define mbuf64 mbuf
#else
struct file64 {
int f_flag;
int f_count;
int f_options;
int f_type;
u_longlong_t f_data;
};
struct socket64 {
short so_type; /* generic type, see socket.h */
short so_options; /* from socket call, see socket.h */
ushort so_linger; /* time to linger while closing */
short so_state; /* internal state flags SS_*, below */
u_longlong_t so_pcb; /* protocol control block */
u_longlong_t so_proto; /* protocol handle */
};
struct protosw64 {
short pr_type; /* socket type used for */
u_longlong_t pr_domain; /* domain protocol a member of */
short pr_protocol; /* protocol number */
short pr_flags; /* see below */
};
struct inpcb64 {
u_longlong_t inp_next,inp_prev;
/* pointers to other pcb's */
u_longlong_t inp_head; /* pointer back to chain of inpcb's
for this protocol */
u_int32_t inp_iflowinfo; /* input flow label */
u_short inp_fport; /* foreign port */
u_int16_t inp_fatype; /* foreign address type */
union in_addr_6 inp_faddr_6; /* foreign host table entry */
u_int32_t inp_oflowinfo; /* output flow label */
u_short inp_lport; /* local port */
u_int16_t inp_latype; /* local address type */
union in_addr_6 inp_laddr_6; /* local host table entry */
u_longlong_t inp_socket; /* back pointer to socket */
u_longlong_t inp_ppcb; /* pointer to per-protocol pcb */
u_longlong_t space_rt;
struct sockaddr_in6 spare_dst;
u_longlong_t inp_ifa; /* interface address to use */
int inp_flags; /* generic IP/datagram flags */
};
struct tcpcb64 {
u_longlong_t seg__next;
u_longlong_t seg__prev;
short t_state; /* state of this connection */
};
struct unpcb64 {
u_longlong_t unp_socket; /* pointer back to socket */
u_longlong_t unp_vnode; /* if associated with file */
ino_t unp_vno; /* fake vnode number */
u_longlong_t unp_conn; /* control block of connected socket */
u_longlong_t unp_refs; /* referencing socket linked list */
u_longlong_t unp_nextref; /* link in unp_refs list */
u_longlong_t unp_addr; /* bound address of socket */
};
struct m_hdr64
{
u_longlong_t mh_next; /* next buffer in chain */
u_longlong_t mh_nextpkt; /* next chain in queue/record */
long mh_len; /* amount of data in this mbuf */
u_longlong_t mh_data; /* location of data */
};
struct mbuf64
{
struct m_hdr64 m_hdr;
};
#define m_len m_hdr.mh_len
#endif

View File

@ -0,0 +1,265 @@
/*
* Copyright (c) 2009, Jay Loden, 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.
*
* Helper functions related to fetching process information.
* Used by _psutil_bsd module methods.
*/
#include <Python.h>
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/param.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <signal.h>
#include "process_info.h"
/*
* Returns a list of all BSD processes on the system. This routine
* allocates the list and puts it in *procList and a count of the
* number of entries in *procCount. You are responsible for freeing
* this list (use "free" from System framework).
* On success, the function returns 0.
* On error, the function returns a BSD errno value.
*/
int
psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount)
{
int err;
struct kinfo_proc *result;
int done;
static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0 };
// Declaring name as const requires us to cast it when passing it to
// sysctl because the prototype doesn't include the const modifier.
size_t length;
assert( procList != NULL);
assert(*procList == NULL);
assert(procCount != NULL);
*procCount = 0;
/*
* We start by calling sysctl with result == NULL and length == 0.
* That will succeed, and set length to the appropriate length.
* We then allocate a buffer of that size and call sysctl again
* with that buffer. If that succeeds, we're done. If that fails
* with ENOMEM, we have to throw away our buffer and loop. Note
* that the loop causes use to call sysctl with NULL again; this
* is necessary because the ENOMEM failure case sets length to
* the amount of data returned, not the amount of data that
* could have been returned.
*/
result = NULL;
done = 0;
do {
assert(result == NULL);
// Call sysctl with a NULL buffer.
length = 0;
err = sysctl((int *)name, (sizeof(name) / sizeof(*name)) - 1,
NULL, &length, NULL, 0);
if (err == -1)
err = errno;
// Allocate an appropriately sized buffer based on the results
// from the previous call.
if (err == 0) {
result = malloc(length);
if (result == NULL)
err = ENOMEM;
}
// Call sysctl again with the new buffer. If we get an ENOMEM
// error, toss away our buffer and start again.
if (err == 0) {
err = sysctl((int *) name, (sizeof(name) / sizeof(*name)) - 1,
result, &length, NULL, 0);
if (err == -1)
err = errno;
if (err == 0) {
done = 1;
}
else if (err == ENOMEM) {
assert(result != NULL);
free(result);
result = NULL;
err = 0;
}
}
} while (err == 0 && ! done);
// Clean up and establish post conditions.
if (err != 0 && result != NULL) {
free(result);
result = NULL;
}
*procList = result;
*procCount = length / sizeof(struct kinfo_proc);
assert((err == 0) == (*procList != NULL));
return err;
}
char
*psutil_get_cmd_path(long pid, size_t *pathsize)
{
int mib[4];
char *path;
size_t size = 0;
/*
* Make a sysctl() call to get the raw argument space of the process.
*/
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
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)
return NULL;
path = malloc(size);
if (path == NULL) {
PyErr_NoMemory();
return NULL;
}
*pathsize = size;
if (sysctl(mib, 4, path, &size, NULL, 0) == -1) {
free(path);
return NULL; // Insufficient privileges
}
return path;
}
/*
* XXX no longer used; it probably makese sense to remove it.
* Borrowed from psi Python System Information project
*
* Get command arguments and environment variables.
*
* Based on code from ps.
*
* Returns:
* 0 for success;
* -1 for failure (Exception raised);
* 1 for insufficient privileges.
*/
char
*psutil_get_cmd_args(long pid, size_t *argsize)
{
int mib[4], argmax;
size_t size = sizeof(argmax);
char *procargs = NULL;
// Get the maximum process arguments size.
mib[0] = CTL_KERN;
mib[1] = KERN_ARGMAX;
size = sizeof(argmax);
if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1)
return NULL;
// Allocate space for the arguments.
procargs = (char *)malloc(argmax);
if (procargs == NULL) {
PyErr_NoMemory();
return NULL;
}
/*
* Make a sysctl() call to get the raw argument space of the process.
*/
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_ARGS;
mib[3] = pid;
size = argmax;
if (sysctl(mib, 4, procargs, &size, NULL, 0) == -1) {
free(procargs);
return NULL; // Insufficient privileges
}
// return string and set the length of arguments
*argsize = size;
return procargs;
}
// returns the command line as a python list object
PyObject *
psutil_get_arg_list(long pid)
{
char *argstr = NULL;
int pos = 0;
size_t argsize = 0;
PyObject *retlist = Py_BuildValue("[]");
PyObject *item = NULL;
if (pid < 0)
return retlist;
argstr = psutil_get_cmd_args(pid, &argsize);
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
// separator
if (argsize > 0) {
while (pos < argsize) {
item = Py_BuildValue("s", &argstr[pos]);
if (!item)
goto error;
if (PyList_Append(retlist, item))
goto error;
Py_DECREF(item);
pos = pos + strlen(&argstr[pos]) + 1;
}
}
free(argstr);
return retlist;
error:
Py_XDECREF(item);
Py_DECREF(retlist);
if (argstr != NULL)
free(argstr);
return NULL;
}
/*
* Return 1 if PID exists in the current process list, else 0.
*/
int
psutil_pid_exists(long pid)
{
int kill_ret;
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))
return 1;
// otherwise return 0 for PID not found
return 0;
}

View File

@ -0,0 +1,15 @@
/*
* Copyright (c) 2009, Jay Loden, 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.
*/
#include <Python.h>
typedef struct kinfo_proc kinfo_proc;
char *psutil_get_cmd_args(long pid, size_t *argsize);
char *psutil_get_cmd_path(long pid, size_t *pathsize);
int psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount);
int psutil_pid_exists(long pid);
PyObject* psutil_get_arg_list(long pid);

View File

@ -1,368 +0,0 @@
/*
* 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.
*
* Retrieves per-process open socket connections.
*/
#include <Python.h>
#include <sys/user.h>
#include <sys/socketvar.h> // for struct xsocket
#include <sys/un.h>
#include <sys/sysctl.h>
#include <netinet/in.h> // for xinpcb struct
#include <netinet/in_pcb.h>
#include <netinet/tcp_var.h> // for struct xtcpcb
#include <arpa/inet.h> // for inet_ntop()
#include <libutil.h>
#include "../../_psutil_common.h"
#include "../../_psutil_posix.h"
// The tcplist fetching and walking is borrowed from netstat/inet.c.
static char *
psutil_fetch_tcplist(void) {
char *buf;
size_t len;
for (;;) {
if (sysctlbyname("net.inet.tcp.pcblist", NULL, &len, NULL, 0) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
buf = malloc(len);
if (buf == NULL) {
PyErr_NoMemory();
return NULL;
}
if (sysctlbyname("net.inet.tcp.pcblist", buf, &len, NULL, 0) < 0) {
free(buf);
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return buf;
}
}
static int
psutil_sockaddr_port(int family, struct sockaddr_storage *ss) {
struct sockaddr_in6 *sin6;
struct sockaddr_in *sin;
if (family == AF_INET) {
sin = (struct sockaddr_in *)ss;
return (sin->sin_port);
}
else {
sin6 = (struct sockaddr_in6 *)ss;
return (sin6->sin6_port);
}
}
static void *
psutil_sockaddr_addr(int family, struct sockaddr_storage *ss) {
struct sockaddr_in6 *sin6;
struct sockaddr_in *sin;
if (family == AF_INET) {
sin = (struct sockaddr_in *)ss;
return (&sin->sin_addr);
}
else {
sin6 = (struct sockaddr_in6 *)ss;
return (&sin6->sin6_addr);
}
}
static socklen_t
psutil_sockaddr_addrlen(int family) {
if (family == AF_INET)
return (sizeof(struct in_addr));
else
return (sizeof(struct in6_addr));
}
static int
psutil_sockaddr_matches(int family, int port, void *pcb_addr,
struct sockaddr_storage *ss) {
if (psutil_sockaddr_port(family, ss) != port)
return (0);
return (memcmp(psutil_sockaddr_addr(family, ss), pcb_addr,
psutil_sockaddr_addrlen(family)) == 0);
}
#if __FreeBSD_version >= 1200026
static struct xtcpcb *
psutil_search_tcplist(char *buf, struct kinfo_file *kif) {
struct xtcpcb *tp;
struct xinpcb *inp;
#else
static struct tcpcb *
psutil_search_tcplist(char *buf, struct kinfo_file *kif) {
struct tcpcb *tp;
struct inpcb *inp;
#endif
struct xinpgen *xig, *oxig;
struct xsocket *so;
oxig = xig = (struct xinpgen *)buf;
for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
xig->xig_len > sizeof(struct xinpgen);
xig = (struct xinpgen *)((char *)xig + xig->xig_len)) {
#if __FreeBSD_version >= 1200026
tp = (struct xtcpcb *)xig;
inp = &tp->xt_inp;
so = &inp->xi_socket;
#else
tp = &((struct xtcpcb *)xig)->xt_tp;
inp = &((struct xtcpcb *)xig)->xt_inp;
so = &((struct xtcpcb *)xig)->xt_socket;
#endif
if (so->so_type != kif->kf_sock_type ||
so->xso_family != kif->kf_sock_domain ||
so->xso_protocol != kif->kf_sock_protocol)
continue;
if (kif->kf_sock_domain == AF_INET) {
if (!psutil_sockaddr_matches(
AF_INET, inp->inp_lport, &inp->inp_laddr,
#if __FreeBSD_version < 1200031
&kif->kf_sa_local))
#else
&kif->kf_un.kf_sock.kf_sa_local))
#endif
continue;
if (!psutil_sockaddr_matches(
AF_INET, inp->inp_fport, &inp->inp_faddr,
#if __FreeBSD_version < 1200031
&kif->kf_sa_peer))
#else
&kif->kf_un.kf_sock.kf_sa_peer))
#endif
continue;
} else {
if (!psutil_sockaddr_matches(
AF_INET6, inp->inp_lport, &inp->in6p_laddr,
#if __FreeBSD_version < 1200031
&kif->kf_sa_local))
#else
&kif->kf_un.kf_sock.kf_sa_local))
#endif
continue;
if (!psutil_sockaddr_matches(
AF_INET6, inp->inp_fport, &inp->in6p_faddr,
#if __FreeBSD_version < 1200031
&kif->kf_sa_peer))
#else
&kif->kf_un.kf_sock.kf_sa_peer))
#endif
continue;
}
return (tp);
}
return NULL;
}
PyObject *
psutil_proc_connections(PyObject *self, PyObject *args) {
// Return connections opened by process.
long pid;
int i;
int cnt;
struct kinfo_file *freep = NULL;
struct kinfo_file *kif;
char *tcplist = NULL;
#if __FreeBSD_version >= 1200026
struct xtcpcb *tcp;
#else
struct tcpcb *tcp;
#endif
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
PyObject *py_laddr = NULL;
PyObject *py_raddr = NULL;
PyObject *py_af_filter = NULL;
PyObject *py_type_filter = NULL;
PyObject *py_family = NULL;
PyObject *py_type = NULL;
if (py_retlist == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "lOO", &pid, &py_af_filter, &py_type_filter))
goto error;
if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) {
PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence");
goto error;
}
errno = 0;
freep = kinfo_getfile(pid, &cnt);
if (freep == NULL) {
psutil_raise_for_pid(pid, "kinfo_getfile()");
goto error;
}
tcplist = psutil_fetch_tcplist();
if (tcplist == NULL) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
for (i = 0; i < cnt; i++) {
int lport, rport, state;
char lip[200], rip[200];
char path[PATH_MAX];
int inseq;
py_tuple = NULL;
py_laddr = NULL;
py_raddr = NULL;
kif = &freep[i];
if (kif->kf_type == KF_TYPE_SOCKET) {
// apply filters
py_family = PyLong_FromLong((long)kif->kf_sock_domain);
inseq = PySequence_Contains(py_af_filter, py_family);
Py_DECREF(py_family);
if (inseq == 0)
continue;
py_type = PyLong_FromLong((long)kif->kf_sock_type);
inseq = PySequence_Contains(py_type_filter, py_type);
Py_DECREF(py_type);
if (inseq == 0)
continue;
// IPv4 / IPv6 socket
if ((kif->kf_sock_domain == AF_INET) ||
(kif->kf_sock_domain == AF_INET6)) {
// fill status
state = PSUTIL_CONN_NONE;
if (kif->kf_sock_type == SOCK_STREAM) {
tcp = psutil_search_tcplist(tcplist, kif);
if (tcp != NULL)
state = (int)tcp->t_state;
}
// build addr and port
inet_ntop(
kif->kf_sock_domain,
psutil_sockaddr_addr(kif->kf_sock_domain,
#if __FreeBSD_version < 1200031
&kif->kf_sa_local),
#else
&kif->kf_un.kf_sock.kf_sa_local),
#endif
lip,
sizeof(lip));
inet_ntop(
kif->kf_sock_domain,
psutil_sockaddr_addr(kif->kf_sock_domain,
#if __FreeBSD_version < 1200031
&kif->kf_sa_peer),
#else
&kif->kf_un.kf_sock.kf_sa_peer),
#endif
rip,
sizeof(rip));
lport = htons(psutil_sockaddr_port(kif->kf_sock_domain,
#if __FreeBSD_version < 1200031
&kif->kf_sa_local));
#else
&kif->kf_un.kf_sock.kf_sa_local));
#endif
rport = htons(psutil_sockaddr_port(kif->kf_sock_domain,
#if __FreeBSD_version < 1200031
&kif->kf_sa_peer));
#else
&kif->kf_un.kf_sock.kf_sa_peer));
#endif
// construct python tuple/list
py_laddr = Py_BuildValue("(si)", lip, lport);
if (!py_laddr)
goto error;
if (rport != 0)
py_raddr = Py_BuildValue("(si)", rip, rport);
else
py_raddr = Py_BuildValue("()");
if (!py_raddr)
goto error;
py_tuple = Py_BuildValue(
"(iiiNNi)",
kif->kf_fd,
kif->kf_sock_domain,
kif->kf_sock_type,
py_laddr,
py_raddr,
state
);
if (!py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
}
// UNIX socket.
// Note: remote path cannot be determined.
else if (kif->kf_sock_domain == AF_UNIX) {
struct sockaddr_un *sun;
#if __FreeBSD_version < 1200031
sun = (struct sockaddr_un *)&kif->kf_sa_local;
#else
sun = (struct sockaddr_un *)&kif->kf_un.kf_sock.kf_sa_local;
#endif
snprintf(
path, sizeof(path), "%.*s",
(int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))),
sun->sun_path);
py_laddr = PyUnicode_DecodeFSDefault(path);
if (! py_laddr)
goto error;
py_tuple = Py_BuildValue(
"(iiiOsi)",
kif->kf_fd,
kif->kf_sock_domain,
kif->kf_sock_type,
py_laddr,
"", // raddr can't be determined
PSUTIL_CONN_NONE
);
if (!py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
Py_DECREF(py_laddr);
}
}
}
free(freep);
free(tcplist);
return py_retlist;
error:
Py_XDECREF(py_tuple);
Py_XDECREF(py_laddr);
Py_XDECREF(py_raddr);
Py_DECREF(py_retlist);
if (freep != NULL)
free(freep);
if (tcplist != NULL)
free(tcplist);
return NULL;
}

View File

@ -1,9 +0,0 @@
/*
* 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.
*/
#include <Python.h>
PyObject* psutil_proc_connections(PyObject* self, PyObject* args);

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +0,0 @@
/*
* Copyright (c) 2009, Jay Loden, 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.
*/
#include <Python.h>
typedef struct kinfo_proc kinfo_proc;
int psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount);
int psutil_kinfo_proc(const pid_t pid, struct kinfo_proc *proc);
//
PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args);
PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args);
PyObject* psutil_get_cmdline(long pid);
PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args);
PyObject* psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args);
PyObject* psutil_proc_cpu_affinity_set(PyObject* self, PyObject* args);
PyObject* psutil_proc_cwd(PyObject* self, PyObject* args);
PyObject* psutil_proc_exe(PyObject* self, PyObject* args);
PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args);
PyObject* psutil_proc_num_fds(PyObject* self, PyObject* args);
PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args);
PyObject* psutil_proc_threads(PyObject* self, PyObject* args);
PyObject* psutil_swap_mem(PyObject* self, PyObject* args);
PyObject* psutil_virtual_mem(PyObject* self, PyObject* args);
PyObject* psutil_cpu_stats(PyObject* self, PyObject* args);
#if defined(PSUTIL_FREEBSD)
PyObject* psutil_sensors_battery(PyObject* self, PyObject* args);
#endif

View File

@ -1,362 +0,0 @@
/*
* 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.
*
* Retrieves system-wide open socket connections. This is based off of
* sockstat utility source code:
* https://github.com/freebsd/freebsd/blob/master/usr.bin/sockstat/sockstat.c
*/
#include <Python.h>
#include <sys/user.h>
#include <sys/file.h>
#include <sys/socketvar.h> // for struct xsocket
#include <sys/un.h>
#include <sys/unpcb.h>
#include <sys/sysctl.h>
#include <netinet/in.h> // for xinpcb struct
#include <netinet/ip.h>
#include <netinet/in_pcb.h>
#include <netinet/tcp_var.h> // for struct xtcpcb
#include <arpa/inet.h> // for inet_ntop()
#include "../../_psutil_common.h"
#include "../../_psutil_posix.h"
static struct xfile *psutil_xfiles;
static int psutil_nxfiles;
int
psutil_populate_xfiles() {
size_t len;
if ((psutil_xfiles = malloc(len = sizeof *psutil_xfiles)) == NULL) {
PyErr_NoMemory();
return 0;
}
while (sysctlbyname("kern.file", psutil_xfiles, &len, 0, 0) == -1) {
if (errno != ENOMEM) {
PyErr_SetFromErrno(0);
return 0;
}
len *= 2;
if ((psutil_xfiles = realloc(psutil_xfiles, len)) == NULL) {
PyErr_NoMemory();
return 0;
}
}
if (len > 0 && psutil_xfiles->xf_size != sizeof *psutil_xfiles) {
PyErr_Format(PyExc_RuntimeError, "struct xfile size mismatch");
return 0;
}
psutil_nxfiles = len / sizeof *psutil_xfiles;
return 1;
}
struct xfile *
psutil_get_file_from_sock(void *sock) {
struct xfile *xf;
int n;
for (xf = psutil_xfiles, n = 0; n < psutil_nxfiles; ++n, ++xf) {
if (xf->xf_data == sock)
return xf;
}
return NULL;
}
// Reference:
// https://github.com/freebsd/freebsd/blob/master/usr.bin/sockstat/sockstat.c
int psutil_gather_inet(int proto, PyObject *py_retlist) {
struct xinpgen *xig, *exig;
struct xinpcb *xip;
struct xtcpcb *xtp;
#if __FreeBSD_version >= 1200026
struct xinpcb *inp;
#else
struct inpcb *inp;
#endif
struct xsocket *so;
const char *varname = NULL;
size_t len, bufsize;
void *buf;
int retry;
int type;
PyObject *py_tuple = NULL;
PyObject *py_laddr = NULL;
PyObject *py_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;
}
buf = NULL;
bufsize = 8192;
retry = 5;
do {
for (;;) {
buf = realloc(buf, bufsize);
if (buf == NULL)
continue; // XXX
len = bufsize;
if (sysctlbyname(varname, buf, &len, NULL, 0) == 0)
break;
if (errno != ENOMEM) {
PyErr_SetFromErrno(0);
goto error;
}
bufsize *= 2;
}
xig = (struct xinpgen *)buf;
exig = (struct xinpgen *)(void *)((char *)buf + len - sizeof *exig);
if (xig->xig_len != sizeof *xig || exig->xig_len != sizeof *exig) {
PyErr_Format(PyExc_RuntimeError, "struct xinpgen size mismatch");
goto error;
}
} while (xig->xig_gen != exig->xig_gen && retry--);
for (;;) {
struct xfile *xf;
int lport, rport, 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");
goto error;
}
inp = &xtp->xt_inp;
#if __FreeBSD_version >= 1200026
so = &inp->xi_socket;
status = xtp->t_state;
#else
so = &xtp->xt_socket;
status = xtp->xt_tp.t_state;
#endif
break;
case IPPROTO_UDP:
xip = (struct xinpcb *)xig;
if (xip->xi_len != sizeof *xip) {
PyErr_Format(PyExc_RuntimeError,
"struct xinpcb size mismatch");
goto error;
}
#if __FreeBSD_version >= 1200026
inp = xip;
#else
inp = &xip->xi_inp;
#endif
so = &xip->xi_socket;
status = PSUTIL_CONN_NONE;
break;
default:
PyErr_Format(PyExc_RuntimeError, "invalid proto");
goto error;
}
char lip[200], rip[200];
xf = psutil_get_file_from_sock(so->xso_so);
if (xf == NULL)
continue;
lport = ntohs(inp->inp_lport);
rport = ntohs(inp->inp_fport);
if (inp->inp_vflag & INP_IPV4) {
family = AF_INET;
inet_ntop(AF_INET, &inp->inp_laddr.s_addr, lip, sizeof(lip));
inet_ntop(AF_INET, &inp->inp_faddr.s_addr, rip, sizeof(rip));
}
else if (inp->inp_vflag & INP_IPV6) {
family = AF_INET6;
inet_ntop(AF_INET6, &inp->in6p_laddr.s6_addr, lip, sizeof(lip));
inet_ntop(AF_INET6, &inp->in6p_faddr.s6_addr, rip, sizeof(rip));
}
// construct python tuple/list
py_laddr = Py_BuildValue("(si)", lip, lport);
if (!py_laddr)
goto error;
if (rport != 0)
py_raddr = Py_BuildValue("(si)", rip, rport);
else
py_raddr = Py_BuildValue("()");
if (!py_raddr)
goto error;
py_tuple = Py_BuildValue(
"(iiiNNii)",
xf->xf_fd, // fd
family, // family
type, // type
py_laddr, // laddr
py_raddr, // raddr
status, // status
xf->xf_pid); // pid
if (!py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
}
free(buf);
return 1;
error:
Py_XDECREF(py_tuple);
Py_XDECREF(py_laddr);
Py_XDECREF(py_raddr);
free(buf);
return 0;
}
int psutil_gather_unix(int proto, PyObject *py_retlist) {
struct xunpgen *xug, *exug;
struct xunpcb *xup;
const char *varname = NULL;
const char *protoname = NULL;
size_t len;
size_t bufsize;
void *buf;
int retry;
struct sockaddr_un *sun;
char path[PATH_MAX];
PyObject *py_tuple = NULL;
PyObject *py_lpath = 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;
}
buf = NULL;
bufsize = 8192;
retry = 5;
do {
for (;;) {
buf = realloc(buf, bufsize);
if (buf == NULL) {
PyErr_NoMemory();
goto error;
}
len = bufsize;
if (sysctlbyname(varname, buf, &len, NULL, 0) == 0)
break;
if (errno != ENOMEM) {
PyErr_SetFromErrno(0);
goto error;
}
bufsize *= 2;
}
xug = (struct xunpgen *)buf;
exug = (struct xunpgen *)(void *)
((char *)buf + len - sizeof *exug);
if (xug->xug_len != sizeof *xug || exug->xug_len != sizeof *exug) {
PyErr_Format(PyExc_RuntimeError, "struct xinpgen size mismatch");
goto error;
}
} while (xug->xug_gen != exug->xug_gen && retry--);
for (;;) {
struct xfile *xf;
xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len);
if (xug >= exug)
break;
xup = (struct xunpcb *)xug;
if (xup->xu_len != sizeof *xup)
goto error;
xf = psutil_get_file_from_sock(xup->xu_socket.xso_so);
if (xf == NULL)
continue;
sun = (struct sockaddr_un *)&xup->xu_addr;
snprintf(path, sizeof(path), "%.*s",
(int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))),
sun->sun_path);
py_lpath = PyUnicode_DecodeFSDefault(path);
if (! py_lpath)
goto error;
py_tuple = Py_BuildValue("(iiiOsii)",
xf->xf_fd, // fd
AF_UNIX, // family
proto, // type
py_lpath, // lpath
"", // rath
PSUTIL_CONN_NONE, // status
xf->xf_pid); // pid
if (!py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_lpath);
Py_DECREF(py_tuple);
}
free(buf);
return 1;
error:
Py_XDECREF(py_tuple);
Py_XDECREF(py_lpath);
free(buf);
return 0;
}
PyObject*
psutil_net_connections(PyObject* self, PyObject* args) {
// Return system-wide open connections.
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)
goto error;
if (psutil_gather_unix(SOCK_STREAM, py_retlist) == 0)
goto error;
if (psutil_gather_unix(SOCK_DGRAM, py_retlist) == 0)
goto error;
free(psutil_xfiles);
return py_retlist;
error:
Py_DECREF(py_retlist);
free(psutil_xfiles);
return NULL;
}

View File

@ -1,10 +0,0 @@
/*
* 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.
*/
#include <Python.h>
PyObject* psutil_net_connections(PyObject* self, PyObject* args);

View File

@ -1,447 +0,0 @@
/*
* Copyright (c) 2009, Giampaolo Rodola'.
* Copyright (c) 2015, Ryo ONODERA.
* All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <Python.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/cdefs.h>
#include <arpa/inet.h>
#include <sys/queue.h>
#include <sys/un.h>
#include <sys/file.h>
#include "../../_psutil_common.h"
#include "../../_psutil_posix.h"
// address family filter
enum af_filter {
INET,
INET4,
INET6,
TCP,
TCP4,
TCP6,
UDP,
UDP4,
UDP6,
UNIX,
ALL,
};
// kinfo_file results
struct kif {
SLIST_ENTRY(kif) kifs;
struct kinfo_file *kif;
};
// kinfo_file results list
SLIST_HEAD(kifhead, kif) kihead = SLIST_HEAD_INITIALIZER(kihead);
// kinfo_pcb results
struct kpcb {
SLIST_ENTRY(kpcb) kpcbs;
struct kinfo_pcb *kpcb;
};
// kinfo_pcb results list
SLIST_HEAD(kpcbhead, kpcb) kpcbhead = SLIST_HEAD_INITIALIZER(kpcbhead);
static void psutil_kiflist_init(void);
static void psutil_kiflist_clear(void);
static void psutil_kpcblist_init(void);
static void psutil_kpcblist_clear(void);
static int psutil_get_files(void);
static int psutil_get_sockets(const char *name);
static int psutil_get_info(int aff);
// Initialize kinfo_file results list.
static void
psutil_kiflist_init(void) {
SLIST_INIT(&kihead);
return;
}
// Clear kinfo_file results list.
static void
psutil_kiflist_clear(void) {
while (!SLIST_EMPTY(&kihead)) {
SLIST_REMOVE_HEAD(&kihead, kifs);
}
return;
}
// Initialize kinof_pcb result list.
static void
psutil_kpcblist_init(void) {
SLIST_INIT(&kpcbhead);
return;
}
// Clear kinof_pcb result list.
static void
psutil_kpcblist_clear(void) {
while (!SLIST_EMPTY(&kpcbhead)) {
SLIST_REMOVE_HEAD(&kpcbhead, kpcbs);
}
return;
}
// Get all open files including socket.
static int
psutil_get_files(void) {
size_t len;
size_t j;
int mib[6];
char *buf;
off_t offset;
mib[0] = CTL_KERN;
mib[1] = KERN_FILE2;
mib[2] = KERN_FILE_BYFILE;
mib[3] = 0;
mib[4] = sizeof(struct kinfo_file);
mib[5] = 0;
if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) {
PyErr_SetFromErrno(PyExc_OSError);
return -1;
}
offset = len % sizeof(off_t);
mib[5] = len / sizeof(struct kinfo_file);
if ((buf = malloc(len + offset)) == NULL) {
PyErr_NoMemory();
return -1;
}
if (sysctl(mib, 6, buf + offset, &len, NULL, 0) == -1) {
free(buf);
PyErr_SetFromErrno(PyExc_OSError);
return -1;
}
len /= sizeof(struct kinfo_file);
struct kinfo_file *ki = (struct kinfo_file *)(buf + offset);
for (j = 0; j < len; j++) {
struct kif *kif = malloc(sizeof(struct kif));
kif->kif = &ki[j];
SLIST_INSERT_HEAD(&kihead, kif, kifs);
}
/*
// debug
struct kif *k;
SLIST_FOREACH(k, &kihead, kifs) {
printf("%d\n", k->kif->ki_pid);
}
*/
return 0;
}
// Get open sockets.
static int
psutil_get_sockets(const char *name) {
size_t namelen;
int mib[8];
struct kinfo_pcb *pcb;
size_t len;
size_t j;
memset(mib, 0, sizeof(mib));
if (sysctlnametomib(name, mib, &namelen) == -1) {
PyErr_SetFromErrno(PyExc_OSError);
return -1;
}
if (sysctl(mib, __arraycount(mib), NULL, &len, NULL, 0) == -1) {
PyErr_SetFromErrno(PyExc_OSError);
return -1;
}
if ((pcb = malloc(len)) == NULL) {
PyErr_NoMemory();
return -1;
}
memset(pcb, 0, len);
mib[6] = sizeof(*pcb);
mib[7] = len / sizeof(*pcb);
if (sysctl(mib, __arraycount(mib), pcb, &len, NULL, 0) == -1) {
free(pcb);
PyErr_SetFromErrno(PyExc_OSError);
return -1;
}
len /= sizeof(struct kinfo_pcb);
struct kinfo_pcb *kp = (struct kinfo_pcb *)pcb;
for (j = 0; j < len; j++) {
struct kpcb *kpcb = malloc(sizeof(struct kpcb));
kpcb->kpcb = &kp[j];
SLIST_INSERT_HEAD(&kpcbhead, kpcb, kpcbs);
}
/*
// debug
struct kif *k;
struct kpcb *k;
SLIST_FOREACH(k, &kpcbhead, kpcbs) {
printf("ki_type: %d\n", k->kpcb->ki_type);
printf("ki_family: %d\n", k->kpcb->ki_family);
}
*/
return 0;
}
// Collect open file and connections.
static int
psutil_get_info(int aff) {
switch (aff) {
case INET:
if (psutil_get_sockets("net.inet.tcp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet.udp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0)
return -1;
break;
case INET4:
if (psutil_get_sockets("net.inet.tcp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet.udp.pcblist") != 0)
return -1;
break;
case INET6:
if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0)
return -1;
break;
case TCP:
if (psutil_get_sockets("net.inet.tcp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0)
return -1;
break;
case TCP4:
if (psutil_get_sockets("net.inet.tcp.pcblist") != 0)
return -1;
break;
case TCP6:
if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0)
return -1;
break;
case UDP:
if (psutil_get_sockets("net.inet.udp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0)
return -1;
break;
case UDP4:
if (psutil_get_sockets("net.inet.udp.pcblist") != 0)
return -1;
break;
case UDP6:
if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0)
return -1;
break;
case UNIX:
if (psutil_get_sockets("net.local.stream.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.local.seqpacket.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.local.dgram.pcblist") != 0)
return -1;
break;
case ALL:
if (psutil_get_sockets("net.inet.tcp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet.udp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.local.stream.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.local.seqpacket.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.local.dgram.pcblist") != 0)
return -1;
break;
}
return 0;
}
/*
* Return system-wide connections (unless a pid != -1 is passed).
*/
PyObject *
psutil_net_connections(PyObject *self, PyObject *args) {
char laddr[PATH_MAX];
char raddr[PATH_MAX];
int32_t lport;
int32_t rport;
int32_t status;
pid_t pid;
PyObject *py_tuple = NULL;
PyObject *py_laddr = NULL;
PyObject *py_raddr = NULL;
PyObject *py_retlist = PyList_New(0);
if (py_retlist == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
psutil_kiflist_init();
psutil_kpcblist_init();
if (psutil_get_files() != 0)
goto error;
if (psutil_get_info(ALL) != 0)
goto error;
struct kif *k;
SLIST_FOREACH(k, &kihead, kifs) {
struct kpcb *kp;
if ((pid != -1) && (k->kif->ki_pid != (unsigned int)pid))
continue;
SLIST_FOREACH(kp, &kpcbhead, kpcbs) {
if (k->kif->ki_fdata != kp->kpcb->ki_sockaddr)
continue;
// IPv4 or IPv6
if ((kp->kpcb->ki_family == AF_INET) ||
(kp->kpcb->ki_family == AF_INET6)) {
if (kp->kpcb->ki_family == AF_INET) {
// IPv4
struct sockaddr_in *sin_src =
(struct sockaddr_in *)&kp->kpcb->ki_src;
struct sockaddr_in *sin_dst =
(struct sockaddr_in *)&kp->kpcb->ki_dst;
// source addr and port
inet_ntop(AF_INET, &sin_src->sin_addr, laddr,
sizeof(laddr));
lport = ntohs(sin_src->sin_port);
// remote addr and port
inet_ntop(AF_INET, &sin_dst->sin_addr, raddr,
sizeof(raddr));
rport = ntohs(sin_dst->sin_port);
}
else {
// IPv6
struct sockaddr_in6 *sin6_src =
(struct sockaddr_in6 *)&kp->kpcb->ki_src;
struct sockaddr_in6 *sin6_dst =
(struct sockaddr_in6 *)&kp->kpcb->ki_dst;
// local addr and port
inet_ntop(AF_INET6, &sin6_src->sin6_addr, laddr,
sizeof(laddr));
lport = ntohs(sin6_src->sin6_port);
// remote addr and port
inet_ntop(AF_INET6, &sin6_dst->sin6_addr, raddr,
sizeof(raddr));
rport = ntohs(sin6_dst->sin6_port);
}
// status
if (kp->kpcb->ki_type == SOCK_STREAM)
status = kp->kpcb->ki_tstate;
else
status = PSUTIL_CONN_NONE;
// build addr tuple
py_laddr = Py_BuildValue("(si)", laddr, lport);
if (! py_laddr)
goto error;
if (rport != 0)
py_raddr = Py_BuildValue("(si)", raddr, rport);
else
py_raddr = Py_BuildValue("()");
if (! py_raddr)
goto error;
}
else if (kp->kpcb->ki_family == AF_UNIX) {
// UNIX sockets
struct sockaddr_un *sun_src =
(struct sockaddr_un *)&kp->kpcb->ki_src;
struct sockaddr_un *sun_dst =
(struct sockaddr_un *)&kp->kpcb->ki_dst;
strcpy(laddr, sun_src->sun_path);
strcpy(raddr, sun_dst->sun_path);
status = PSUTIL_CONN_NONE;
py_laddr = PyUnicode_DecodeFSDefault(laddr);
if (! py_laddr)
goto error;
py_raddr = PyUnicode_DecodeFSDefault(raddr);
if (! py_raddr)
goto error;
}
else {
continue;
}
// append tuple to list
py_tuple = Py_BuildValue(
"(iiiOOii)",
k->kif->ki_fd,
kp->kpcb->ki_family,
kp->kpcb->ki_type,
py_laddr,
py_raddr,
status,
k->kif->ki_pid);
if (! py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_laddr);
Py_DECREF(py_raddr);
Py_DECREF(py_tuple);
}
}
psutil_kiflist_clear();
psutil_kpcblist_clear();
return py_retlist;
error:
Py_XDECREF(py_tuple);
Py_XDECREF(py_laddr);
Py_XDECREF(py_raddr);
return 0;
}

View File

@ -1,10 +0,0 @@
/*
* Copyright (c) 2009, Giampaolo Rodola'.
* Copyright (c) 2015, Ryo ONODERA.
* All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
PyObject *psutil_proc_connections(PyObject *, PyObject *);
PyObject *psutil_net_connections(PyObject *, PyObject *);

View File

@ -1,652 +0,0 @@
/*
* Copyright (c) 2009, Giampaolo Rodola', Landry Breuil.
* All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Platform-specific module methods for NetBSD.
*/
#if defined(PSUTIL_NETBSD)
#define _KMEMUSER
#endif
#include <Python.h>
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/swap.h> // for swap_mem
#include <signal.h>
#include <kvm.h>
// connection stuff
#include <netdb.h> // for NI_MAXHOST
#include <sys/socket.h>
#include <sys/sched.h> // for CPUSTATES & CP_*
#define _KERNEL // for DTYPE_*
#include <sys/file.h>
#undef _KERNEL
#include <sys/disk.h> // struct diskstats
#include <netinet/in.h>
#include <arpa/inet.h>
#include "specific.h"
#include "../../_psutil_common.h"
#include "../../_psutil_posix.h"
#define PSUTIL_KPT2DOUBLE(t) (t ## _sec + t ## _usec / 1000000.0)
#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0)
// ============================================================================
// Utility functions
// ============================================================================
int
psutil_kinfo_proc(pid_t pid, kinfo_proc *proc) {
// Fills a kinfo_proc struct based on process pid.
int ret;
int mib[6];
size_t size = sizeof(kinfo_proc);
mib[0] = CTL_KERN;
mib[1] = KERN_PROC2;
mib[2] = KERN_PROC_PID;
mib[3] = pid;
mib[4] = size;
mib[5] = 1;
ret = sysctl((int*)mib, 6, proc, &size, NULL, 0);
if (ret == -1) {
PyErr_SetFromErrno(PyExc_OSError);
return -1;
}
// sysctl stores 0 in the size if we can't find the process information.
if (size == 0) {
NoSuchProcess("");
return -1;
}
return 0;
}
struct kinfo_file *
kinfo_getfile(pid_t pid, int* cnt) {
// Mimic's FreeBSD kinfo_file call, taking a pid and a ptr to an
// int as arg and returns an array with cnt struct kinfo_file.
int mib[6];
size_t len;
struct kinfo_file* kf;
mib[0] = CTL_KERN;
mib[1] = KERN_FILE2;
mib[2] = KERN_FILE_BYPID;
mib[3] = (int) pid;
mib[4] = sizeof(struct kinfo_file);
mib[5] = 0;
// get the size of what would be returned
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
if ((kf = malloc(len)) == NULL) {
PyErr_NoMemory();
return NULL;
}
mib[5] = (int)(len / sizeof(struct kinfo_file));
if (sysctl(mib, 6, kf, &len, NULL, 0) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
*cnt = (int)(len / sizeof(struct kinfo_file));
return kf;
}
// XXX: This is no longer used as per
// https://github.com/giampaolo/psutil/pull/557#issuecomment-171912820
// Current implementation uses /proc instead.
// Left here just in case.
/*
PyObject *
psutil_proc_exe(PyObject *self, PyObject *args) {
#if __NetBSD_Version__ >= 799000000
pid_t pid;
char pathname[MAXPATHLEN];
int error;
int mib[4];
int ret;
size_t size;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (pid == 0) {
// else returns ENOENT
return Py_BuildValue("s", "");
}
mib[0] = CTL_KERN;
mib[1] = KERN_PROC_ARGS;
mib[2] = pid;
mib[3] = KERN_PROC_PATHNAME;
size = sizeof(pathname);
error = sysctl(mib, 4, NULL, &size, NULL, 0);
if (error == -1) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
error = sysctl(mib, 4, pathname, &size, NULL, 0);
if (error == -1) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
if (size == 0 || strlen(pathname) == 0) {
ret = psutil_pid_exists(pid);
if (ret == -1)
return NULL;
else if (ret == 0)
return NoSuchProcess("");
else
strcpy(pathname, "");
}
return PyUnicode_DecodeFSDefault(pathname);
#else
return Py_BuildValue("s", "");
#endif
}
*/
PyObject *
psutil_proc_num_threads(PyObject *self, PyObject *args) {
// Return number of threads used by process as a Python integer.
long pid;
kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
return Py_BuildValue("l", (long)kp.p_nlwps);
}
PyObject *
psutil_proc_threads(PyObject *self, PyObject *args) {
pid_t pid;
int mib[5];
int i, nlwps;
ssize_t st;
size_t size;
struct kinfo_lwp *kl = NULL;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
if (py_retlist == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "l", &pid))
goto error;
mib[0] = CTL_KERN;
mib[1] = KERN_LWP;
mib[2] = pid;
mib[3] = sizeof(struct kinfo_lwp);
mib[4] = 0;
st = sysctl(mib, 5, NULL, &size, NULL, 0);
if (st == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
if (size == 0) {
NoSuchProcess("");
goto error;
}
mib[4] = size / sizeof(size_t);
kl = malloc(size);
if (kl == NULL) {
PyErr_NoMemory();
goto error;
}
st = sysctl(mib, 5, kl, &size, NULL, 0);
if (st == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
if (size == 0) {
NoSuchProcess("");
goto error;
}
nlwps = (int)(size / sizeof(struct kinfo_lwp));
for (i = 0; i < nlwps; i++) {
py_tuple = Py_BuildValue("idd",
(&kl[i])->l_lid,
PSUTIL_KPT2DOUBLE((&kl[i])->l_rtime),
PSUTIL_KPT2DOUBLE((&kl[i])->l_rtime));
if (py_tuple == NULL)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
}
free(kl);
return py_retlist;
error:
Py_XDECREF(py_tuple);
Py_DECREF(py_retlist);
if (kl != NULL)
free(kl);
return NULL;
}
// ============================================================================
// APIS
// ============================================================================
int
psutil_get_proc_list(kinfo_proc **procList, size_t *procCount) {
// Returns a list of all BSD processes on the system. This routine
// allocates the list and puts it in *procList and a count of the
// number of entries in *procCount. You are responsible for freeing
// this list (use "free" from System framework).
// On success, the function returns 0.
// On error, the function returns a BSD errno value.
kinfo_proc *result;
// Declaring name as const requires us to cast it when passing it to
// sysctl because the prototype doesn't include the const modifier.
char errbuf[_POSIX2_LINE_MAX];
int cnt;
kvm_t *kd;
assert( procList != NULL);
assert(*procList == NULL);
assert(procCount != NULL);
kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
if (kd == NULL) {
PyErr_Format(
PyExc_RuntimeError, "kvm_openfiles() syscall failed: %s", errbuf);
return errno;
}
result = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(kinfo_proc), &cnt);
if (result == NULL) {
PyErr_Format(PyExc_RuntimeError, "kvm_getproc2() syscall failed");
kvm_close(kd);
return errno;
}
*procCount = (size_t)cnt;
size_t mlen = cnt * sizeof(kinfo_proc);
if ((*procList = malloc(mlen)) == NULL) {
PyErr_NoMemory();
kvm_close(kd);
return errno;
}
memcpy(*procList, result, mlen);
assert(*procList != NULL);
kvm_close(kd);
return 0;
}
char *
psutil_get_cmd_args(pid_t pid, size_t *argsize) {
int mib[4];
ssize_t st;
size_t argmax;
size_t size;
char *procargs = NULL;
mib[0] = CTL_KERN;
mib[1] = KERN_ARGMAX;
size = sizeof(argmax);
st = sysctl(mib, 2, &argmax, &size, NULL, 0);
if (st == -1) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
procargs = (char *)malloc(argmax);
if (procargs == NULL) {
PyErr_NoMemory();
return NULL;
}
mib[0] = CTL_KERN;
mib[1] = KERN_PROC_ARGS;
mib[2] = pid;
mib[3] = KERN_PROC_ARGV;
st = sysctl(mib, 4, procargs, &argmax, NULL, 0);
if (st == -1) {
free(procargs);
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
*argsize = argmax;
return procargs;
}
// Return the command line as a python list object.
// XXX - most of the times sysctl() returns a truncated string.
// Also /proc/pid/cmdline behaves the same so it looks like this
// is a kernel bug.
PyObject *
psutil_get_cmdline(pid_t pid) {
char *argstr = NULL;
size_t pos = 0;
size_t argsize = 0;
PyObject *py_arg = NULL;
PyObject *py_retlist = PyList_New(0);
if (py_retlist == NULL)
return NULL;
if (pid == 0)
return py_retlist;
argstr = psutil_get_cmd_args(pid, &argsize);
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
// separator
if (argsize > 0) {
while (pos < argsize) {
py_arg = PyUnicode_DecodeFSDefault(&argstr[pos]);
if (!py_arg)
goto error;
if (PyList_Append(py_retlist, py_arg))
goto error;
Py_DECREF(py_arg);
pos = pos + strlen(&argstr[pos]) + 1;
}
}
free(argstr);
return py_retlist;
error:
Py_XDECREF(py_arg);
Py_DECREF(py_retlist);
if (argstr != NULL)
free(argstr);
return NULL;
}
/*
* Virtual memory stats, taken from:
* https://github.com/satterly/zabbix-stats/blob/master/src/libs/zbxsysinfo/
* netbsd/memory.c
*/
PyObject *
psutil_virtual_mem(PyObject *self, PyObject *args) {
size_t size;
struct uvmexp_sysctl uv;
int mib[] = {CTL_VM, VM_UVMEXP2};
long pagesize = getpagesize();
size = sizeof(uv);
if (sysctl(mib, 2, &uv, &size, NULL, 0) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return Py_BuildValue("KKKKKKKK",
(unsigned long long) uv.npages << uv.pageshift, // total
(unsigned long long) uv.free << uv.pageshift, // free
(unsigned long long) uv.active << uv.pageshift, // active
(unsigned long long) uv.inactive << uv.pageshift, // inactive
(unsigned long long) uv.wired << uv.pageshift, // wired
(unsigned long long) uv.filepages + uv.execpages * pagesize, // cached
// These are determined from /proc/meminfo in Python.
(unsigned long long) 0, // buffers
(unsigned long long) 0 // shared
);
}
PyObject *
psutil_swap_mem(PyObject *self, PyObject *args) {
uint64_t swap_total, swap_free;
struct swapent *swdev;
int nswap, i;
nswap = swapctl(SWAP_NSWAP, 0, 0);
if (nswap == 0) {
// This means there's no swap partition.
return Py_BuildValue("(iiiii)", 0, 0, 0, 0, 0);
}
swdev = calloc(nswap, sizeof(*swdev));
if (swdev == NULL) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
if (swapctl(SWAP_STATS, swdev, nswap) == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
// Total things up.
swap_total = swap_free = 0;
for (i = 0; i < nswap; i++) {
if (swdev[i].se_flags & SWF_ENABLE) {
swap_total += swdev[i].se_nblks * DEV_BSIZE;
swap_free += (swdev[i].se_nblks - swdev[i].se_inuse) * DEV_BSIZE;
}
}
free(swdev);
// Get swap in/out
unsigned int total;
size_t size = sizeof(total);
struct uvmexp_sysctl uv;
int mib[] = {CTL_VM, VM_UVMEXP2};
long pagesize = getpagesize();
size = sizeof(uv);
if (sysctl(mib, 2, &uv, &size, NULL, 0) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
return Py_BuildValue("(LLLll)",
swap_total,
(swap_total - swap_free),
swap_free,
(long) uv.pgswapin * pagesize, // swap in
(long) uv.pgswapout * pagesize); // swap out
error:
free(swdev);
return NULL;
}
PyObject *
psutil_proc_num_fds(PyObject *self, PyObject *args) {
long pid;
int cnt;
struct kinfo_file *freep;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
errno = 0;
freep = kinfo_getfile(pid, &cnt);
if (freep == NULL) {
psutil_raise_for_pid(pid, "kinfo_getfile()");
return NULL;
}
free(freep);
return Py_BuildValue("i", cnt);
}
PyObject *
psutil_per_cpu_times(PyObject *self, PyObject *args) {
// XXX: why static?
int mib[3];
int ncpu;
size_t len;
size_t size;
int i;
PyObject *py_cputime = NULL;
PyObject *py_retlist = PyList_New(0);
if (py_retlist == NULL)
return NULL;
// retrieve the number of cpus
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
len = sizeof(ncpu);
if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
uint64_t cpu_time[CPUSTATES];
for (i = 0; i < ncpu; i++) {
// per-cpu info
mib[0] = CTL_KERN;
mib[1] = KERN_CP_TIME;
mib[2] = i;
size = sizeof(cpu_time);
if (sysctl(mib, 3, &cpu_time, &size, NULL, 0) == -1) {
warn("failed to get kern.cptime2");
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
py_cputime = Py_BuildValue(
"(ddddd)",
(double)cpu_time[CP_USER] / CLOCKS_PER_SEC,
(double)cpu_time[CP_NICE] / CLOCKS_PER_SEC,
(double)cpu_time[CP_SYS] / CLOCKS_PER_SEC,
(double)cpu_time[CP_IDLE] / CLOCKS_PER_SEC,
(double)cpu_time[CP_INTR] / CLOCKS_PER_SEC);
if (!py_cputime)
goto error;
if (PyList_Append(py_retlist, py_cputime))
goto error;
Py_DECREF(py_cputime);
}
return py_retlist;
error:
Py_XDECREF(py_cputime);
Py_DECREF(py_retlist);
return NULL;
}
PyObject *
psutil_disk_io_counters(PyObject *self, PyObject *args) {
int i, dk_ndrive, mib[3];
size_t len;
struct io_sysctl *stats = NULL;
PyObject *py_disk_info = NULL;
PyObject *py_retdict = PyDict_New();
if (py_retdict == NULL)
return NULL;
mib[0] = CTL_HW;
mib[1] = HW_IOSTATS;
mib[2] = sizeof(struct io_sysctl);
len = 0;
if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0) {
warn("can't get HW_IOSTATS");
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
dk_ndrive = (int)(len / sizeof(struct io_sysctl));
stats = malloc(len);
if (stats == NULL) {
PyErr_NoMemory();
goto error;
}
if (sysctl(mib, 3, stats, &len, NULL, 0) < 0 ) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
for (i = 0; i < dk_ndrive; i++) {
py_disk_info = Py_BuildValue(
"(KKKK)",
stats[i].rxfer,
stats[i].wxfer,
stats[i].rbytes,
stats[i].wbytes
);
if (!py_disk_info)
goto error;
if (PyDict_SetItemString(py_retdict, stats[i].name, py_disk_info))
goto error;
Py_DECREF(py_disk_info);
}
free(stats);
return py_retdict;
error:
Py_XDECREF(py_disk_info);
Py_DECREF(py_retdict);
if (stats != NULL)
free(stats);
return NULL;
}
PyObject *
psutil_cpu_stats(PyObject *self, PyObject *args) {
size_t size;
struct uvmexp_sysctl uv;
int uvmexp_mib[] = {CTL_VM, VM_UVMEXP2};
size = sizeof(uv);
if (sysctl(uvmexp_mib, 2, &uv, &size, NULL, 0) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return Py_BuildValue(
"IIIIIII",
uv.swtch, // ctx switches
uv.intrs, // interrupts - XXX always 0, will be determined via /proc
uv.softs, // soft interrupts
uv.syscalls, // syscalls - XXX always 0
uv.traps, // traps
uv.faults, // faults
uv.forks // forks
);
}

View File

@ -1,28 +0,0 @@
/*
* Copyright (c) 2009, Giampaolo Rodola', Landry Breuil.
* All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <Python.h>
typedef struct kinfo_proc2 kinfo_proc;
int psutil_kinfo_proc(pid_t pid, kinfo_proc *proc);
struct kinfo_file * kinfo_getfile(pid_t pid, int* cnt);
int psutil_get_proc_list(kinfo_proc **procList, size_t *procCount);
char *psutil_get_cmd_args(pid_t pid, size_t *argsize);
//
PyObject *psutil_get_cmdline(pid_t pid);
PyObject *psutil_proc_threads(PyObject *self, PyObject *args);
PyObject *psutil_virtual_mem(PyObject *self, PyObject *args);
PyObject *psutil_swap_mem(PyObject *self, PyObject *args);
PyObject *psutil_proc_num_fds(PyObject *self, PyObject *args);
PyObject *psutil_proc_connections(PyObject *self, PyObject *args);
PyObject *psutil_per_cpu_times(PyObject *self, PyObject *args);
PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args);
PyObject* psutil_proc_exe(PyObject* self, PyObject* args);
PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args);
PyObject* psutil_cpu_stats(PyObject* self, PyObject* args);

View File

@ -1,791 +0,0 @@
/*
* Copyright (c) 2009, Giampaolo Rodola', Landry Breuil.
* All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Platform-specific module methods for OpenBSD.
*/
#include <Python.h>
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/mount.h> // for VFS_*
#include <sys/swap.h> // for swap_mem
#include <sys/vmmeter.h> // for vmtotal struct
#include <signal.h>
#include <kvm.h>
// connection stuff
#include <netdb.h> // for NI_MAXHOST
#include <sys/socket.h>
#include <sys/sched.h> // for CPUSTATES & CP_*
#define _KERNEL // for DTYPE_*
#include <sys/file.h>
#undef _KERNEL
#include <sys/disk.h> // struct diskstats
#include <arpa/inet.h> // for inet_ntoa()
#include <err.h> // for warn() & err()
#include "../../_psutil_common.h"
#include "../../_psutil_posix.h"
#define PSUTIL_KPT2DOUBLE(t) (t ## _sec + t ## _usec / 1000000.0)
// #define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0)
// ============================================================================
// Utility functions
// ============================================================================
int
psutil_kinfo_proc(pid_t pid, struct kinfo_proc *proc) {
// Fills a kinfo_proc struct based on process pid.
int ret;
int mib[6];
size_t size = sizeof(struct kinfo_proc);
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = pid;
mib[4] = size;
mib[5] = 1;
ret = sysctl((int*)mib, 6, proc, &size, NULL, 0);
if (ret == -1) {
PyErr_SetFromErrno(PyExc_OSError);
return -1;
}
// sysctl stores 0 in the size if we can't find the process information.
if (size == 0) {
NoSuchProcess("");
return -1;
}
return 0;
}
struct kinfo_file *
kinfo_getfile(long pid, int* cnt) {
// Mimic's FreeBSD kinfo_file call, taking a pid and a ptr to an
// int as arg and returns an array with cnt struct kinfo_file.
int mib[6];
size_t len;
struct kinfo_file* kf;
mib[0] = CTL_KERN;
mib[1] = KERN_FILE;
mib[2] = KERN_FILE_BYPID;
mib[3] = (int) pid;
mib[4] = sizeof(struct kinfo_file);
mib[5] = 0;
/* get the size of what would be returned */
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
if ((kf = malloc(len)) == NULL) {
PyErr_NoMemory();
return NULL;
}
mib[5] = (int)(len / sizeof(struct kinfo_file));
if (sysctl(mib, 6, kf, &len, NULL, 0) < 0) {
free(kf);
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
*cnt = (int)(len / sizeof(struct kinfo_file));
return kf;
}
// ============================================================================
// APIS
// ============================================================================
int
psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) {
// Returns a list of all BSD processes on the system. This routine
// allocates the list and puts it in *procList and a count of the
// number of entries in *procCount. You are responsible for freeing
// this list (use "free" from System framework).
// On success, the function returns 0.
// On error, the function returns a BSD errno value.
struct kinfo_proc *result;
// Declaring name as const requires us to cast it when passing it to
// sysctl because the prototype doesn't include the const modifier.
char errbuf[_POSIX2_LINE_MAX];
int cnt;
kvm_t *kd;
assert(procList != NULL);
assert(*procList == NULL);
assert(procCount != NULL);
kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
if (kd == NULL) {
return errno;
}
result = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cnt);
if (result == NULL) {
kvm_close(kd);
err(1, NULL);
return errno;
}
*procCount = (size_t)cnt;
size_t mlen = cnt * sizeof(struct kinfo_proc);
if ((*procList = malloc(mlen)) == NULL) {
kvm_close(kd);
err(1, NULL);
return errno;
}
memcpy(*procList, result, mlen);
assert(*procList != NULL);
kvm_close(kd);
return 0;
}
char **
_psutil_get_argv(long pid) {
static char **argv;
int argv_mib[] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV};
size_t argv_size = 128;
// Loop and reallocate until we have enough space to fit argv.
for (;; argv_size *= 2) {
if (argv_size >= 8192) {
PyErr_SetString(PyExc_RuntimeError,
"can't allocate enough space for KERN_PROC_ARGV");
return NULL;
}
if ((argv = realloc(argv, argv_size)) == NULL)
continue;
if (sysctl(argv_mib, 4, argv, &argv_size, NULL, 0) == 0)
return argv;
if (errno == ENOMEM)
continue;
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
}
// returns the command line as a python list object
PyObject *
psutil_get_cmdline(long pid) {
static char **argv;
char **p;
PyObject *py_arg = NULL;
PyObject *py_retlist = Py_BuildValue("[]");
if (!py_retlist)
return NULL;
if (pid < 0)
return py_retlist;
if ((argv = _psutil_get_argv(pid)) == NULL)
goto error;
for (p = argv; *p != NULL; p++) {
py_arg = PyUnicode_DecodeFSDefault(*p);
if (!py_arg)
goto error;
if (PyList_Append(py_retlist, py_arg))
goto error;
Py_DECREF(py_arg);
}
return py_retlist;
error:
Py_XDECREF(py_arg);
Py_DECREF(py_retlist);
return NULL;
}
PyObject *
psutil_proc_threads(PyObject *self, PyObject *args) {
// OpenBSD reference:
// https://github.com/janmojzis/pstree/blob/master/proc_kvm.c
// Note: this requires root access, else it will fail trying
// to access /dev/kmem.
long pid;
kvm_t *kd = NULL;
int nentries, i;
char errbuf[4096];
struct kinfo_proc *kp;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
if (py_retlist == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "l", &pid))
goto error;
kd = kvm_openfiles(0, 0, 0, O_RDONLY, errbuf);
if (! kd) {
if (strstr(errbuf, "Permission denied") != NULL)
AccessDenied("");
else
PyErr_Format(PyExc_RuntimeError, "kvm_openfiles() syscall failed");
goto error;
}
kp = kvm_getprocs(
kd, KERN_PROC_PID | KERN_PROC_SHOW_THREADS | KERN_PROC_KTHREAD, pid,
sizeof(*kp), &nentries);
if (! kp) {
if (strstr(errbuf, "Permission denied") != NULL)
AccessDenied("");
else
PyErr_Format(PyExc_RuntimeError, "kvm_getprocs() syscall failed");
goto error;
}
for (i = 0; i < nentries; i++) {
if (kp[i].p_tid < 0)
continue;
if (kp[i].p_pid == pid) {
py_tuple = Py_BuildValue(
"Idd",
kp[i].p_tid,
PSUTIL_KPT2DOUBLE(kp[i].p_uutime),
PSUTIL_KPT2DOUBLE(kp[i].p_ustime));
if (py_tuple == NULL)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
}
}
kvm_close(kd);
return py_retlist;
error:
Py_XDECREF(py_tuple);
Py_DECREF(py_retlist);
if (kd != NULL)
kvm_close(kd);
return NULL;
}
PyObject *
psutil_virtual_mem(PyObject *self, PyObject *args) {
int64_t total_physmem;
int uvmexp_mib[] = {CTL_VM, VM_UVMEXP};
int bcstats_mib[] = {CTL_VFS, VFS_GENERIC, VFS_BCACHESTAT};
int physmem_mib[] = {CTL_HW, HW_PHYSMEM64};
int vmmeter_mib[] = {CTL_VM, VM_METER};
size_t size;
struct uvmexp uvmexp;
struct bcachestats bcstats;
struct vmtotal vmdata;
long pagesize = getpagesize();
size = sizeof(total_physmem);
if (sysctl(physmem_mib, 2, &total_physmem, &size, NULL, 0) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
size = sizeof(uvmexp);
if (sysctl(uvmexp_mib, 2, &uvmexp, &size, NULL, 0) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
size = sizeof(bcstats);
if (sysctl(bcstats_mib, 3, &bcstats, &size, NULL, 0) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
size = sizeof(vmdata);
if (sysctl(vmmeter_mib, 2, &vmdata, &size, NULL, 0) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return Py_BuildValue("KKKKKKKK",
// Note: many programs calculate total memory as
// "uvmexp.npages * pagesize" but this is incorrect and does not
// match "sysctl | grep hw.physmem".
(unsigned long long) total_physmem,
(unsigned long long) uvmexp.free * pagesize,
(unsigned long long) uvmexp.active * pagesize,
(unsigned long long) uvmexp.inactive * pagesize,
(unsigned long long) uvmexp.wired * pagesize,
// this is how "top" determines it
(unsigned long long) bcstats.numbufpages * pagesize, // cached
(unsigned long long) 0, // buffers
(unsigned long long) vmdata.t_vmshr + vmdata.t_rmshr // shared
);
}
PyObject *
psutil_swap_mem(PyObject *self, PyObject *args) {
uint64_t swap_total, swap_free;
struct swapent *swdev;
int nswap, i;
if ((nswap = swapctl(SWAP_NSWAP, 0, 0)) == 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
if ((swdev = calloc(nswap, sizeof(*swdev))) == NULL) {
PyErr_NoMemory();
return NULL;
}
if (swapctl(SWAP_STATS, swdev, nswap) == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
// Total things up.
swap_total = swap_free = 0;
for (i = 0; i < nswap; i++) {
if (swdev[i].se_flags & SWF_ENABLE) {
swap_free += (swdev[i].se_nblks - swdev[i].se_inuse);
swap_total += swdev[i].se_nblks;
}
}
free(swdev);
return Py_BuildValue("(LLLII)",
swap_total * DEV_BSIZE,
(swap_total - swap_free) * DEV_BSIZE,
swap_free * DEV_BSIZE,
// swap in / swap out is not supported as the
// swapent struct does not provide any info
// about it.
0, 0);
error:
free(swdev);
return NULL;
}
PyObject *
psutil_proc_num_fds(PyObject *self, PyObject *args) {
long pid;
int cnt;
struct kinfo_file *freep;
struct kinfo_proc kipp;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kipp) == -1)
return NULL;
errno = 0;
freep = kinfo_getfile(pid, &cnt);
if (freep == NULL) {
psutil_raise_for_pid(pid, "kinfo_getfile()");
return NULL;
}
free(freep);
return Py_BuildValue("i", cnt);
}
PyObject *
psutil_proc_cwd(PyObject *self, PyObject *args) {
// Reference:
// https://github.com/openbsd/src/blob/
// 588f7f8c69786211f2d16865c552afb91b1c7cba/bin/ps/print.c#L191
long pid;
struct kinfo_proc kp;
char path[MAXPATHLEN];
size_t pathlen = sizeof path;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
int name[] = { CTL_KERN, KERN_PROC_CWD, pid };
if (sysctl(name, 3, path, &pathlen, NULL, 0) != 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return PyUnicode_DecodeFSDefault(path);
}
// see sys/kern/kern_sysctl.c lines 1100 and
// usr.bin/fstat/fstat.c print_inet_details()
static char *
psutil_convert_ipv4(int family, uint32_t addr[4]) {
struct in_addr a;
memcpy(&a, addr, sizeof(a));
return inet_ntoa(a);
}
static char *
psutil_inet6_addrstr(struct in6_addr *p)
{
struct sockaddr_in6 sin6;
static char hbuf[NI_MAXHOST];
const int niflags = NI_NUMERICHOST;
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(struct sockaddr_in6);
sin6.sin6_addr = *p;
if (IN6_IS_ADDR_LINKLOCAL(p) &&
*(u_int16_t *)&sin6.sin6_addr.s6_addr[2] != 0) {
sin6.sin6_scope_id =
ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
sin6.sin6_addr.s6_addr[2] = sin6.sin6_addr.s6_addr[3] = 0;
}
if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
hbuf, sizeof(hbuf), NULL, 0, niflags))
return "invalid";
return hbuf;
}
/*
* List process connections.
* Note: there is no net_connections() on OpenBSD. The Python
* implementation will iterate over all processes and use this
* function.
* Note: local and remote paths cannot be determined for UNIX sockets.
*/
PyObject *
psutil_proc_connections(PyObject *self, PyObject *args) {
long pid;
int i;
int cnt;
struct kinfo_file *freep = NULL;
struct kinfo_file *kif;
char *tcplist = NULL;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
PyObject *py_laddr = NULL;
PyObject *py_raddr = NULL;
PyObject *py_af_filter = NULL;
PyObject *py_type_filter = NULL;
PyObject *py_family = NULL;
PyObject *_type = NULL;
if (py_retlist == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "lOO", &pid, &py_af_filter, &py_type_filter))
goto error;
if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) {
PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence");
goto error;
}
errno = 0;
freep = kinfo_getfile(pid, &cnt);
if (freep == NULL) {
psutil_raise_for_pid(pid, "kinfo_getfile()");
goto error;
}
for (i = 0; i < cnt; i++) {
int state;
int lport;
int rport;
char addrbuf[NI_MAXHOST + 2];
int inseq;
struct in6_addr laddr6;
py_tuple = NULL;
py_laddr = NULL;
py_raddr = NULL;
kif = &freep[i];
if (kif->f_type == DTYPE_SOCKET) {
// apply filters
py_family = PyLong_FromLong((long)kif->so_family);
inseq = PySequence_Contains(py_af_filter, py_family);
Py_DECREF(py_family);
if (inseq == 0)
continue;
_type = PyLong_FromLong((long)kif->so_type);
inseq = PySequence_Contains(py_type_filter, _type);
Py_DECREF(_type);
if (inseq == 0)
continue;
// IPv4 / IPv6 socket
if ((kif->so_family == AF_INET) || (kif->so_family == AF_INET6)) {
// fill status
if (kif->so_type == SOCK_STREAM)
state = kif->t_state;
else
state = PSUTIL_CONN_NONE;
// ports
lport = ntohs(kif->inp_lport);
rport = ntohs(kif->inp_fport);
// local address, IPv4
if (kif->so_family == AF_INET) {
py_laddr = Py_BuildValue(
"(si)",
psutil_convert_ipv4(kif->so_family, kif->inp_laddru),
lport);
if (!py_laddr)
goto error;
}
else {
// local address, IPv6
memcpy(&laddr6, kif->inp_laddru, sizeof(laddr6));
snprintf(addrbuf, sizeof(addrbuf), "%s",
psutil_inet6_addrstr(&laddr6));
py_laddr = Py_BuildValue("(si)", addrbuf, lport);
if (!py_laddr)
goto error;
}
if (rport != 0) {
// remote address, IPv4
if (kif->so_family == AF_INET) {
py_raddr = Py_BuildValue(
"(si)",
psutil_convert_ipv4(
kif->so_family, kif->inp_faddru),
rport);
}
else {
// remote address, IPv6
memcpy(&laddr6, kif->inp_faddru, sizeof(laddr6));
snprintf(addrbuf, sizeof(addrbuf), "%s",
psutil_inet6_addrstr(&laddr6));
py_raddr = Py_BuildValue("(si)", addrbuf, rport);
if (!py_raddr)
goto error;
}
}
else {
py_raddr = Py_BuildValue("()");
}
if (!py_raddr)
goto error;
py_tuple = Py_BuildValue(
"(iiiNNi)",
kif->fd_fd,
kif->so_family,
kif->so_type,
py_laddr,
py_raddr,
state);
if (!py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
}
// UNIX socket.
// XXX: local addr is supposed to be in "unp_path" but it
// always empty; also "fstat" command is not able to show
// UNIX socket paths.
else if (kif->so_family == AF_UNIX) {
py_tuple = Py_BuildValue(
"(iiissi)",
kif->fd_fd,
kif->so_family,
kif->so_type,
"", // laddr (kif->unp_path is empty)
"", // raddr
PSUTIL_CONN_NONE);
if (!py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
Py_INCREF(Py_None);
}
}
}
free(freep);
free(tcplist);
return py_retlist;
error:
Py_XDECREF(py_tuple);
Py_XDECREF(py_laddr);
Py_XDECREF(py_raddr);
Py_DECREF(py_retlist);
if (freep != NULL)
free(freep);
if (tcplist != NULL)
free(tcplist);
return NULL;
}
PyObject *
psutil_per_cpu_times(PyObject *self, PyObject *args) {
int mib[3];
int ncpu;
size_t len;
size_t size;
int i;
PyObject *py_retlist = PyList_New(0);
PyObject *py_cputime = NULL;
if (py_retlist == NULL)
return NULL;
// retrieve the number of cpus
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
len = sizeof(ncpu);
if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
uint64_t cpu_time[CPUSTATES];
for (i = 0; i < ncpu; i++) {
// per-cpu info
mib[0] = CTL_KERN;
mib[1] = KERN_CPTIME2;
mib[2] = i;
size = sizeof(cpu_time);
if (sysctl(mib, 3, &cpu_time, &size, NULL, 0) == -1) {
warn("failed to get kern.cptime2");
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
py_cputime = Py_BuildValue(
"(ddddd)",
(double)cpu_time[CP_USER] / CLOCKS_PER_SEC,
(double)cpu_time[CP_NICE] / CLOCKS_PER_SEC,
(double)cpu_time[CP_SYS] / CLOCKS_PER_SEC,
(double)cpu_time[CP_IDLE] / CLOCKS_PER_SEC,
(double)cpu_time[CP_INTR] / CLOCKS_PER_SEC);
if (!py_cputime)
goto error;
if (PyList_Append(py_retlist, py_cputime))
goto error;
Py_DECREF(py_cputime);
}
return py_retlist;
error:
Py_XDECREF(py_cputime);
Py_DECREF(py_retlist);
return NULL;
}
PyObject *
psutil_disk_io_counters(PyObject *self, PyObject *args) {
int i, dk_ndrive, mib[3];
size_t len;
struct diskstats *stats = NULL;
PyObject *py_retdict = PyDict_New();
PyObject *py_disk_info = NULL;
if (py_retdict == NULL)
return NULL;
mib[0] = CTL_HW;
mib[1] = HW_DISKSTATS;
len = 0;
if (sysctl(mib, 2, NULL, &len, NULL, 0) < 0) {
warn("can't get hw.diskstats size");
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
dk_ndrive = (int)(len / sizeof(struct diskstats));
stats = malloc(len);
if (stats == NULL) {
warn("can't malloc");
PyErr_NoMemory();
goto error;
}
if (sysctl(mib, 2, stats, &len, NULL, 0) < 0 ) {
warn("could not read hw.diskstats");
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
for (i = 0; i < dk_ndrive; i++) {
py_disk_info = Py_BuildValue(
"(KKKK)",
stats[i].ds_rxfer, // num reads
stats[i].ds_wxfer, // num writes
stats[i].ds_rbytes, // read bytes
stats[i].ds_wbytes // write bytes
);
if (!py_disk_info)
goto error;
if (PyDict_SetItemString(py_retdict, stats[i].ds_name, py_disk_info))
goto error;
Py_DECREF(py_disk_info);
}
free(stats);
return py_retdict;
error:
Py_XDECREF(py_disk_info);
Py_DECREF(py_retdict);
if (stats != NULL)
free(stats);
return NULL;
}
PyObject *
psutil_cpu_stats(PyObject *self, PyObject *args) {
size_t size;
struct uvmexp uv;
int uvmexp_mib[] = {CTL_VM, VM_UVMEXP};
size = sizeof(uv);
if (sysctl(uvmexp_mib, 2, &uv, &size, NULL, 0) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return Py_BuildValue(
"IIIIIII",
uv.swtch, // ctx switches
uv.intrs, // interrupts - XXX always 0, will be determined via /proc
uv.softs, // soft interrupts
uv.syscalls, // syscalls - XXX always 0
uv.traps, // traps
uv.faults, // faults
uv.forks // forks
);
}

View File

@ -1,27 +0,0 @@
/*
* Copyright (c) 2009, Giampaolo Rodola', Landry Breuil.
* All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <Python.h>
typedef struct kinfo_proc kinfo_proc;
int psutil_kinfo_proc(pid_t pid, struct kinfo_proc *proc);
struct kinfo_file * kinfo_getfile(long pid, int* cnt);
int psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount);
char **_psutil_get_argv(long pid);
PyObject * psutil_get_cmdline(long pid);
//
PyObject *psutil_proc_threads(PyObject *self, PyObject *args);
PyObject *psutil_virtual_mem(PyObject *self, PyObject *args);
PyObject *psutil_swap_mem(PyObject *self, PyObject *args);
PyObject *psutil_proc_num_fds(PyObject *self, PyObject *args);
PyObject *psutil_proc_cwd(PyObject *self, PyObject *args);
PyObject *psutil_proc_connections(PyObject *self, PyObject *args);
PyObject *psutil_per_cpu_times(PyObject *self, PyObject *args);
PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args);
PyObject* psutil_cpu_stats(PyObject* self, PyObject* args);

View File

@ -21,7 +21,28 @@
#include "process_info.h"
#include "../../_psutil_common.h"
#include "../../_psutil_posix.h"
/*
* Return 1 if PID exists in the current process list, else 0.
*/
int
psutil_pid_exists(long pid)
{
int kill_ret;
// save some time if it's an invalid PID
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))
return 1;
// otherwise return 0 for PID not found
return 0;
}
/*
* Returns a list of all BSD processes on the system. This routine
@ -32,12 +53,14 @@
* On error, the function returns a BSD errno value.
*/
int
psutil_get_proc_list(kinfo_proc **procList, size_t *procCount) {
int mib3[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
size_t size, size2;
void *ptr;
int err;
int lim = 8; // some limit
psutil_get_proc_list(kinfo_proc **procList, size_t *procCount)
{
// Declaring mib as const requires use of a cast since the
// sysctl prototype doesn't include the const modifier.
static const int mib3[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
size_t size, size2;
void *ptr;
int err, lim = 8; // some limit
assert( procList != NULL);
assert(*procList == NULL);
@ -93,7 +116,8 @@ psutil_get_proc_list(kinfo_proc **procList, size_t *procCount) {
// Read the maximum argument size for processes
int
psutil_get_argmax() {
psutil_get_argmax()
{
int argmax;
int mib[] = { CTL_KERN, KERN_ARGMAX };
size_t size = sizeof(argmax);
@ -106,18 +130,18 @@ psutil_get_argmax() {
// return process args as a python list
PyObject *
psutil_get_cmdline(long pid) {
psutil_get_arg_list(long pid)
{
int mib[3];
int nargs;
size_t len;
int len;
char *procargs = NULL;
char *arg_ptr;
char *arg_end;
char *curr_arg;
size_t argmax;
PyObject *py_arg = NULL;
PyObject *py_retlist = NULL;
PyObject *arg = NULL;
PyObject *arglist = NULL;
// special case for PID 0 (kernel_task) where cmdline cannot be fetched
if (pid == 0)
@ -139,14 +163,15 @@ psutil_get_cmdline(long pid) {
// read argument space
mib[0] = CTL_KERN;
mib[1] = KERN_PROCARGS2;
mib[2] = (pid_t)pid;
mib[2] = pid;
if (sysctl(mib, 3, procargs, &argmax, NULL, 0) < 0) {
// In case of zombie process we'll get EINVAL. We translate it
// to NSP and _psosx.py will translate it to ZP.
if ((errno == EINVAL) && (psutil_pid_exists(pid)))
NoSuchProcess("");
else
PyErr_SetFromErrno(PyExc_OSError);
if (EINVAL == errno) {
// EINVAL == access denied OR nonexistent PID
if (psutil_pid_exists(pid))
AccessDenied();
else
NoSuchProcess();
}
goto error;
}
@ -171,17 +196,17 @@ psutil_get_cmdline(long pid) {
// iterate through arguments
curr_arg = arg_ptr;
py_retlist = Py_BuildValue("[]");
if (!py_retlist)
arglist = Py_BuildValue("[]");
if (!arglist)
goto error;
while (arg_ptr < arg_end && nargs > 0) {
if (*arg_ptr++ == '\0') {
py_arg = PyUnicode_DecodeFSDefault(curr_arg);
if (! py_arg)
arg = Py_BuildValue("s", curr_arg);
if (!arg)
goto error;
if (PyList_Append(py_retlist, py_arg))
if (PyList_Append(arglist, arg))
goto error;
Py_DECREF(py_arg);
Py_DECREF(arg);
// iterate to next arg and decrement # of args
curr_arg = arg_ptr;
nargs--;
@ -189,142 +214,26 @@ psutil_get_cmdline(long pid) {
}
free(procargs);
return py_retlist;
return arglist;
error:
Py_XDECREF(py_arg);
Py_XDECREF(py_retlist);
Py_XDECREF(arg);
Py_XDECREF(arglist);
if (procargs != NULL)
free(procargs);
return NULL;
}
// return process environment as a python string
PyObject *
psutil_get_environ(long pid) {
int mib[3];
int nargs;
char *procargs = NULL;
char *procenv = NULL;
char *arg_ptr;
char *arg_end;
char *env_start;
size_t argmax;
PyObject *py_ret = NULL;
// special case for PID 0 (kernel_task) where cmdline cannot be fetched
if (pid == 0)
goto empty;
// read argmax and allocate memory for argument space.
argmax = psutil_get_argmax();
if (! argmax) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
procargs = (char *)malloc(argmax);
if (NULL == procargs) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
// read argument space
mib[0] = CTL_KERN;
mib[1] = KERN_PROCARGS2;
mib[2] = (pid_t)pid;
if (sysctl(mib, 3, procargs, &argmax, NULL, 0) < 0) {
// In case of zombie process we'll get EINVAL. We translate it
// to NSP and _psosx.py will translate it to ZP.
if ((errno == EINVAL) && (psutil_pid_exists(pid)))
NoSuchProcess("");
else
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
arg_end = &procargs[argmax];
// copy the number of arguments to nargs
memcpy(&nargs, procargs, sizeof(nargs));
// skip executable path
arg_ptr = procargs + sizeof(nargs);
arg_ptr = memchr(arg_ptr, '\0', arg_end - arg_ptr);
if (arg_ptr == NULL || arg_ptr == arg_end)
goto empty;
// skip ahead to the first argument
for (; arg_ptr < arg_end; arg_ptr++) {
if (*arg_ptr != '\0')
break;
}
// iterate through arguments
while (arg_ptr < arg_end && nargs > 0) {
if (*arg_ptr++ == '\0')
nargs--;
}
// build an environment variable block
env_start = arg_ptr;
procenv = calloc(1, arg_end - arg_ptr);
if (procenv == NULL) {
PyErr_NoMemory();
goto error;
}
while (*arg_ptr != '\0' && arg_ptr < arg_end) {
char *s = memchr(arg_ptr + 1, '\0', arg_end - arg_ptr);
if (s == NULL)
break;
memcpy(procenv + (arg_ptr - env_start), arg_ptr, s - arg_ptr);
arg_ptr = s + 1;
}
py_ret = PyUnicode_DecodeFSDefaultAndSize(
procenv, arg_ptr - env_start + 1);
if (!py_ret) {
// XXX: don't want to free() this as per:
// https://github.com/giampaolo/psutil/issues/926
// It sucks but not sure what else to do.
procargs = NULL;
goto error;
}
free(procargs);
free(procenv);
return py_ret;
empty:
if (procargs != NULL)
free(procargs);
return Py_BuildValue("s", "");
error:
Py_XDECREF(py_ret);
if (procargs != NULL)
free(procargs);
if (procenv != NULL)
free(procargs);
return NULL;
}
int
psutil_get_kinfo_proc(long pid, struct kinfo_proc *kp) {
psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp)
{
int mib[4];
size_t len;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = (pid_t)pid;
mib[3] = pid;
// fetch the info with sysctl()
len = sizeof(struct kinfo_proc);
@ -338,7 +247,7 @@ psutil_get_kinfo_proc(long pid, struct kinfo_proc *kp) {
// sysctl succeeds but len is zero, happens when process has gone away
if (len == 0) {
NoSuchProcess("");
NoSuchProcess();
return -1;
}
return 0;
@ -346,16 +255,27 @@ psutil_get_kinfo_proc(long pid, struct kinfo_proc *kp) {
/*
* A wrapper around proc_pidinfo().
* Returns 0 on failure (and Python exception gets already set).
* A thin wrapper around proc_pidinfo()
*/
int
psutil_proc_pidinfo(long pid, int flavor, uint64_t arg, void *pti, int size) {
errno = 0;
int ret = proc_pidinfo((int)pid, flavor, arg, pti, size);
if ((ret <= 0) || ((unsigned long)ret < sizeof(pti))) {
psutil_raise_for_pid(pid, "proc_pidinfo()");
psutil_proc_pidinfo(long pid, int flavor, void *pti, int size)
{
int ret = proc_pidinfo((int)pid, flavor, 0, pti, size);
if (ret == 0) {
if (! psutil_pid_exists(pid)) {
NoSuchProcess();
return 0;
}
else {
AccessDenied();
return 0;
}
}
else if (ret != size) {
AccessDenied();
return 0;
}
return ret;
else {
return 1;
}
}

View File

@ -9,9 +9,8 @@
typedef struct kinfo_proc kinfo_proc;
int psutil_get_argmax(void);
int psutil_get_kinfo_proc(long pid, struct kinfo_proc *kp);
int psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp);
int psutil_get_proc_list(kinfo_proc **procList, size_t *procCount);
int psutil_proc_pidinfo(
long pid, int flavor, uint64_t arg, void *pti, int size);
PyObject* psutil_get_cmdline(long pid);
PyObject* psutil_get_environ(long pid);
int psutil_pid_exists(long pid);
int psutil_proc_pidinfo(long pid, int flavor, void *pti, int size);
PyObject* psutil_get_arg_list(long pid);

View File

@ -1,405 +0,0 @@
/*
* Copyright (c) 2009, Giampaolo Rodola', Oleksii Shevchuk.
* All rights reserved. Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*
* Functions specific for Process.environ().
*/
#define NEW_MIB_COMPLIANT 1
#define _STRUCTURED_PROC 1
#include <Python.h>
#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
# undef _FILE_OFFSET_BITS
# undef _LARGEFILE64_SOURCE
#endif
#include <sys/types.h>
#include <sys/procfs.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "environ.h"
#define STRING_SEARCH_BUF_SIZE 512
/*
* Open address space of specified process and return file descriptor.
* @param pid a pid of process.
* @param procfs_path a path to mounted procfs filesystem.
* @return file descriptor or -1 in case of error.
*/
static int
open_address_space(pid_t pid, const char *procfs_path) {
int fd;
char proc_path[PATH_MAX];
snprintf(proc_path, PATH_MAX, "%s/%i/as", procfs_path, pid);
fd = open(proc_path, O_RDONLY);
if (fd < 0)
PyErr_SetFromErrno(PyExc_OSError);
return fd;
}
/*
* Read chunk of data by offset to specified buffer of the same size.
* @param fd a file descriptor.
* @param offset an required offset in file.
* @param buf a buffer where to store result.
* @param buf_size a size of buffer where data will be stored.
* @return amount of bytes stored to the buffer or -1 in case of
* error.
*/
static int
read_offt(int fd, off_t offset, char *buf, size_t buf_size) {
size_t to_read = buf_size;
size_t stored = 0;
int r;
while (to_read) {
r = pread(fd, buf + stored, to_read, offset + stored);
if (r < 0)
goto error;
else if (r == 0)
break;
to_read -= r;
stored += r;
}
return stored;
error:
PyErr_SetFromErrno(PyExc_OSError);
return -1;
}
/*
* Read null-terminated string from file descriptor starting from
* specified offset.
* @param fd a file descriptor of opened address space.
* @param offset an offset in specified file descriptor.
* @return allocated null-terminated string or NULL in case of error.
*/
static char *
read_cstring_offt(int fd, off_t offset) {
int r;
int i = 0;
off_t end = offset;
size_t len;
char buf[STRING_SEARCH_BUF_SIZE];
char *result = NULL;
if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
// Search end of string
for (;;) {
r = read(fd, buf, sizeof(buf));
if (r == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
else if (r == 0) {
break;
}
else {
for (i=0; i<r; i++)
if (! buf[i])
goto found;
}
end += r;
}
found:
len = end + i - offset;
result = malloc(len+1);
if (! result) {
PyErr_NoMemory();
goto error;
}
if (len) {
if (read_offt(fd, offset, result, len) < 0) {
goto error;
}
}
result[len] = '\0';
return result;
error:
if (result)
free(result);
return NULL;
}
/*
* Read block of addresses by offset, dereference them one by one
* and create an array of null terminated C strings from them.
* @param fd a file descriptor of address space of interesting process.
* @param offset an offset of address block in address space.
* @param ptr_size a size of pointer. Only 4 or 8 are valid values.
* @param count amount of pointers in block.
* @return allocated array of strings dereferenced and read by offset.
* Number of elements in array are count. In case of error function
* returns NULL.
*/
static char **
read_cstrings_block(int fd, off_t offset, size_t ptr_size, size_t count) {
char **result = NULL;
char *pblock = NULL;
size_t pblock_size;
int i;
assert(ptr_size == 4 || ptr_size == 8);
if (!count)
goto error;
pblock_size = ptr_size * count;
pblock = malloc(pblock_size);
if (! pblock) {
PyErr_NoMemory();
goto error;
}
if (read_offt(fd, offset, pblock, pblock_size) != pblock_size)
goto error;
result = (char **) calloc(count, sizeof(char *));
if (! result) {
PyErr_NoMemory();
goto error;
}
for (i=0; i<count; i++) {
result[i] = read_cstring_offt(
fd, (ptr_size == 4?
((uint32_t *) pblock)[i]:
((uint64_t *) pblock)[i]));
if (!result[i])
goto error;
}
free(pblock);
return result;
error:
if (result)
psutil_free_cstrings_array(result, i);
if (pblock)
free(pblock);
return NULL;
}
/*
* Check that caller process can extract proper values from psinfo_t
* structure.
* @param info a pointer to process info (psinfo_t) structure of the
* interesting process.
* @return 1 in case if caller process can extract proper values from
* psinfo_t structure, or 0 otherwise.
*/
static inline int
is_ptr_dereference_possible(psinfo_t info) {
#if !defined(_LP64)
return info.pr_dmodel == PR_MODEL_ILP32;
#else
return 1;
#endif
}
/*
* Return pointer size according to psinfo_t structure
* @param info a ponter to process info (psinfo_t) structure of the
* interesting process.
* @return pointer size (4 or 8).
*/
static inline int
ptr_size_by_psinfo(psinfo_t info) {
return info.pr_dmodel == PR_MODEL_ILP32? 4 : 8;
}
/*
* Count amount of pointers in a block which ends with NULL.
* @param fd a discriptor of /proc/PID/as special file.
* @param offt an offset of block of pointers at the file.
* @param ptr_size a pointer size (allowed values: {4, 8}).
* @return amount of non-NULL pointers or -1 in case of error.
*/
static int
search_pointers_vector_size_offt(int fd, off_t offt, size_t ptr_size) {
int count = 0;
int r;
char buf[8];
static const char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
assert(ptr_size == 4 || ptr_size == 8);
if (lseek(fd, offt, SEEK_SET) == (off_t)-1)
goto error;
for (;; count ++) {
r = read(fd, buf, ptr_size);
if (r < 0)
goto error;
if (r == 0)
break;
if (r != ptr_size) {
PyErr_SetString(
PyExc_RuntimeError, "pointer block is truncated");
return -1;
}
if (! memcmp(buf, zeros, ptr_size))
break;
}
return count;
error:
PyErr_SetFromErrno(PyExc_OSError);
return -1;
}
/*
* Derefence and read array of strings by psinfo_t.pr_argv pointer from
* remote process.
* @param info a ponter to process info (psinfo_t) structure of the
* interesting process
* @param procfs_path a cstring with path to mounted procfs filesystem.
* @param count a pointer to variable where to store amount of elements in
* returned array. In case of error value of variable will not be
changed.
* @return allocated array of cstrings or NULL in case of error.
*/
char **
psutil_read_raw_args(psinfo_t info, const char *procfs_path, size_t *count) {
int as;
char **result;
if (! is_ptr_dereference_possible(info)) {
PyErr_SetString(
PyExc_NotImplementedError,
"can't get env of a 64 bit process from a 32 bit process");
return NULL;
}
if (! (info.pr_argv && info.pr_argc)) {
PyErr_SetString(
PyExc_RuntimeError, "process doesn't have arguments block");
return NULL;
}
as = open_address_space(info.pr_pid, procfs_path);
if (as < 0)
return NULL;
result = read_cstrings_block(
as, info.pr_argv, ptr_size_by_psinfo(info), info.pr_argc
);
if (result && count)
*count = info.pr_argc;
close(as);
return result;
}
/*
* Dereference and read array of strings by psinfo_t.pr_envp pointer
* from remote process.
* @param info a ponter to process info (psinfo_t) structure of the
* interesting process.
* @param procfs_path a cstring with path to mounted procfs filesystem.
* @param count a pointer to variable where to store amount of elements in
* returned array. In case of error value of variable will not be
* changed. To detect special case (described later) variable should be
* initialized by -1 or other negative value.
* @return allocated array of cstrings or NULL in case of error.
* Special case: count set to 0, return NULL.
* Special case means there is no error acquired, but no data
* retrieved.
* Special case exists because the nature of the process. From the
* beginning it's not clean how many pointers in envp array. Also
* situation when environment is empty is common for kernel processes.
*/
char **
psutil_read_raw_env(psinfo_t info, const char *procfs_path, ssize_t *count) {
int as;
int env_count;
int ptr_size;
char **result = NULL;
if (! is_ptr_dereference_possible(info)) {
PyErr_SetString(
PyExc_NotImplementedError,
"can't get env of a 64 bit process from a 32 bit process");
return NULL;
}
as = open_address_space(info.pr_pid, procfs_path);
if (as < 0)
return NULL;
ptr_size = ptr_size_by_psinfo(info);
env_count = search_pointers_vector_size_offt(
as, info.pr_envp, ptr_size);
if (env_count >= 0 && count)
*count = env_count;
if (env_count > 0)
result = read_cstrings_block(
as, info.pr_envp, ptr_size, env_count);
close(as);
return result;
}
/*
* Free array of cstrings.
* @param array an array of cstrings returned by psutil_read_raw_env,
* psutil_read_raw_args or any other function.
* @param count a count of strings in the passed array
*/
void
psutil_free_cstrings_array(char **array, size_t count) {
int i;
if (!array)
return;
for (i=0; i<count; i++) {
if (array[i]) {
free(array[i]);
}
}
free(array);
}

View File

@ -1,19 +0,0 @@
/*
* Copyright (c) 2009, Giampaolo Rodola', Oleksii Shevchuk.
* All rights reserved. Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
#ifndef PROCESS_AS_UTILS_H
#define PROCESS_AS_UTILS_H
char **
psutil_read_raw_args(psinfo_t info, const char *procfs_path, size_t *count);
char **
psutil_read_raw_env(psinfo_t info, const char *procfs_path, ssize_t *count);
void
psutil_free_cstrings_array(char **array, size_t count);
#endif // PROCESS_AS_UTILS_H

View File

@ -1,124 +0,0 @@
/* Refrences:
* https://lists.samba.org/archive/samba-technical/2009-February/063079.html
* http://stackoverflow.com/questions/4139405/#4139811
* https://github.com/steve-o/openpgm/blob/master/openpgm/pgm/getifaddrs.c
*/
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include "ifaddrs.h"
#define MAX(x,y) ((x)>(y)?(x):(y))
#define SIZE(p) MAX((p).ss_len,sizeof(p))
static struct sockaddr *
sa_dup (struct sockaddr_storage *sa1)
{
struct sockaddr *sa2;
size_t sz = sizeof(struct sockaddr_storage);
sa2 = (struct sockaddr *) calloc(1,sz);
memcpy(sa2,sa1,sz);
return(sa2);
}
void freeifaddrs (struct ifaddrs *ifp)
{
if (NULL == ifp) return;
free(ifp->ifa_name);
free(ifp->ifa_addr);
free(ifp->ifa_netmask);
free(ifp->ifa_dstaddr);
freeifaddrs(ifp->ifa_next);
free(ifp);
}
int getifaddrs (struct ifaddrs **ifap)
{
int sd = -1;
char *ccp, *ecp;
struct lifconf ifc;
struct lifreq *ifr;
struct lifnum lifn;
struct ifaddrs *cifa = NULL; /* current */
struct ifaddrs *pifa = NULL; /* previous */
const size_t IFREQSZ = sizeof(struct lifreq);
sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd < 0)
goto error;
ifc.lifc_buf = NULL;
*ifap = NULL;
/* find how much memory to allocate for the SIOCGLIFCONF call */
lifn.lifn_family = AF_UNSPEC;
lifn.lifn_flags = 0;
if (ioctl(sd, SIOCGLIFNUM, &lifn) < 0)
goto error;
/* Sun and Apple code likes to pad the interface count here in case interfaces
* are coming up between calls */
lifn.lifn_count += 4;
ifc.lifc_family = AF_UNSPEC;
ifc.lifc_len = lifn.lifn_count * sizeof(struct lifreq);
ifc.lifc_buf = calloc(1, ifc.lifc_len);
if (ioctl(sd, SIOCGLIFCONF, &ifc) < 0)
goto error;
ccp = (char *)ifc.lifc_req;
ecp = ccp + ifc.lifc_len;
while (ccp < ecp) {
ifr = (struct lifreq *) ccp;
cifa = (struct ifaddrs *) calloc(1, sizeof(struct ifaddrs));
cifa->ifa_next = NULL;
cifa->ifa_name = strdup(ifr->lifr_name);
if (pifa == NULL) *ifap = cifa; /* first one */
else pifa->ifa_next = cifa;
if (ioctl(sd, SIOCGLIFADDR, ifr, IFREQSZ) < 0)
goto error;
cifa->ifa_addr = sa_dup(&ifr->lifr_addr);
if (ioctl(sd, SIOCGLIFNETMASK, ifr, IFREQSZ) < 0)
goto error;
cifa->ifa_netmask = sa_dup(&ifr->lifr_addr);
cifa->ifa_flags = 0;
cifa->ifa_dstaddr = NULL;
if (0 == ioctl(sd, SIOCGLIFFLAGS, ifr)) /* optional */
cifa->ifa_flags = ifr->lifr_flags;
if (ioctl(sd, SIOCGLIFDSTADDR, ifr, IFREQSZ) < 0) {
if (0 == ioctl(sd, SIOCGLIFBRDADDR, ifr, IFREQSZ))
cifa->ifa_dstaddr = sa_dup(&ifr->lifr_addr);
}
else cifa->ifa_dstaddr = sa_dup(&ifr->lifr_addr);
pifa = cifa;
ccp += IFREQSZ;
}
free(ifc.lifc_buf);
close(sd);
return 0;
error:
if (ifc.lifc_buf != NULL)
free(ifc.lifc_buf);
if (sd != -1)
close(sd);
return (-1);
}

View File

@ -1,26 +0,0 @@
/* Reference: https://lists.samba.org/archive/samba-technical/2009-February/063079.html */
#ifndef __IFADDRS_H__
#define __IFADDRS_H__
#include <sys/socket.h>
#include <net/if.h>
#undef ifa_dstaddr
#undef ifa_broadaddr
#define ifa_broadaddr ifa_dstaddr
struct ifaddrs {
struct ifaddrs *ifa_next;
char *ifa_name;
unsigned int ifa_flags;
struct sockaddr *ifa_addr;
struct sockaddr *ifa_netmask;
struct sockaddr *ifa_dstaddr;
};
extern int getifaddrs(struct ifaddrs **);
extern void freeifaddrs(struct ifaddrs *);
#endif

View File

@ -1,46 +1,41 @@
/*
* Copyright (c) 2009, Giampaolo Rodola', Jeff Tang. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <Python.h>
#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) {
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;
srcaddr.ss_family = Family;
if (family == AF_INET) {
if (Family == AF_INET)
{
dwAddressLength = sizeof(struct sockaddr_in);
memcpy(&(srcaddr4->sin_addr), pAddr, sizeof(struct in_addr));
}
else if (family == AF_INET6) {
} else if (Family == AF_INET6)
{
dwAddressLength = sizeof(struct sockaddr_in6);
memcpy(&(srcaddr6->sin6_addr), pAddr, sizeof(struct in6_addr));
}
else {
PyErr_SetString(PyExc_ValueError, "invalid family");
} else {
return NULL;
}
if (WSAAddressToString((LPSOCKADDR) &srcaddr,
dwAddressLength,
0,
pStringBuf,
dwAddressLength,
0,
pStringBuf,
(LPDWORD) &StringBufSize) != 0) {
PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
return NULL;
}
return pStringBuf;
}
}

Some files were not shown because too many files have changed in this diff Show More