Seite 1 von 2

Prozess-IDs (PIDs) und den Namen laufender Prozesse

Verfasst: Freitag 19. Januar 2007, 15:06
von gerold
Hi @all!

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""
Returns processinfos. (pid, name and size_kb)

Free for everybody. (by gerold)
"""

import sys
import os


def get_current_processes():
    """
    Returns processinfos. (pid, name and size_kb)

    On Windows-Systems, it uses ``tasklist.exe`` or WMI to list the processes.
    On other platforms, it reads the "/proc"-directory.
    
    :return: Dictionary with PID's as keys and the infos as values in an
        inner dictionary. (It is possible, that "size_kb" doesn't exist.): 
        {
            123: {"name": "bash", "pid": 123},
            234: {"name": "mc", "pid": 234, "size_kb": 1000},
        }
    """
    
    retdict = {}
    
    if sys.platform.startswith("win"):
        # tasklist.exe runs on Windows XP and higher. (To parse the ouput of
        # tasklist.exe is faster than WMI.)
        import csv
        csvlines = []
        for line in os.popen("tasklist.exe /fo csv /nh"):
            line = line.strip()
            if line:
                csvlines.append(line)
        for line in csv.reader(csvlines):
            pid = int(line[1])
            details = {
                "name": line[0].decode("cp850"), # to unicode
                "pid": pid,
            }
            value = "".join(
                char for char in line[4]
                if char in "0123456789"
            )
            details["size_kb"] = int(value)
            retdict[pid] = details
        if not csvlines:
            try:
                from win32com.client import GetObject
                # pywin32 is installed --> use WMI
                wmi = GetObject('winmgmts:')
                processes = wmi.InstancesOf('Win32_Process')
                for process in processes:
                    pid = int(process.Properties_("ProcessId").value)
                    details = {
                        "name": process.Properties_("Name").value,
                        "pid": pid,
                        "size_kb": int(process.Properties_("WorkingSetSize").value) / 1000
                    }
                    retdict[pid] = details
            except ImportError:
                raise NotImplementedError("No tasklist.exe and no WMI.")
    else:
        # Linux, Cygwin
        from glob import glob
        for filename in glob("/proc/*/status"):
            try: 
                int(filename[len("/proc/"):-len("/status")])
            except ValueError:
                continue
            details = {}
            try:
                f = file(filename, "r")
                try:
                    for line in f:
                        line_lower = line.lower()
                        if line_lower.startswith("name:"):
                            details["name"] = line[len("Name:"):].strip()
                        elif line_lower.startswith("pid:"):
                            details["pid"] = line[len("pid:"):].strip()
                        elif line_lower.startswith("vmsize:"):
                            value = "".join(
                                char for char in line[len("vmsize:"):]
                                if char in "0123456789"
                            )
                            details["size_kb"] = int(value)
                        if (
                            details.has_key("name") and
                            details.has_key("pid") and
                            details.has_key("size_kb")
                        ):
                            break
                finally:
                    f.close()
            except IOError:
                pass
            if details:
                retdict[details["pid"]] = details
    
    # Return value
    return retdict or None


def main():
    """Testing"""
    
    from pprint import pformat

    # Process-Infos
    print pformat(get_current_processes())
    

if __name__ == "__main__":
    main()
Siehe auch: http://www.python-forum.de/topic-8277.html
Trac: http://gelb.bcom.at/trac/misc/browser/processinfo

lg
Gerold
:-)

Verfasst: Freitag 19. Januar 2007, 15:50
von gerold
...jetzt auch mit WMI. :-)
(dank dem Link von Leonidas)

Verfasst: Freitag 19. Januar 2007, 16:13
von sape
Super!
Ist nun, wie das vorherige Script von dir, in meiner Library 8)

Wenns dir nichts ausmacht, könntest du ja im Wiki einen Link zu diesem Thread und den anderen packen, weil man dein Script immer mal gebrauchen kann :)

lg

Verfasst: Samstag 28. Juli 2007, 16:12
von xraver
Hallo,
das Script funktioniert wunderbar.
Für mein Projekt möchte ich einfach nur überprüfen ob ein bestimmter Process vorhanden ist. Wie kann ich das Ergebnis deines Scripts (oder eines Dictionary) durchsuchen?

//update
Jetzt habe ich es erstmal so gemacht um einen gewünschten Process zu finden;

Code: Alles auswählen

str(get_current_processes()).find('firefox.exe')
Aber es gibt doch bestimmt noch eine saubere Lösung, oder?

Verfasst: Samstag 28. Juli 2007, 17:28
von lunar
http://cheeseshop.python.org/pypi/enumprocess/0.1

Wieso wird das Rad eigentlich immer neu erfunden? ;)

Verfasst: Donnerstag 6. September 2007, 12:42
von BigBo
hi gerold!

dein code ist wirklich super !

aber wie bekomm ich da aus der liste wo er mir zurückliefert die pid eines bestimmten prozesses ?

ps: ich habs mal so versucht:

Code: Alles auswählen

pid2 = fileOps.get_current_processes()
pid = str(fileOps.get_current_processes()).find('fpassist.exe')
print pid
print pid2
allerdings kam mir dann folgende ausgabe:
261
..."1004: {'pid': 1004, 'name': u'fpassist.exe', 'size_kb': 1028}"...

also hat der prozess fpassist.exe im moment die pid 1004, aber mit dem find bekomm ich 261 zurück (die position im dictionary?)

Verfasst: Donnerstag 6. September 2007, 13:44
von gerold
BigBo hat geschrieben:wie bekomm ich da aus der liste wo er mir zurückliefert die pid eines bestimmten prozesses ?
Hallo BigBo!

Nachdem ich deine Frage entschlüsselte... :?

Erstens:
Du bekommst **keine Liste** sondern ein **Dictionary** zurück.

Zweitens:
Z.B. so:

Code: Alles auswählen

processes = {
    0: {'name': u'System Idle Process', 'pid': 0, 'size_kb': 16},
    4: {'name': u'System', 'pid': 4, 'size_kb': 220},
    264: {'name': u'IAAnotif.exe', 'pid': 264, 'size_kb': 2112},
    268: {'name': u'sqlservr.exe', 'pid': 268, 'size_kb': 178548},
}

for proc in processes.values():
    if proc["name"] == "IAAnotif.exe":
        # Gefunden
        print proc["name"]
        print proc["pid"]
        break
else:
    print "Nichts gefunden"
mfg
Gerold
:-)

Verfasst: Donnerstag 6. September 2007, 14:11
von BigBo
*lach* sorry das meine frage so undeutlich formuliert war gerold, versuch mich in zukunft zu bessern, danke es funktioniert so :-)

Verfasst: Freitag 7. September 2007, 11:51
von BigBo
ähm...nochmal n sonderwunsch gerold :oops: kann man noch irgendwie in des dictionary einbauen, das es unter windows anzeigt, welcher benutzer einen prozess gestartet hat?

Vollständiger Pfad

Verfasst: Dienstag 11. Dezember 2007, 09:11
von droptix
Auch noch eine Frage/ein Wunsch von mir: Ist es möglich, dass nicht nur der Dateiname des Prozesses aufgelistet wird, sondern auch der komplette Pfad zur Datei?

Und das mit dem Besitzer des Prozesses (Benutzername) wäre auch ne feine und wichtige Sache, um zu unterscheiden ob es sich um einen Systemprozess handelt oder einen Userprozess. Unter Windows ist das bestimmt recht einfach ermittelbar -> Wie sieht es bei Unix aus?

Verfasst: Dienstag 11. Dezember 2007, 12:32
von Leonidas
In Linux gehört der zur PID gehörende Ordner in `/proc` dem ausführendem User.

Verfasst: Dienstag 11. Dezember 2007, 23:19
von droptix
Wenn ich es richtig verstehe, hat jede PID einen gleichnamigen Ordner. Also der Prozess mit der ID 123 hat den Ordner /proc/123, richtig? Dort drin lagert jede Menge Unkraut, was ich aber leider nicht zuordnen kann. Ist auch nicht ganz so wichtig...

Was mich aber interessiert: ich habe z.B. zwei gleichnamige Dateien in /foo/bar und die andere in /bar/bar. Ich führe nun beide aus. /foo/bar bekommt PID 1234 und /bar/bar bekommt PID 5678. Über Gerolds Tool kann bekomme ich ein Dictionary mit den Infos:

Code: Alles auswählen

{
    "1234": "bar",
    "5678": "bar"
}
Das ist jetzt nur sinngemäß, ihr versteht... Ich kann anhand der Prozessliste nicht unterscheiden, welche der beiden Dateien welche ist, weil beide denselben Namen tragen. Daher wäre es für mich wichtig, auch den vollständigen Pfad zur ausgeführten Datei zu kennen, um sie eindeutig zu identifizieren.

Wie könnte man den vollständigen Pfad heraus bekommen?

Verfasst: Dienstag 11. Dezember 2007, 23:36
von Leonidas
droptix hat geschrieben:Wie könnte man den vollständigen Pfad heraus bekommen?
Der Symlink `'/proc/%s/cmd' % PID` zeigt auf die entsprechende ausgeführte Datei. Du kannst sogar noch so einen Prozess damit starten, etwa so:

Code: Alles auswählen

$ /proc/$(pidof firefox-bin)/exe

Verfasst: Mittwoch 12. Dezember 2007, 09:03
von droptix
Prima! Aber ich finde nirgends /proc/PID/cmd, meinst du vielleicht /proc/PID/cwd?

Ich befinde mich im Verzeichnis /proc/1249, welches mir gehört. Dort drin liegt folgendes:
droptix@hostname:/proc/1249$ ls -la
ls: cannot read symbolic link cwd: Permission denied
ls: cannot read symbolic link root: Permission denied
ls: cannot read symbolic link exe: Permission denied
total 0
dr-xr-xr-x 6 droptix droptix 0 2007-12-12 08:53 .
dr-xr-xr-x 82 root root 0 2007-12-04 18:29 ..
dr-xr-xr-x 2 droptix droptix 0 2007-12-12 08:55 attr
-r-------- 1 root root 0 2007-12-12 08:55 auxv
--w------- 1 root root 0 2007-12-12 08:55 clear_refs
-r--r--r-- 1 root root 0 2007-12-12 08:55 cmdline
-r--r--r-- 1 root root 0 2007-12-12 08:55 cpuset
lrwxrwxrwx 1 root root 0 2007-12-12 08:55 cwd
-r-------- 1 root root 0 2007-12-12 08:55 environ
lrwxrwxrwx 1 root root 0 2007-12-12 08:55 exe
dr-x------ 2 root root 0 2007-12-12 08:55 fd
dr-x------ 2 root root 0 2007-12-12 08:55 fdinfo
-r--r--r-- 1 root root 0 2007-12-12 08:55 maps
-rw------- 1 root root 0 2007-12-12 08:55 mem
-r--r--r-- 1 root root 0 2007-12-12 08:55 mounts
-r-------- 1 root root 0 2007-12-12 08:55 mountstats
-rw-r--r-- 1 root root 0 2007-12-12 08:55 oom_adj
-r--r--r-- 1 root root 0 2007-12-12 08:55 oom_score
lrwxrwxrwx 1 root root 0 2007-12-12 08:55 root
-rw------- 1 root root 0 2007-12-12 08:55 seccomp
-r--r--r-- 1 root root 0 2007-12-12 08:55 smaps
-r--r--r-- 1 root root 0 2007-12-12 08:55 stat
-r--r--r-- 1 root root 0 2007-12-12 08:55 statm
-r--r--r-- 1 root root 0 2007-12-12 08:55 status
dr-xr-xr-x 3 droptix droptix 0 2007-12-12 08:55 task
-r--r--r-- 1 root root 0 2007-12-12 08:55 wchan
droptix@hostname:/proc/1249$
Die Symlinks cwd, root und exe darf ich nicht lesen. Also bekomme ich den Pfad nur mit root-Rechten raus... aber das lässt sich ja einrichten. Sieht dann so aus:
droptix@hostname:/proc/1249$ sudo ls -la
total 0
dr-xr-xr-x 6 droptix droptix 0 2007-12-12 08:53 .
dr-xr-xr-x 82 root root 0 2007-12-04 18:29 ..
dr-xr-xr-x 2 droptix droptix 0 2007-12-12 08:55 attr
-r-------- 1 root root 0 2007-12-12 08:55 auxv
--w------- 1 root root 0 2007-12-12 08:55 clear_refs
-r--r--r-- 1 root root 0 2007-12-12 08:55 cmdline
-r--r--r-- 1 root root 0 2007-12-12 08:55 cpuset
lrwxrwxrwx 1 root root 0 2007-12-12 08:55 cwd -> /
-r-------- 1 root root 0 2007-12-12 08:55 environ
lrwxrwxrwx 1 root root 0 2007-12-12 08:55 exe -> /usr/sbin/sshd
dr-x------ 2 root root 0 2007-12-12 08:55 fd
dr-x------ 2 root root 0 2007-12-12 08:55 fdinfo
-r--r--r-- 1 root root 0 2007-12-12 08:55 maps
-rw------- 1 root root 0 2007-12-12 08:55 mem
-r--r--r-- 1 root root 0 2007-12-12 08:55 mounts
-r-------- 1 root root 0 2007-12-12 08:55 mountstats
-rw-r--r-- 1 root root 0 2007-12-12 08:55 oom_adj
-r--r--r-- 1 root root 0 2007-12-12 08:55 oom_score
lrwxrwxrwx 1 root root 0 2007-12-12 08:55 root -> /
-rw------- 1 root root 0 2007-12-12 08:55 seccomp
-r--r--r-- 1 root root 0 2007-12-12 08:55 smaps
-r--r--r-- 1 root root 0 2007-12-12 08:55 stat
-r--r--r-- 1 root root 0 2007-12-12 08:55 statm
-r--r--r-- 1 root root 0 2007-12-12 08:55 status
dr-xr-xr-x 3 droptix droptix 0 2007-12-12 08:55 task
-r--r--r-- 1 root root 0 2007-12-12 08:55 wchan
Ich denke der Symlink exe zeigt auf die Datei und cwd wahrscheinlich auf das Current Working Directory, oder? Was bedeuted root?

Verfasst: Mittwoch 12. Dezember 2007, 09:16
von Rebecca
droptix hat geschrieben:Ich denke der Symlink exe zeigt auf die Datei und cwd wahrscheinlich auf das Current Working Directory, oder?
Yepp.
droptix hat geschrieben:Was bedeuted root?
Das ist das Wurzelverzeichnis.

Verfasst: Mittwoch 12. Dezember 2007, 09:47
von Leonidas
droptix hat geschrieben:Prima! Aber ich finde nirgends /proc/PID/cmd, meinst du vielleicht /proc/PID/cwd?
Nein, ich meine so wie ich geschrieben habe `exe`. Und bei mir ist die User-lesbar, zumindest für den der sie gestartet hat. Was hast du für ein System? Distribution und Kernel?

Verfasst: Mittwoch 12. Dezember 2007, 16:09
von droptix
Rebecca hat geschrieben:
droptix hat geschrieben:Was bedeuted root?
Das ist das Wurzelverzeichnis.
:twisted: LOL!

Ist denn root nicht immer /, weil man das hier extra auflistet? Aber das tut wenig zur Sache... ich weiß jetzt alles um mir Gerolds Script etwas anzupassen. Danke!

Verfasst: Mittwoch 12. Dezember 2007, 16:20
von Leonidas
Es kann ja sein, dass das Programm in einem Chroot läuft da etwas anderes steht.

Verfasst: Mittwoch 12. Dezember 2007, 16:25
von droptix
Leonidas hat geschrieben:Der Symlink `'/proc/%s/cmd' % PID` zeigt auf die entsprechende ausgeführte Datei.
^^ Du sagtest cmd, daher die Verwirrung.
Leonidas hat geschrieben:
droptix hat geschrieben:Prima! Aber ich finde nirgends /proc/PID/cmd, meinst du vielleicht /proc/PID/cwd?
Nein, ich meine so wie ich geschrieben habe `exe`. Und bei mir ist die User-lesbar, zumindest für den der sie gestartet hat. Was hast du für ein System? Distribution und Kernel?
Habe Ubuntu Linux 7.10 (Gutsy). Bei mir war die nicht User-lesbar.

Verfasst: Mittwoch 12. Dezember 2007, 16:40
von Leonidas
Gah, hast recht. :evil: Ich war absolut überzeugt, dass ich `exe` geschrieben habe.

Gut, was hat denn Gutsy für einen Kernel und was für eine glibc?