bash 如何从进程名称中获取进程ID?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9415740/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get process id from process name?
提问by dhrm
I'm trying to create a shell script getting the process idof the Skype app on my Mac.
我正在尝试创建一个 shell 脚本来获取Mac 上 Skype 应用程序的进程 ID。
ps -clx | grep 'Skype' | awk '{print $2}' | head -1
ps -clx | grep 'Skype' | awk '{print $2}' | 头-1
The above is working fine, but there are two problems:
以上工作正常,但有两个问题:
1)The grepcommand would get all process if their name just contains "Skype". How can I ensure that it only get the result, if the process name is exactly Skype?
1)如果名称只包含“Skype” ,grep命令将获取所有进程。如果进程名称正好是Skype,我如何确保它只得到结果?
2)I would like to make a shell script from this, which can be used from the terminal but the process name should be an argument of this script:
2)我想从中制作一个shell脚本,它可以从终端使用,但进程名称应该是这个脚本的参数:
#!/bin/sh
ps -clx | grep '' | awk '{print }' | head -1
This isn't returning anything. I think this is because the $2in the awk is treated as an argument too. How can I solve this?
这不会返回任何东西。我认为这是因为awk 中的$2也被视为参数。我该如何解决这个问题?
回答by David W.
Your ps -cl1output looks like this:
您的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
Thus, the last entry in each line is your command. That means you can use the full power of regular expressions to help you.
因此,每行的最后一个条目是您的命令。这意味着您可以使用正则表达式的全部功能来帮助您。
The $in a regular expression means the end of the string, thus, you could use $to specify that not only does the output must have Skypein it, it must end with Skype. This means if you have a command called Skype Controller, you won't pull it up:
$正则表达式中的in 表示字符串的结尾,因此,您可以使用$来指定不仅输出必须包含Skype在其中,而且必须以Skype. 这意味着如果您有一个名为 的命令Skype Controller,则不会将其拉起:
ps -clx | grep 'Skype$' | awk '{print }' | head -1
You can also simplify things by using the ps -oformat to just pull up the columns you want:
您还可以通过使用ps -o格式来提取您想要的列来简化事情:
ps -eo pid,comm | grep 'Skype$' | awk '{print }' | head -1
And, you can eliminate headby simply using awk's ability to select your line for you. In awk, NRis your record number. Thus you could do this:
而且,您可以head通过简单地使用awk的功能为您选择线路来消除。在awk,NR是您的记录编号。因此你可以这样做:
ps -eo pid,comm | grep 'Skype$' | awk 'NR == 1 {print }'
Heck, now that I think of it, we could eliminate the greptoo:
哎呀,现在我想到了,我们也可以消除grep:
ps -eo pid,comm | awk '/Skype$/ {print ; exit}'
This is using awk's ability to use regular expressions. If the line contains the regular expression, 'Skype$', it will print the first column, then exit
这是利用 awk 使用正则表达式的能力。如果该行包含正则表达式 'Skype$',它将打印第一列,然后退出
The only problem is that if you had a command Foo Skype, this will also pick it up. To eliminate that, you'll have to do a bit more fancy footwork:
唯一的问题是,如果你有一个 command Foo Skype,这也会把它捡起来。为了消除这种情况,你必须做一些更花哨的步法:
ps -eo pid,comm | while read pid command
do
if [[ "$command" = "Skype" ]]
then
echo $pid
break
fi
done
The while readis reading two variables. The trick is that readuses white space to divide the variables it reads in. However, since there are only two variables, the last one will contain the rest of the entire line. Thus if the command is Skype Controller, the entire command will be put into $commandeven though there's a space in it.
该while read是读书的两个变量。诀窍是read使用空格来划分它读入的变量。然而,由于只有两个变量,最后一个将包含整行的其余部分。因此,如果命令是Skype Controller,$command即使其中有空格,整个命令也会被放入。
Now, we don't have to use a regular expression. We can compare the command with an equality.
现在,我们不必使用正则表达式。我们可以将命令与等式进行比较。
This is longer to type in, but you're actually using fewer commands and less piping. Remember awkis looping through each line. All you're doing here is making it more explicit. In the end, this is actually much more efficient that what you originally had.
输入的时间更长,但实际上您使用的命令和管道更少。记住awk是循环遍历每一行。你在这里所做的只是让它更明确。最后,这实际上比您最初拥有的效率高得多。
回答by Sven Marnach
If pgrepis available on Mac, you can use pgrep '^Skype$'. This will list the process id of all processes called Skype.
如果pgrep在 Mac 上可用,您可以使用pgrep '^Skype$'. 这将列出所有调用的进程的进程 ID Skype。
You used the wrong quotes in your script:
您在脚本中使用了错误的引号:
ps -clx | grep "" | awk '{print }' | head -1
or
或者
pgrep "^$"
回答by jordanm
The problem with your second example is that the $1 is in single quotes, which prevents bash from expanding the variable. There is already a utility that accomplishes what you want without manually parsing ps output.
你的第二个例子的问题是 $1 是单引号,这会阻止 bash 扩展变量。已经有一个实用程序可以在不手动解析 ps 输出的情况下完成您想要的操作。
pgrep ""
回答by Hai Vu
Method 1 - Use awk
方法 1 - 使用 awk
I don't see any reason to use the -l flag (long format), I also don't see any reason to use grep and awk at the same time: awk has grep capability built in. Here is my plan: use ps and output just 2 columns: pid and command, then use awk to pick out what you want:
我看不出有任何理由使用 -l 标志(长格式),我也看不出有任何理由同时使用 grep 和 awk:awk 内置了 grep 功能。这是我的计划:使用 ps并只输出 2 列:pid 和 command,然后使用 awk 来挑选你想要的:
ps -cx -o pid,command | awk ' == "Skype" { print }'
Method 2 - Use bash
方法 2 - 使用 bash
This method has the advantage that if you already script in bash, you don't even need awk, which save one process. The solution is longer than the other method, but very straight forward.
这种方法的好处是,如果你已经在 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
}
回答by Mr_Nizzle
I'd so something like:
我会这样:
ps aux | grep Skype | awk 'NR==1 {print }'
==== UPDATE ====
==== 更新 ====
Use the parameter without quotes and use single quotes for awk
使用不带引号的参数并使用单引号 awk
#!/bin/bash
ps aux | grep | awk 'NR==1 {print }'
回答by Mr_Nizzle
You can do this in AppleScript:
您可以在 AppleScript 中执行此操作:
tell application "System Events"
set skypeProcess to the process "Skype"
set pid to the unix id of skypeProcess
pid
end tell
which means you can use 'osascript' to get the PID from within a shell script:
这意味着您可以使用 '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
回答by technosaurus
You can format the output of ps using the -o [field],... and list by process name using -C [command_name] ;however, ps will still print the column header, which can be removed by piping it through grep -v PID
您可以使用 -o [field],... 格式化 ps 的输出,并使用 -C [command_name] 按进程名称列出;但是, ps 仍会打印列标题,可以通过 grep 管道将其删除 - PID
ps -o pid -C "" |grep -v PID
where $1 would be the command name (in this case Skype)
其中 $1 将是命令名称(在本例中为 Skype)
回答by Alex Zavatone
pgrep myAwesomeAppName
pgrep myAwesomeAppName
This works great under Catalina 10.15.2
这在 Catalina 10.15.2 下效果很好
回答by dweeves
Use double quotes to allow bash to perform variable substitution. Single quotes disable bash variable substitution mechanism.
使用双引号允许 bash 执行变量替换。单引号禁用 bash 变量替换机制。
ps -clx | grep "" | awk "{print }" | head -1

