Как получить идентификатор процесса из имени процесса?

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

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

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

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

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

#!/bin/sh

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

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

8 ответов


код 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 }' | head -1

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

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

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

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

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

ps -eo pid,comm | awk '/Skype$/  {print ; 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 Контроллер, вся команда будет помещена в $command хотя в нем есть место.

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

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


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

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

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

или

pgrep "^$"

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

pgrep ""

Вы можете сделать это в 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

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

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

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


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

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

= = = = = UPDATE ====

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

#!/bin/bash
ps aux | grep  | awk 'NR==1 {print }'

метод 1-Используйте awk

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

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

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

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

#!/bin/bash

ps -cx -o pid,command | {
    while read pid command
    do
        if [ "_$command" = "_" ]
        then
            # Do something with the pid
            echo Found: pid=$pid, command=$command
            break
        fi
    done
}

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

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