更优雅的“ps aux | grep -v grep”
Posted
技术标签:
【中文标题】更优雅的“ps aux | grep -v grep”【英文标题】:More elegant "ps aux | grep -v grep" 【发布时间】:2012-03-11 15:42:14 【问题描述】:当我检查进程列表并“grep”出那些我感兴趣的进程时,grep
本身也包含在结果中。例如,列出终端:
$ ps aux | grep terminal
user 2064 0.0 0.6 181452 26460 ? Sl Feb13 5:41 gnome-terminal --working-directory=..
user 2979 0.0 0.0 4192 796 pts/3 S+ 11:07 0:00 grep --color=auto terminal
通常我使用ps aux | grep something | grep -v grep
来删除最后一个条目...但它不是优雅 :)
你有没有更优雅的 hack 来解决这个问题(除了将所有命令包装到一个单独的脚本中,这也不错)
【问题讨论】:
不管怎样,这是一个古老的常见问题解答。请参阅faqs.org/faqs/unix-faq/faq/part3 上的第 3.10 项 感谢您的参考。这就是他们的方法:ps ux | awk '/name/ && !/awk/ print $2'
grep -v grep
部分在做什么?
@Jwan622 grep -v grep
从 grep 结果中排除 grep
。如果 grep 与 ps 结合使用,那么也会显示 grep 进程(带有 grep 参数),从而使结果混乱。 grep -v grep 是避免这种情况的常用方法
【参考方案1】:
根据最终用例,您通常更喜欢 Awk。
ps aux | awk '/[t]erminal/'
当你有类似的东西时尤其如此
ps aux | grep '[t]erminal' | awk 'print $1' # useless use of grep!
显然,正则表达式可以很容易地融入到 Awk 脚本中:
ps aux | awk '/[t]erminal/ print $1 '
但是说真的,不要自己重新发明它。 pgrep
和朋友们已经存在很长时间了,并且比大多数临时重新实现更好地处理整个问题空间。
【讨论】:
【参考方案2】:此答案基于之前的 pgrep
answer。它还建立在另一个answer 的基础上,结合了ps
和pgrep
的使用。以下是一些相关的训练示例:
$ pgrep -lf sshd
1902 sshd
$ pgrep -f sshd
1902
$ ps up $(pgrep -f sshd)
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1902 0.0 0.1 82560 3580 ? Ss Oct20 0:00 /usr/sbin/sshd -D
$ ps up $(pgrep -f sshddd)
error: list of process IDs must follow p
[stderr output truncated]
$ ps up $(pgrep -f sshddd) 2>&-
[no output]
以上可以作为函数使用:
$ psgrep() ps up $(pgrep -f $@) 2>&-;
$ psgrep sshd
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1902 0.0 0.1 82560 3580 ? Ss Oct20 0:00 /usr/sbin/sshd -D
将ps
与grep
进行比较。有用的标题行没有打印出来:
$ ps aux | grep [s]shd
root 1902 0.0 0.1 82560 3580 ? Ss Oct20 0:00 /usr/sbin/sshd -D
【讨论】:
见github.com/blueyed/oh-my-zsh/blob/…(但它是Zsh特有的)。 @blueyed,我已经用 bash 函数定义更新了答案。 还要注意-d
选项来指定分隔符;例如ps -fp$(pgrep -d , getty)
我用这个:ps uxp `pgrep <process>`
注意p
必须是最后一个参数(即pux
不起作用)
这不会像grep
那样为搜索进程名称着色【参考方案3】:
通常的技巧是这样的:
ps aux | egrep '[t]erminal'
这将匹配包含terminal
的行,而egrep '[t]erminal'
不匹配!它也适用于许多 Unix 风格。
【讨论】:
这适用于我的任意字符串,但不适用于用户名,例如ps aux | grep '[r]oot'
。有谁知道为什么?
@kxsong: | grep '[t]erminal'
选择任何包含“终端”一词的行,而不将“终端”一词放入进程列表。你想用| grep '[r]oot'
达到什么目的,它怎么不起作用?可能会有更好的解决方案。
如果我错了,请纠正我,但这也适用于 grepped 字符的任何位置:ps aux| grep "te[r]minal"
brilliant hack(我想我应该这么称呼它,因为 aux / grep 作者可能没有想到这种情况。)
@JamieJag:嗯...就像我在帖子中所说,grep '[t]erminal'
将匹配包含terminal
的行。 ps aux
的输出将有一行 grep '[t]erminal'
(带方括号),其中不包含字符串 terminal
(没有相同)。【参考方案4】:
免责声明:我是这个工具的作者,但是......
我会使用px:
~ $ px atom
PID COMMAND USERNAME CPU RAM COMMANDLINE
14321 crashpad_handler walles 0.01s 0% /Users/walles/Downloads/Atom.app/Contents/Frameworks/Electron Framework.framework/Resources/crashpad_handler --database=
16575 crashpad_handler walles 0.01s 0% /Users/walles/Downloads/Atom.app/Contents/Frameworks/Electron Framework.framework/Resources/crashpad_handler --database=
16573 Atom Helper walles 0.5s 0% /Users/walles/Downloads/Atom.app/Contents/Frameworks/Atom Helper.app/Contents/MacOS/Atom Helper --type=gpu-process --cha
16569 Atom walles 2.84s 1% /Users/walles/Downloads/Atom.app/Contents/MacOS/Atom --executed-from=/Users/walles/src/goworkspace/src/github.com/github
16591 Atom Helper walles 7.96s 2% /Users/walles/Downloads/Atom.app/Contents/Frameworks/Atom Helper.app/Contents/MacOS/Atom Helper --type=renderer --no-san
除了使用合理的命令行界面查找进程外,它还可以做很多其他有用的事情,更多详细信息请参见the project page。
适用于 Linux 和 OS X,易于安装:
curl -Ls https://github.com/walles/px/raw/python/install.sh | bash
【讨论】:
这太棒了!! 谢谢斯特凡 :)【参考方案5】:另一个选项是编辑您的.bash_profile
(或您保留 bash 别名的其他文件)以创建一个从结果中 grep 'grep' 的函数。
function mygrep
grep -v grep | grep --color=auto $1
alias grep='mygrep'
grep -v grep
必须放在首位,否则您的 --color=auto
将因某种原因无法工作。
如果您使用的是 bash,则此方法有效;如果您使用的是不同的外壳 YMMV。
【讨论】:
别名和的功能是什么?只需执行function grep command grep -v grep | command grep --color=auto "$@";
(还要注意参数和引用的修复)。但是,这被破坏了,因为任何非ps
调用grep
将不再起作用(参数传递不正确)。无论如何,一个更有用的功能是修改正则表达式以使其不匹配自身,而不是从grep
结果中单独过滤掉grep
。当然,为几十年前已充分解决的问题发明新的解决方案并不是很有成效。【参考方案6】:
使用pgrep。它更可靠。
【讨论】:
pgrep
如果我寻找例如ps aux | grep 'ssh options'
将无法工作
Jakub M.:pgrep -f
呢?
@jakub-m 默认情况下,pgrep
仅将模式与进程名称匹配。要匹配整个命令,请使用 -f
标志。
pgrep
只返回进程 ID。
旧版本采用pgrep -fl
(但如果没有-f
匹配完整的cmdline,则无法看到完整的cmdline,详细信息:serverfault.com/a/619788/44183)。但是,如果您需要 pid、cmdline 之外的任何其他信息,则需要 ps
。可以将它们组合起来:ps -p $(pgrep -f foo)
【参考方案7】:
可以在ps命令中进行过滤,例如
ps u -C gnome-terminal
(或使用 find 等搜索 /proc)
【讨论】:
请注意,这适用于 GNU 的 ps (Linux),但不适用于 BSD ps。 即使使用 GNU ps 也是不正确的。ps -C <command>
将匹配确切的命令。当与a
或x
选项一起使用时,它将报告所有进程,因为a
和x
列出进程除了通过其他方式匹配的进程集。
@Animism True。谢谢,我修好了。
这只有在进程名称被准确指定的情况下才有效。它不适用于部分匹配,例如logind
用于systemd-logind
,或匹配参数。【参考方案8】:
使用方括号将搜索模式中的字符括起来会排除grep
进程,因为它不包含匹配的正则表达式。
$ ps ax | grep 'syslogd'
16 ?? Ss 0:09.43 /usr/sbin/syslogd
18108 s001 S+ 0:00.00 grep syslogd
$ ps ax | grep '[s]yslogd'
16 ?? Ss 0:09.43 /usr/sbin/syslogd
$ ps ax | grep '[s]yslogd|grep'
16 ?? Ss 0:09.43 /usr/sbin/syslogd
18144 s001 S+ 0:00.00 grep [s]yslogd|grep
【讨论】:
【参考方案9】:还有一个alternative:
ps -fC terminal
这里有选项:
-f does full-format listing. This option can be combined
with many other UNIX-style options to add additional
columns. It also causes the command arguments to be
printed. When used with -L, the NLWP (number of
threads) and LWP (thread ID) columns will be added. See
the c option, the format keyword args, and the format
keyword comm.
-C cmdlist Select by command name.
This selects the processes whose executable name is
given in cmdlist.
【讨论】:
一个小缺点,与 OP 的问题无关,它不会向您显示 Tomcat 之类的东西,它实际上是作为带有大量参数的 java 运行的。-C
选项已在@Andreas Frishe 一年半前发布的答案中提出......以上是关于更优雅的“ps aux | grep -v grep”的主要内容,如果未能解决你的问题,请参考以下文章