Как получить идентификатор процесса из имени процесса? - PullRequest
6 голосов
/ 23 февраля 2012

Я пытаюсь создать сценарий оболочки, получающий идентификатор процесса приложения Skype на моем Mac.

ps -clx |grep 'скайп' |awk '{print $ 2}' |head -1

Выше работает нормально, но есть две проблемы:

1) Команда grep получит всепроцесс, если их имя просто содержит «Skype».Как я могу гарантировать, что он получит только результат, если имя процесса точно Skype ?

2) Я хотел бы сделать из этого сценарий оболочки,который может использоваться из терминала, но имя процесса должно быть аргументом этого скрипта:

#!/bin/sh

ps -clx | grep '$1' | awk '{print $2}' | head -1

Это ничего не возвращает.Я думаю, это потому, что $ 2 в awk также рассматривается как аргумент.Как я могу решить это?

Ответы [ 8 ]

14 голосов
/ 23 февраля 2012

Ваш ps -cl1 вывод выглядит так:

  UID   PID  PPID        F CPU PRI NI       SZ    RSS WCHAN     S             ADDR TTY           TIME CMD
  501   185   172      104   0  31  0  2453272   1728 -      S    ffffff80145c5ec0 ??         0:00.00 httpd
  501   303     1 80004004   0  31  0  2456440   1656 -      Ss   ffffff8015131300 ??         0:11.78 launchd
  501   307   303     4004   0  33  0  2453456   7640 -      S    ffffff8015130a80 ??         0:46.17 distnoted
  501   323   303 40004004   0  33  0  2480640   9156 -      S    ffffff80145c4dc0 ??         0:03.29 UserEventAgent

Таким образом, последняя запись в каждой строке - ваша команда. Это означает, что вы можете использовать всю мощь регулярных выражений, чтобы помочь вам.

В регулярном выражении $ означает конец строки, поэтому вы можете использовать $, чтобы указать, что выходные данные должны содержать не только Skype, но и Skype. Это означает, что если у вас есть команда с именем Skype Controller, вы ее не подтянете:

ps -clx | grep 'Skype$' | awk '{print $2}' | head -1

Вы также можете упростить вещи, используя формат ps -o, чтобы просто выбрать нужные столбцы:

ps -eo pid,comm | grep 'Skype$' | awk '{print $1}' | head -1

И вы можете устранить head, просто используя способность awk, чтобы выбрать свою линию для вас. В awk, NR - ваш номер записи. Таким образом, вы можете сделать это:

ps -eo pid,comm | grep 'Skype$' | awk 'NR == 1 {print $1}'

Черт возьми, теперь, когда я думаю об этом, мы можем исключить и grep:

ps -eo pid,comm | awk '/Skype$/  {print $1; exit}'

Это использование способности awk использовать регулярные выражения. Если строка содержит регулярное выражение «Skype $», будет напечатан первый столбец, а затем завершено

Единственная проблема в том, что если у вас была команда Foo Skype, она также подхватит ее. Чтобы устранить это, вам придется сделать немного более сложную работу ногой:

ps -eo pid,comm | while read pid command
do
    if [[ "$command" = "Skype" ]]
    then
        echo $pid
        break
    fi
done

while read читает две переменные. Хитрость в том, что read использует пробел для разделения переменных, которые он читает. Однако, поскольку есть только две переменные, последняя будет содержать остальную часть всей строки. Таким образом, если команда Skype Controller , вся команда будет помещена в $command, даже если в ней есть пробел.

Теперь нам не нужно использовать регулярное выражение. Мы можем сравнить команду с равенством.

Это больше для ввода, но на самом деле вы используете меньше команд и меньше трубопроводов. Помните, awk проходит через каждую строку. Все, что вы делаете здесь, делает это более явным. В конце концов, это на самом деле намного эффективнее того, что было у вас изначально.

1 голос
/ 24 февраля 2012

Метод 1 - Использование awk

Я не вижу причин использовать флаг -l (длинный формат), я также не вижу причин использовать grep и awk одновременно: в awk встроена возможность grep. Вот мой план : используйте ps и выведите только 2 столбца: pid и command, затем используйте awk, чтобы выбрать то, что вы хотите:

ps -cx -o pid,command | awk '$2 == "Skype" { print $1 }'

Метод 2 - Используйте bash

Преимущество этого метода в том, что если вы уже пишете в bash, вам даже не нужен awk, который сохраняет один процесс. Решение дольше, чем другой метод, но очень прямолинейно.

#!/bin/bash

ps -cx -o pid,command | {
    while read pid command
    do
        if [ "_$command" = "_$1" ]
        then
            # Do something with the pid
            echo Found: pid=$pid, command=$command
            break
        fi
    done
}
1 голос
/ 23 февраля 2012

Вы можете отформатировать вывод ps, используя -o [field], ... и список по имени процесса, используя -C [имя_команды], однако ps все равно напечатает заголовок столбца, который можно удалить, отправив его по трубопроводу через grep -v PID

ps -o pid -C "$1" |grep -v PID

где $ 1 будет именем команды (в данном случае Skype)

1 голос
/ 23 февраля 2012

Вы можете сделать это в AppleScript:

tell application "System Events"
    set skypeProcess to the process "Skype"
    set pid to the unix id of skypeProcess
    pid
end tell

, что означает, что вы можете использовать 'osascript' для получения PID из сценария оболочки:

$ osascript -e "tell application \"System Events\"" -e "set skypeProcess to the process \"Skype\"" -e "set pid to the unix id of skypeProcess" -e "pid" -e "end tell"
3873
1 голос
/ 23 февраля 2012

Я бы так что-то вроде:

ps aux | grep Skype | awk 'NR==1 {print $2}'

==== ОБНОВЛЕНИЕ ====

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

#!/bin/bash
ps aux | grep $1 | awk 'NR==1 {print $2}'
1 голос
/ 23 февраля 2012

Проблема с вашим вторым примером заключается в том, что $ 1 заключен в одинарные кавычки, что не позволяет bash расширять переменную.Уже есть утилита, которая выполняет то, что вы хотите, не анализируя вывод ps вручную.

pgrep "$1"
1 голос
/ 23 февраля 2012

Если на Mac доступно pgrep, вы можете использовать pgrep '^Skype$'.Это перечислит идентификатор процесса всех процессов с именем Skype.

. Вы использовали неверные кавычки в вашем скрипте:

ps -clx | grep "$1" | awk '{print $2}' | head -1

или

pgrep "^$1$"
0 голосов
/ 23 февраля 2012

Используйте двойные кавычки, чтобы позволить bash выполнить подстановку переменных.Одинарные кавычки отключают механизм подстановки переменных bash.

ps -clx | grep "$1" | awk "{print $2}" | head -1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...