Portable Weg, um alle PIDs von cmdline zu finden

425
Nisba

Ich möchte die PID aller Prozesse ermitteln, die von einem Cmdline-Aufruf ausgeführt wurden, der eine bestimmte Zeichenfolge enthält my_exec.

Öffnen Sie zum Beispiel mit macOS oder Ubuntu ein Terminal und führen Sie es aus /bin/bash, und führen Sie dann einen anderen Terminaltyp aus ps all | grep '/bin/bash'. Sie werden mit so etwas aufgefordert

 501 2995 2366 0 31 0 4290112 1424 - Ss+ s000 0:00.01 /bin/bash --noediting -i 0 2316 2274 0 31 0 4349520 6376 - Ss s007 0:00.02 login -pfl my_username /bin/bash -c exec -la bash /bin/bash 0 2325 2274 0 31 0 4349520 6380 - Ss s008 0:00.02 login -pfl my_username /bin/bash -c exec -la bash /bin/bash 501 8246 2333 0 31 0 4279872 1520 - S+ s008 0:00.00 /bin/bash 501 8255 8248 0 31 0 4267768 888 - S+ s014 0:00.00 grep /bin/bash 

Die zweite Spalte ist die PID, also kann ich sie mit sed spielen.

Bei Ubuntu ist das Format der Ausgabe ps alletwas anders, daher sollte man verschiedene sed-Aufrufe verwenden, sowieso ist es einfach, damit umzugehen.

Das Problem ist, dass das Format der Ausgabe unter den verschiedenen Linux-Distributionen psvöllig unterschiedlich sein kann. Dies ist beispielsweise bei Alpine Linux der Fall, für das ich nicht einmal die Spalte mit der Cmdline erhalten kann.

Was kann ich für einen tragbaren Code tun? Vielleicht die Dateien manuell untersuchen /proc/<PID>/cmdline(vielleicht gibt es hier Probleme mit Berechtigungen)?

Dies ist mein bisheriger Code, bitte helfen Sie mir für den anderen Teil.

if [ "$(uname)" == "Darwin" ]; then  pid=$(ps all|grep 'my_exec'|sed 's/^[[:space:]]*[a-z0-9]*//g'|sed 's/^[[:space:]]*\([0-9]*\)[^0-9].*/\1/g'); pid=$(echo $pid|xargs) IFS=' ' read -r -a array <<< "$pid" else %portable code for various linux distros fi 
1

2 Antworten auf die Frage

2
davidgo

Ich glaube, das Problem ist, dass Sie den Schalter "all" verwenden - wenn Sie dies verwenden

Wenn die Version von ps dies unterstützt (busybox funktioniert nicht), verwenden Sie

 ps -o pid,command 

ist möglicherweise der einfachste Weg, um eine definierte und leicht zu durchlaufende Ausgabe zu erhalten

Wenn du benutzt

ps w 

Dies wird mit eingebetteten Systemen kompatibel sein, die ebenfalls Busybox verwenden, jedoch mit weniger Funktionalität.

Ich versuche es morgen, bevor Sie geantwortet haben, dass ich weiter an einer Lösung gearbeitet habe, werde ich als Antwort posten, was ich am Ende erhalten habe Nisba vor 6 Jahren 0
0
Nisba

Ich endete mit diesem Code, im Grunde betrachtet er alle Prozesse in /proc/, sucht nach Inhalt /proc/<PID>/cmdlineund prüft, ob in dieser Zeichenfolge ein my_execTeilstring vorhanden ist.

Beachten Sie die Verwendung von trzum Analysieren des Inhalts von, cmdlineum eine \0-separierte Zeichenfolge in eine durch Leerzeichen getrennte Zeichenfolge umzuwandeln.

array=() pids=$(find /proc -maxdepth 1 -name '*'|sed 's/^\/proc\(\/[-a-z_]*\)*//g'|tr '\n' ' '|xargs) IFS=' ' read -r -a pid_array <<< "$pids" for pid in "$"; do file="/proc/"$pid"/cmdline" if [ -f $file ]; then cmd=$(cat $file|tr '\0' ' ') g=$(grep 'my_exec' <<< $cmd) if [ "$" != " " ]; then  g=$g" " fi if [ "$cmd" == "$g" ] && [ -n "$cmd" ]; then echo '"'$cmd'"'", "'"'$g'"' array+=($pid) fi fi done