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

问题描述:

我试图创建一个shell脚本,在我的Mac上获取Skype应用程序的进程ID如何从进程名称获取进程ID?

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

以上工作正常,但有两个问题:

1)的grep命令会得到所有的过程,如果他们的名字只包含 “Skype的”。我如何确保它只能得到结果,如果进程名称正好是Skype

2) 我想使从该一个外壳脚本,其可以从终端但过程名中使用应该是这个脚本的参数:

#!/bin/sh 

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

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

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 

而且,您可以通过简单地使用awk为您选择线路的功能来消除head。在awkNR是你的记录号码。因此,你可以这样做:

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控制器,则整个命令将被放入$command,即使其中有空间。

现在,我们不必使用正则表达式。我们可以比较命令与平等。

输入的时间较长,但实际上使用的命令较少,管道较少。记住awk正在循环每一行。你在这里做的只是让它更加明确。最后,这实际上比你原来的效率高得多。

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

您使用了错误的报价在你的脚本:

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

pgrep "^$1$" 

与你的第二个例子中的问题是,$ 1是单引号,防止庆典从扩大变量。已经有一个实用程序可以在不手动解析ps输出的情况下完成你想要的任务。

pgrep "$1" 

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

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

我想这样是这样的:

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

==== ==== UPDATE

使用不带引号的参数,并使用单引号awk

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

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

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

这意味着你可以使用 'osascript' 从shell脚本中得到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 "$1" |grep -v PID 

除去其中$ 1人的命令名(在这种情况下的Skype)

方法1 - 使用AWK

我看不出有任何理由使用-l标志(长格式),我也看不出有任何理由使用grep和awk在同一时间:AWK具有内置的grep功能。这是我的计划:用ps输出仅有2列:PID和命令,然后用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 
}