Holen Sie sich die Speicher-/CPU-Auslastung nach Anwendung

Holen Sie sich die Speicher-/CPU-Auslastung nach Anwendung

Was ich brauche

Ich möchte Systemressourcen (nämlich Speicher- und CPU-Auslastung) nach Anwendung überwachen – nicht nur nach Prozess. So wie der Windows Task-Manager Ressourcen nach dem „aufrufenden Mutterprozess“ gruppiert, möchte ich es auch so sehen. Heutzutage erzeugen Anwendungen wie Firefox und vscode viele untergeordnete Prozesse und ich möchte einen schnellen und vollständigen Überblick über deren Nutzung erhalten.

Die Lösung kann eine GUI oder TUI, ein Bash-Skript oder ein großer Einzeiler sein. Mir ist das eigentlich egal. Damit es funktioniert, könnte ich es theoretisch mit der PID des Mutterprozesses oder dem Namen einer ausführbaren Datei füttern, um es zu filtern.

Beispiel

Task-Manager gruppiert/sammelt Systemressourcen des Chrome-Browsers

Was ich versucht habe

  • Ich habe es versucht htop, aber es wird mir nur ein Baum angezeigt, in dem der aufrufende Prozess seinen eigenen Speicher aufgelistet hat – nicht die, die er aufgerufen hat.
  • Ich habe das versucht gnome-system-monitor, aber es ist dasselbe.
  • Ich habe ein bisschen mit psund herumprobiert free, aber nicht den richtigen Satz an Argumenten/Pipes gefunden, um sie das tun zu lassen, was ich will.

Ich bin ratlos, dass ich dafür keine Lösung googeln konnte. Vielleicht gibt es dafür einen Grund?

Hat jemand eine Idee? Ich wäre sehr dankbar!

Antwort1

Das folgende Skript erfordert viele zusätzliche Verbesserungen, aber ich denke, es kann als Grundlage dienen.
Ich habe angefangen, Kommentare zu schreiben, kann es aber vorerst nicht beenden. Ich werde Änderungen an meiner Antwort verwenden, um neue Kommentare hinzuzufügen und Fehler zu beheben, wenn ich mehr Freizeit habe.
In meiner Umgebung funktioniert es einwandfrei. Ich habe dieses Skript mytop genannt und es in /usr/local/bin abgelegt, damit ich die Tab-Vervollständigung des Bash-Befehls darauf habe. Sie können mytop in Ihr ~/bin-Verzeichnis (wenn ~/bin nicht in Ihrem $PATH ist, fügen Sie es hinzu) oder an einen beliebigen Ort auf Ihrem Computer legen. Natürlich muss das Execute-Bit mit chmod u+x mytop gesetzt sein.

#!/bin/bash
# mytop -ver 1.0

# script name (default is: 'mytop')
s_name=$(basename $0)

# version
ver="1.0"

# set default time between mytop iterations
sec_delay=3 
# set default mytop repetitions/iterations
mt_rep=1000000

# Help function explaining syntax, options, ...
Help()
{
# Display Help
echo
echo "Show Totals of %CPU and &MEM using 'top' command."
echo
echo "Syntax:"
echo "   $s_name [-h|-V]"
echo "   $s_name [[-d <S>][-n <N>] <APP_NAME>"]
echo 
echo "Options:"
echo "     -h       Print this Help."
echo "     -d S     Delay/wait S seconds between iterations (default: 3 seconds)."
echo "     -n N     Run/iterate 'mytop' N times (default: 3 times)."
echo "     -V       Print version."
echo
echo "Examples:"
echo "   mytop -V"
echo "   mytop -d1 -n5 chromium"
echo
echo 'Use CTRL+C for exit!'
echo
}

# Handling options from command line arguments
while getopts ":hn:d:V" option; do
case $option in
  h) # display Help
     Help
     exit;;
  V) # print version 
     echo "$s_name $ver"
     exit;;
  n) # set how many times 'mytop' will repeat/iterate
     mt_rep=$OPTARG;;
  d) # set delays in seconds
     sec_delay=$OPTARG;;
 \?)
     echo "$s_name: inapropriate: '$1'."
     echo "Usage:"
     echo "  $s_name [-h|-V|-d<S> -n<N> <APP_NAME>]"
     exit;;
  esac
done

# If no arguments given just display Help function and exit
if [[ $# -eq 0 ]]; then
    Help
    exit
else
    # If last argument starts with '-' exit from app
    if [[ ${@:$#} =~ -+.* ]]; then
        echo ${s_name}: error: Last argument must be the name of the application that you want to track. >&2
        exit 1
    else
        app_name=${@:$#}
    fi
fi



# Set 'dashes' literally
#t_dsh='-----------------------------------------------------------'
# or set them with printf command
t_dsh=$(printf '%0.s-' {1..59})

# Not in use
#if [[ -z $mt_rep ]] 2>/dev/null; then
#   r_endless=1
#   mt_rep=1000
#else
#   r_endless=0
#fi



i=0
while [[ $i -lt $mt_rep ]]; do

    #if [[ "$r_endless" == "0" ]]; then ((i++)); fi
    ((i++))

    # Handle pids of app you want to track by removing 'mytop' pids
    # get s_name (mytop) pids
    pgrep $s_name > /tmp/mt_pids
    # get app_name pids -all of them --not desired behaviour
    pgrep -f $app_name > /tmp/app_name_pids
    # get app_name without mytop pids --desired behaviour
    for e in $(cat /tmp/mt_pids); do sed -i "/$e/d" /tmp/app_name_pids; done
    if [[ ! -s "/tmp/app_name_pids" ]]; then echo "1000000" > /tmp/app_name_pids; fi

    # top -b -n1 -p; -b for output without ANSI formating; -n1 for just one iteration of 'top'; -p for feeding processes from 'pgrep' command
    # Use LC_NUMERIC if your 'top' command outputs 'commas' instead 'dots' - with LC_NUMERIC you will get 'dots' during this script
    LC_NUMERIC=en_US.UTF-8 top -b -n1 -p $(cat /tmp/app_name_pids | xargs | tr ' ' ,) > /tmp/pstemp

    wc_l=$(wc -l < /tmp/pstemp)

    cpu_use=$(tail -n +8 /tmp/pstemp | tr -s ' ' | sed 's/^ *//' | cut -d' ' -f9 | xargs | tr ' ' + | bc)
    if [[ "$cpu_use" == "0" ]]; then
        cpu_use="0.0"
    else
        if (( $(bc <<< "$cpu_use < 1") )); then cpu_use="0$cpu_use"; fi
    fi

    mem_use=$(tail -n +8 /tmp/pstemp | tr -s ' ' | sed 's/^ *//' | cut -d' ' -f10 | xargs | tr ' ' + | bc)
    if [[ "$mem_use" == "0" ]]; then
        mem_use="0.0"
    else
        if (( $(bc <<< "$mem_use < 1") )); then mem_use="0$mem_use"; fi
    fi

    echo -en "\033[2J\033[0;0f"
    # Use 'echo ...' above or 'tput ...' below (chose the one that works for you)
    #tput cup 0 0 && tput ed

    # Align Totals under %CPU and %MEM columns
    if (( $(bc <<< "$cpu_use < 1") )); then
        sed "${wc_l}a \\\n\nTotal (%CPU/%MEM): $(printf " %29s")$cpu_use  $mem_use\n${t_dsh}" /tmp/pstemp
    elif (( $(bc <<< "$cpu_use < 100") )); then
        sed "${wc_l}a \\\n\nTotal (%CPU/%MEM): $(printf " %28s")$cpu_use  $mem_use\n${t_dsh}" /tmp/pstemp
    else
        sed "${wc_l}a \\\n\nTotal (%CPU/%MEM): $(printf " %27s")$cpu_use  $mem_use\n${t_dsh}" /tmp/pstemp
    fi  

    if [[ $i -lt $mt_rep ]]; then sleep $sec_delay; fi
done

verwandte Informationen