Cara portabel untuk menemukan semua PID dengan cmdline

1

Saya ingin menemukan PID dari semua proses yang dijalankan oleh panggilan cmdline yang berisi string tertentu my_exec.

Misalnya, dengan macOS atau Ubuntu, buka terminal dan jalankan /bin/bash, dan kemudian dalam jenis terminal lain ps all | grep '/bin/bash'. Anda akan diminta dengan sesuatu seperti ini

  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

Kolom kedua adalah PID jadi saya akan bisa membuatnya bermain dengan sed.

Dengan Ubuntu format outputnya ps allsedikit berbeda, jadi orang harus menggunakan panggilan sed yang berbeda, toh mudah menangani hal ini.

Masalahnya adalah bahwa di antara berbagai distro Linux format output psbisa sangat berbeda. Sebagai contoh, ini adalah kasus Alpine Linux, di mana saya bahkan tidak bisa mendapatkan kolom yang berisi cmdline.

Apa yang dapat saya lakukan untuk memiliki kode portabel? Mungkin memeriksa file secara manual /proc/<PID>/cmdline(mungkin ada masalah izin di sini)?

Ini adalah kode saya sejauh ini, tolong bantu saya untuk bagian lain.

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
Nisba
sumber

Jawaban:

2

Saya percaya masalahnya adalah Anda menggunakan tombol "semua" - jika Anda menggunakannya

Jika versi ps mendukungnya (busybox tidak), gunakan

 ps -o pid,command 

mungkin cara termudah untuk mendapatkan output yang jelas dan mudah untuk lulus

Jika Anda menggunakan

ps w

Itu akan kompatibel dengan sistem tertanam yang menggunakan Busybox juga, tetapi dengan fungsionalitas yang lebih sedikit.

davidgo
sumber
Saya mencoba ini besok, sebelum Anda menjawab saya terus mengerjakan solusi, saya akan memposting sebagai jawaban apa yang akhirnya saya dapatkan
Nisba
0

Saya berakhir dengan kode ini, pada dasarnya itu mempertimbangkan semua proses dalam /proc/, mencari konten /proc/<PID>/cmdlinedan memeriksa apakah dalam string yang ada my_execsebagai substring.

Perhatikan penggunaan truntuk mem-parsing konten cmdlineuntuk mengubah \0string -separated menjadi string yang dipisahkan oleh spasi.

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
Nisba
sumber