在bash
中,仅使用您问题中列出的基本工具(1),您应该能够做到:
kill $(ps aux | grep '[p]ython csp_build.py' | awk '{print $2}')
以下是其工作原理的详细信息:
ps
命令可以列出所有进程的列表。
grep
命令可以基于搜索字符串对其进行筛选,[p]
是一个技巧,用于防止选择实际的 grep
进程本身。
awk
命令只会给出每行的第二个字段,即 PID。
$(x)
结构表示要执行 x
然后取其输出并将其放在命令行上。上面的管道内的 ps
的输出结果是进程 ID 列表,因此最终得到类似于 kill 1234 1122 7654
的命令。
下面是其实际操作的示例:
pax> sleep 3600 &
[1] 2225
pax> sleep 3600 &
[2] 2226
pax> sleep 3600 &
[3] 2227
pax> sleep 3600 &
[4] 2228
pax> sleep 3600 &
[5] 2229
pax> kill $(ps aux | grep '[s]leep' | awk '{print $2}')
[5]+ Terminated sleep 3600
[1] Terminated sleep 3600
[2] Terminated sleep 3600
[3]- Terminated sleep 3600
[4]+ Terminated sleep 3600
并且您可以看到它终止了所有的睡眠进程。
更详细地解释一下
grep '[p]ython csp_build.py'
的含义:当您执行
sleep 3600&
后跟
ps -ef | grep sleep
,您往往会得到
两个带有
sleep
的进程,即
sleep 3600
和
grep sleep
(因为它们都包含
sleep
这个单词,这不是什么难事)。
然而,ps -ef | grep '[s]leep'
将不会创建一个带有sleep
的grep
进程,而是创建一个带有命令grep '[s]leep'
的进程,这是一个棘手的问题:grep
找不到它,因为它正在寻找正则表达式“字符类[s]
中的任何字符(基本上只有s
)后跟leep
”。
换句话说,它正在寻找sleep
,但grep
进程是grep '[s]leep'
,它没有该文本sleep
。
当我被某个SO上的人展示了这种方法之后,我立刻开始使用它,因为
- 它比添加
| grep -v grep
少了一个进程; - 它既优雅又狡猾,这是一种罕见的组合:-)
(1)如果您
不限于使用这些基本工具,则有一个巧妙的
pgrep
命令,它可以根据某些标准查找进程(当然,假设您的系统可用)。
例如,您可以使用pgrep sleep
输出所有sleep
命令的进程ID(默认情况下,它匹配进程名称)。如果您想像ps
中显示的那样匹配整个命令行,则可以执行类似于pgrep -f 'sleep 9999'
的操作。
顺便说一下,如果您执行pgrep pgrep
,它不会列出自身,因此在这种情况下不需要使用上面显示的棘手过滤器方法。
您可以使用-a
来显示完整的进程名称检查您感兴趣的进程是否正确。您还可以使用-u
或-U
将范围限制为自己的进程(或特定的一组用户)。有关更多选项,请参阅pgrep
/pkill
的man
页面。
一旦您确信它只会显示您感兴趣的进程,则可以使用相同的参数使用pkill
向所有这些进程发送信号。