1

Я хочу найти PID всех процессов, которые были запущены вызовом cmdline, который содержит определенную строку my_exec .

Например, в macOS или Ubuntu откройте терминал и запустите /bin/bash , а затем в другом терминале введите ps all | grep '/bin/bash' . Вам будет предложено что-то вроде этого

  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

Второй столбец - это PID, поэтому я смогу поиграть в него с помощью sed.

В Ubuntu формат вывода ps all немного отличается, поэтому нужно использовать разные вызовы sed, в любом случае это легко сделать.

Проблема в том, что среди различных дистрибутивов Linux формат вывода ps может быть совершенно разным. Например, это случай Alpine Linux, для которого я даже не могу получить столбец, содержащий cmdline.

Что я могу сделать, чтобы иметь переносимый код? Может быть, вручную проверять файлы /proc/<PID>/cmdline (возможно, здесь есть проблема с разрешениями)?

Это мой код, пожалуйста, помогите мне для остальной части.

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

2 ответа2

2

Я считаю, что проблема в том, что вы используете переключатель "все" - если вы используете

Если версия PS поддерживает это (busybox нет), используя

 ps -o pid,command 

может быть самым простым способом получить определенный и простой для передачи вывод

Если вы используете

ps w

Это будет совместимо со встроенными системами, которые также используют Busybox, но с меньшей функциональностью.

0

Я получил этот код, в основном он рассматривает все процессы в /proc/ , ищет содержимое /proc/<PID>/cmdline и проверяет, есть ли в этой строке my_exec качестве подстроки.

Обратите внимание на использование tr для синтаксического анализа содержимого cmdline для преобразования \0 -разделенной строки в строку, разделенную пробелом.

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .