如何从进程名称获取进程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
。在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控制器,则整个命令将被放入$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
}