[Gelöst] CPU-Auslastung eines bestimmten Prozesses und eines bestimmten Users auslesen und weiterverarbeiten

  • Moin, ich weiss nicht wohin damit, also OT.

    Wie der Titel schon sagt, möchte ich die CPU-Auslastung eines bestimmten Prozesses eines bestimmten Users auslesen und weiterverarbeiten, habe aber irgendwie den Eindruck, dass sich das einfacher, eleganter und stabiler machen ließe.

    Im Moment sieht das ganze z.B. mit dem Prozess sox und dem User pi so aus:

    Code
    pidstat -p ALL -G sox -C sox --dec=0 -h --human -U pi -I -C "sox" | tr "\n" " " | cut -c182-183 > /dev/shm/avg_cpu.txt

    Probiert habe ich auch schon die zahlreichen anderen Tools, aber bin für Vorschläge offen, egal ob in bash oder python.

    Was auch ein Problem ist, dass er immer den Durchschnitt seit dem Systemstart zu nehmen scheint, statt dem aktuellen Wert.

    :helpnew:

  • Hallo fred0815,


    wenn Du die dynamische Veränderung ermitteln können möchtest, dann solltest Du direkt die Daten in /proc auswerten. D.h. mit so einer einfachen Bash-Pipe kommst Du nicht ans Ziel.


    Vor ein paar Jahren habe ich dazu mal einen Beitrag mit Programm-Code gepostet.


    Mit zwei geänderten Zeilen (User, Prozess) sollte Dein Ergebnis ermittelt werden können.



    Beste Grüße


    Andreas Schulz

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    • Icon-Tutorials (IDE: Geany) - GPIO-Library - µController-Programmierung in Icon! - ser. Devices - kein Support per PM / Konversation

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • Dann probiere ich es anders, z.B. mit

    ifstat -z -n -b 5 | cut -c3-5 > /dev/shm/kbs.txt

    lese ich die Übertragungsrate aus und schreibe sie nach /dev/shm/ , von dort aus kann ich sie weiterverarbeiten und noch mit Bedingungen verknüpfen, Hauptsache ist, ich kann irgendwie feststellen, dass der Stream noch läuft.

    Ist zwar nicht die Lösung, wie in der Frage gestellt, aber egal ist ja in OT. :lol:

  • Wo sind denn die {$} definiert, woher kommen die ?

    Das sind die Felder/Spalten der top-Ausgabe, separiert durch Whitespace (default).

    top -n 1 -d 1 -b -U pi | awk '/sox/ {print $9}'

    Menschen die keine Ironie verstehen finde ich super!

  • Wo sind denn die {$} definiert, woher kommen die ?

    Das sind die Spalten.


    Möglicherweise unterscheidet sich von Distribution zu Distribution die Reihenfolge der Felder oder ich habe mich um eins vertan. Bei interaktiven tools ist es meist so, dass die Ausgabe nicht so gut verwetbar ist. Andere Tools haben sogar ein Warnhinweis, dass die Ausgabe nicht zur Verarbeitung in Shell-Scripten geeignet ist.


    Bei top kann man wohl auch die Reihenfolge der Felder selber vorgeben.

  • Da Python angesprochen wurde: Da ist das `psutil`-Modul ganz nützlich um alle möglichen Informationen über Prozesse zu erfahren.

    “If debugging is the process of removing software bugs, then programming must be the process of putting them in.” — Edsger Dijkstra

  • fred0815

    Changed the title of the thread from “CPU-Auslastung eines bestimmten Prozesses und eines bestimmten Users auslesen und weiterverarbeiten” to “[Gelöst] CPU-Auslastung eines bestimmten Prozesses und eines bestimmten Users auslesen und weiterverarbeiten”.
  • __blackjack__

    Mit Python mag er nicht, ausgerechnet bei getloadavg bricht er ab:

    Code
    #!/usr/bin/env python3
    import psutil
    print(psutil.users())
    print(psutil.cpu_percent(5))
    print("Number of cores in system", psutil.cpu_count())
    print("\nNumber of physical cores in system",)
    print(psutil.getloadavg())

    Fehlermeldung:

    Code
    ./avg_cpu.pydio:~ $ 
    [suser(name='pi', terminal='tty1', host='', started=1607384064.0, pid=667), suser(name='pi', terminal='tty7', host='localhost', started=1607384064.0, pid=669), suser(name='pi', terminal='pts/0', host='192.168.0.2', started=1607384832.0, pid=953)]
    2.2
    Number of cores in system 1
    
    Number of physical cores in system
    Traceback (most recent call last):
      File "./avg_cpu.py", line 7, in <module>
        print(psutil.getloadavg())
    AttributeError: module 'psutil' has no attribute 'getloadavg'

    :conf:

  • Entweder du hast irgendwo ein Modul im Suchpfad mit dem gleichen Namen oder es existiert eine Uralt-Version von psutil, dass diese Funktion noch nicht implementiert hat. Ich tippe mal auf ersteres, denn getloadvg hört sich wichtig an.


    Code
    python3 -c "import psutil; print(psutil.version_info)"
    python3 -c "import psutil; print(psutil.__file__)"


    Ausgabe:

    Quote

    (5, 7, 0)

    /usr/local/lib/python3.7/dist-packages/psutil/__init__.py


    Das ist auf meinem Server mit Debian Buster. Dort ist psutil über den Paketmanager installiert worden und deswegen ist es in dist-packages.

    In site-packages wäre es dann ein von pip installiertes Paket. Wenn dort noch ein ganz anderer Suchpfad auftaucht, hast du den Übeltäter gefunden.

    Ein häufiger Fehler ist es, den gleichen Namen für ein Modul zu verwenden, dass installiert ist.


    Wenn du z. B. rein zufällig eine psutil.py im aktuellen Verzeichnis hast, Python öffnest, psutil importierst, dann hast du die psutil.py aus dem aktuellen Verzeichnis und nicht aus dist-packages/site-packages.

  • Code
    python3 -c "import psutil; print(psutil.version_info)"
    python3 -c "import psutil; print(psutil.__file__)"

    Ein häufiger Fehler ist es, den gleichen Namen für ein Modul zu verwenden, dass installiert ist.

    Ausgabe:

    Code
    python3 -c "import psutil; print(psutil.version_info)"
    (5, 5, 1)
    python3 -c "import psutil; print(psutil.__file__)"
    /usr/lib/python3/dist-packages/psutil/__init__.py

    Der Name der Datei ist selbstverständlich abweichend genug, das hatte ich auch schon im Internet gelesen, dass sich die Dateinamen sich nicht in die Quere kommen dürfen. :bravo2:

  • Ja, das ist doof.


    getloadavg ist irgendwann nach psutil 5.5.1 eingeführt worden, aber 5.5.1 ist der momentane Release für Debian Buster.


    Das ist einer der vielen Gründe, wieso ich selten bis gar nicht den vorinstallierten Python-Interpreter nutze. Mir ist das alles einfach zu alt.


    Da du unter Linux arbeitest, sollte auch os.getloadavg zur Verfügung stehen.

    Diese Funktion wird einfach nur in psutil/__init__.py referenziert: https://github.com/giampaolo/p…/psutil/__init__.py#L1896


    Also:

    Code
    import os
    
    
    print(os.getloadavg())


    Wenn das Programm betriebsystemunabhängig sein soll, vereinfacht die Verwendung von psutil die Sonderfälle.

    Unter Windows gibt es z.B. kein os.geloadavg und an dieser Stelle springt psutil ein, um eine Ersatzfunktion zur Verfügung zu stellen.

  • Ist zwar schon als gelöst markiert, aber hier noch meine stümperhafte Pythonvariante.

    Prüft ob die Dateien vorhanden sind, erstellt sie, falls nicht.

    Prüft, ob der Prozess läuft, die durchschnittliche CPU-Auslastung der letzten 5 Sekunden, die durchschnittliche Netzwerkauslastung der letzten 5 Sekunden, wenn min_net und min_cpu unterschritten wird, beendet und startet es den Prozess via stop.sh und start.sh.

    Nicht wundern, der Teil mit dem Prozesscheck kommt noch, ich wollte das nur hier verewigen, bevor ich weiter drauf rumhacke und anschliessend wieder nichts geht. :lol:

  • fred0815: Das ist ein bisschen viel Code auf einmal IMHO. Also mehr als eine Funktion.


    `max_cpu` wird definiert aber nirgends verwendet. Das und `min_cpu` und `min_net` sind wohl Konstanten und sollten als solche KOMPLETT_GROSS geschrieben werden.


    Namen sollte man nicht kryptisch abkürzen. Nicht `fname` wenn `filename` gemeint ist, wobei `file_path` hier weniger irreführend wäre, weil der Leser bei `filename` eine Zeichenkette erwarten würde und eher nicht ein `Path`-Objekt.


    Die "/dev/shm/cpu_avg.txt"-Datei ist komisch. Du schreibst da rein und liest den geschriebenen Wert sofort wieder aus. Das macht keinen Sinn den Wert wieder auszulesen. Du hast den ja bereits an der Stelle, sonst hättest Du ihn ja nicht in die Datei schreiben können‽ Vor dem schreiben ist der Wert an den Namen `cpu_avg` gebunden und den eingelesenen Wert bindest Du an den Namen `avg_cpu`. Verwirrender geht's ja wohl kaum.


    Die "/dev/shm/Prozesscheck.txt"-Datei wird auch im gleichen Programm geschrieben und gelesen obwohl man an der Stelle den Wert einfach innerhalb des Programms an einen Namen hätte binden können. Warum? Der gelesene Wert wird auch nirgends verwendet.


    Die zum lesen geöffnete Datei bleibt nach dem einlesen auch den gesamten ``if``-Zweig lang geöffnet.


    Die drei Zeilen zum Auslesen der CPU-Auslastung und schreiben in eine Datei stehen vier mal im Code. Das ist offensichtlich ein Kandidat für eine Funktion.


    Man vergleicht nicht mit literalen Wahrheitswerten. Da kommt nur wieder ein Wahrheitswert bei heraus. Entweder der, den man sowieso schon hatte, dann kann man den auch gleich nehmen, oder dessen Gegenteil, dafür ist dann ``not`` da. Wobei Methoden immer ungleich `False` sind. Du musst `is_file()` auch aufrufen, sonst ist die Bedingung dort *immer wahr*.


    Redundanz ist in Daten genau so schlecht wie in Code. Den gleichen Dateinamen/-pfad schreibt man nicht 7(!) mal in den Quelltext, sondern definiert da *einmal* eine Konstante für.


    Literale Zeichenketten an `str()` zu übergeben ist irgendwie sehr sinnlos.


    Man sollte mehr Gebrauch von `Path`-Objekten machen. Die haben beispielsweise Methoden um einen gesamten Dateiinhalt zu lesen oder zu schreiben.


    Der Test ob "/dev/shm/cpu_avg.txt" eine vorhandene Datei ist macht keinen Sinn, weil die Datei auch ohne die Sonderbehandlung erstellt wird.


    Zwischenstand (ungetestet):

    “If debugging is the process of removing software bugs, then programming must be the process of putting them in.” — Edsger Dijkstra

  • Noch bissl aufgeräumt und durchschnittliche Netzwerkauslastung zwischenreingeknüppelt und läuft:

    Jetzt fehlt nur noch der Watchdog und der Teil, in dem noch der freie/belegte Speicher berücksichtigt wird. :bravo2:

    :danke_ATDE: