如何从进程名称获取进程ID?

问题描述 投票:6回答:9

我正在尝试创建一个外壳脚本,在我的Mac上获取Skype应用程序的进程ID

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

上面的方法工作正常,但是有两个问题:

1)如果grep名称仅包含“ Skype”,则将获得所有进程。如果进程名称恰好是Skype,我如何确保仅得到结果?

2)我想从中制作一个shell脚本,可以在终端上使用它,但是进程名应该是该脚本的参数:

#!/bin/sh

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

这不返回任何东西。我认为这是因为awk中的$ 2也被视为一个参数。我该如何解决?

macos bash awk grep
9个回答
14
投票

您的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
投票

如果pgrep在Mac上可用,则可以使用pgrep '^Skype$'。这将列出所有名为Skype的进程的进程ID。


1
投票

第二个示例的问题是$ 1用单引号引起来,这防止bash扩展变量。已经有一个无需手动解析ps输出即可完成所需功能的实用程序。


1
投票

您可以在AppleScript中执行此操作:


1
投票

您可以使用-o [field]来格式化ps的输出,...,并使用-C [command_name]来按进程名称列出;但是,ps仍将打印列标题,可以通过将其通过管道传递来删除grep -v PID


1
投票

我会这样:


1
投票

方法1-使用awk


0
投票

使用双引号允许bash执行变量替换。单引号禁用bash变量替换机制。


0
投票

pgrep myAwesomeAppName

© www.soinside.com 2019 - 2024. All rights reserved.