Modo portatile per trovare tutti i PID per cmdline


1

Voglio trovare il PID di tutti i processi che sono stati eseguiti da una chiamata cmdline che contiene una determinata stringa my_exec.

Ad esempio, con macOS o Ubuntu, apri un terminale ed esegui /bin/bash, quindi in un altro tipo di terminale ps all | grep '/bin/bash'. Ti verrà richiesto con qualcosa del genere

  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

La seconda colonna è il PID, quindi sarò in grado di farlo giocare con sed.

Con Ubuntu il formato dell'output è ps allleggermente diverso, quindi si dovrebbero usare diverse chiamate sed, comunque è facile gestirlo.

Il problema è che tra le varie distro Linux il formato dell'output di pspuò essere completamente diverso. Ad esempio, questo è il caso di Alpine Linux, per il quale non sono nemmeno in grado di ottenere la colonna contenente il cmdline.

Cosa posso fare per avere un codice portatile? Forse esaminando manualmente i file /proc/<PID>/cmdline(forse ci sono problemi con le autorizzazioni qui)?

Questo è il mio codice finora, per favore aiutatemi per l'altra parte.

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

Risposte:


2

Credo che il problema sia il tuo utilizzo dell'interruttore "all" - se lo usi

Se la versione di ps lo supporta (busybox non lo fa), usando

 ps -o pid,command 

può essere il modo più semplice per ottenere un output definito e facile da passare

Se usi

ps w

Sarà compatibile con i sistemi embedded che usano anche Busybox, ma con meno funzionalità.


Ci proverò domani, prima che tu abbia risposto che ho continuato a lavorare su una soluzione, posterò come risposta quello che ho finito con
Nisba

0

Ho finito con questo codice, fondamentalmente considera tutti i processi /proc/, cerca il contenuto /proc/<PID>/cmdlinee controlla se in quella stringa c'è una my_execsottostringa.

Si noti l'uso di trper analizzare il contenuto di cmdlineper trasformare una \0stringa separata in una stringa separata da spazio.

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 "${pid_array[@]}"; do
    file="/proc/"$pid"/cmdline"
    if [ -f $file ]; then
        cmd=$(cat $file|tr '\0' ' ')
        g=$(grep 'my_exec' <<< $cmd)
        if [ "${g: -1}" != " " ]; then                
            g=$g" "
        fi
        if [ "$cmd" == "$g" ] && [ -n "$cmd" ]; then
            echo '"'$cmd'"'", "'"'$g'"'
            array+=($pid)
        fi
    fi
done
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.