Bash - Prozessstruktur anzeigen lassen mit ps

Datum

Jeder Linux-Administrator kennt ps. Je nach Parametern werden sehr detaillierte Prozessinformationen aufgelistet. U. a. welcher Prozess der übergeordnete ist usw. Die Ausgabe von ps ist dabei schon gerne einmal unübersichtlich und man muss schon suchen, um eine Struktur zu erkennen.

Um das zu vereinfachen, habe ich ein kleines Skript entworfen, welches sich in einer Schleife durch die Ausgabe von ps grept, bis der letzte Rattenschwanz einer Prozessstruktur erfasst worden ist. Das Prinzip ist dabei recht simpel: Man sucht nach einer Zeichenkette, das Srkipt geht jeden Eintrag durch, der dafür in Frage kommt, und sucht auch gleich die durch diesen Prozess aufgerufenen Subprozesse.

Hier nun das Skript:

#!/bin/bash
crawled=()
function contains() {
        for e in "${crawled[@]}"
        do
                if [ "$e" == "$1" ]
                then
                        echo "1"
                        return 0
                fi
        done
        echo "0"
        return 0
}
function crawlps() {
        OIFS=$IFS
        IFS=$'\n'
        for ln in $(ps alx | sed 's/ \+/ /g' | cut -d' ' -f2,3,4,13- | sort -k3 -n | grep " $1 " | grep -v 'grep' | grep -v $3)
        do
                u=$(echo $ln | cut -d' ' -f1)
                p1=$(echo $ln | cut -d' ' -f2)
                p2=$(echo $ln | cut -d' ' -f3)
                c=$(echo $ln | cut -d' ' -f4-)
                if [ "$p1" == "$1" ] && [ "$(contains $1)" == "0" ]
                then
                        for i in $(seq 1 $2)
                        do
                                echo -n '  '
                        done
                        echo "$p2 --> $p1: $u: $c"
                        crawled=("${crawled[@]}" "$1")
                elif [ "$p2" == "$1" ]
                then
                        crawlps $p1 $(($2+1)) $3
                fi
        done
        IFS=$OIFS
}
OIFS=$IFS
IFS=$'\n'
for proc in $(ps alx | sed 's/ \+/ /g' | grep "$1" | grep -v ' PPID ' | grep -v 'grep' | grep -v ${0##*/} | cut -d' ' -f3,4 | sort -k2 -n)
do
        crawlps $(echo $proc | cut -d' ' -f1) 0 ${0##*/}
done
IFS=$OIFS

Zur Erläuterung:

  • Zunächst werden zwei Funktionen deklariert und definiert: contains und crawlps
  • In der ersten wird das Array crawled nach einem übergebenen Wert durchsucht und entspr. 1 (Treffer) oder 0 (kein Treffer) ausgegeben.
  • In der zweiten wird die Ausgabe von ps mit entspr. Parametern gefiltert, sortiert und formatiert. Das ergebnis wird in einer Schleife durchgegangen.
  • Es wird geprüft, ob es sich in der Zeile um die übergebene Prozess-ID handelt. (In dem Fall werden die wesentlichen Informationen zu diesem Prozess aufgegeben:)
    • Eltern-PID —> PID: User-ID: Vollständiger Aufruf
  • Falls nicht, wird geprüft, ob es sich bei der übergebenen PID um die übergeordnete Prozess-ID handelt. (In dem Fall wird für diesen Prozess erneut die Funktion crawlps aufgerufen.)
  • Nach der Funktion erfolgt der erste Aufruf und es wird nach einem übergebenen String gefiltert.

Ein Beispiel:

ansible@ansible:~$ ./test.sh ssh
1 --> 14134: 1000: ssh: /home/ansible/.ansible/cp/fa38416f61 [mux]
1 --> 14138: 1000: ssh: /home/ansible/.ansible/cp/0018b3053c [mux]
1 --> 14141: 1000: ssh: /home/ansible/.ansible/cp/2963d0ab38 [mux]
1 --> 14144: 1000: ssh: /home/ansible/.ansible/cp/69fa50d11b [mux]
1 --> 14187: 1000: ssh: /home/ansible/.ansible/cp/b8eef2364b [mux]
1 --> 14190: 1000: ssh: /home/ansible/.ansible/cp/d4cd3c5822 [mux]
1 --> 14193: 1000: ssh: /home/ansible/.ansible/cp/df3202863f [mux]
1 --> 14196: 1000: ssh: /home/ansible/.ansible/cp/52a7e46d0b [mux]
1 --> 14224: 1000: ssh: /home/ansible/.ansible/cp/d0234c0b50 [mux]
1 --> 14228: 1000: ssh: /home/ansible/.ansible/cp/56223fd03c [mux]
1 --> 14240: 1000: ssh: /home/ansible/.ansible/cp/6de55b42e5 [mux]
1 --> 14264: 1000: ssh: /home/ansible/.ansible/cp/b1f85a8b4d [mux]
1 --> 14281: 1000: ssh: /home/ansible/.ansible/cp/8d4319711b [mux]
1 --> 14284: 1000: ssh: /home/ansible/.ansible/cp/1a8d9b688f [mux]
1 --> 14301: 1000: ssh: /home/ansible/.ansible/cp/77145622b8 [mux]
1 --> 446: 0: /usr/sbin/sshd -D
  446 --> 20782: 0: sshd: ansible [priv]
    20782 --> 20784: 1000: sshd: ansible@pts/1
      20784 --> 20785: 1000: -bash

Das Skript nimmt sich selbst aus der Ausgabe natürlich raus, sowie auch grep.

Autor
Kategorien Linux, Scripting

PRTG Map