grep - 在脚本中使用 pgrep 进行进程计数
问题描述
在我的 Raspbian 中,我使用了以下命令:
pgrep -c ^
我认为这个命令应该在不使用更习惯的方法的情况下对所有进程进行计数
ps -A --no-headers | wc -l
但是,当在脚本上运行 pgrep -c ^ 时(假设在登录时),我想将计数的正在运行的进程数减去 1,以便调用的 shell(比如“sh”)运行脚本(或脚本本身)不算作一个过程......我不知道你是否在关注我。然后我开始用 pgrep 命令做一些实验
这是我的脚本的一个例子:
#!/bin/sh
ps1=$(pgrep -c ^)
ps2=$(expr $(pgrep -c ^) - 1) # minus 1
ps3=$(expr $(pgrep -c ^) - 2) # minus 2
echo ${ps1}
echo ${ps2} # ps1 == ps2
echo ${ps3}
我得到了结果(就我而言):
112
112
111
a) 在脚本中,更改 ps1 和 ps2 的评估顺序没有任何区别。关键是 ps1 和 ps2 总是相等的(不知道为什么)。
b) 直接在提示符上输入相同的命令,如下所示:
$> pgrep -c ^; expr $(pgrep -c ^) - 1
显示(如预期):
111
110
c)但是如果我修改命令以使用 echo:
$> echo "$(pgrep -c ^) : $(expr $(pgrep -c ^) - 1)"
甚至改变评估顺序:
"$> echo "$(expr $(pgrep -c ^) - 1) : $(pgrep -c ^)"
在这两种情况下,就像在脚本中一样,我得到:
112 : 112
问题:
1)为什么在脚本/回显之外它按预期工作,但在脚本内部或内部和 echo/printf 值是相同的?
2)命令 pgrep -c ^ 是按我想做的那样计算正在运行的进程的正确命令吗?
谢谢
解决方案
这里的问题是您忽略了这样一个事实,即 shell 通过分叉自己来执行每个命令替换来创建一个单独的进程。
我承认贝壳的行为方式令人困惑。就像,以这个为例:
$ pstree $$
sh───pstree
$ echo $(pstree $$)
sh───pstree
尽管我在上面另有说明,但似乎sh
没有创建额外的进程来执行命令替换。但是,这是一种误解。它实际上是分叉的,但由于只有一个命令$()
,所以分叉的进程没有意义;pstree
所以它只是通过调用 exec* 系列的函数来替换自己;即它变成了pstree
。
如果在终止后还有另一个命令要执行pstree
,则分叉的进程必须保持活动状态。看:
$ echo $(pstree $$; :)
sh───sh───pstree
嵌套命令替换的扩展也可能令人困惑,所以让我们也澄清一下。
$ echo $(echo $(pstree $$))
sh───sh───pstree
对于上面的示例,由于每个命令替换仅包含一个命令,因此人们可能希望sh
在进程树中只看到一个命令;但这不是它的工作原理。包含在$()
其中的命令在为执行命令替换而创建的子 shell 中处理,而不是在父 shell 中处理。对于这种情况,这意味着;分叉的进程制作了自己的另一个副本,以便能够执行pstree
和收集其输出,然后执行echo
;即分叉的进程在运行时还活着,因此树中pstree
的额外进程。sh
因此,不要处理这些异常(以及我不知道或不记得的可能其他异常),而是依赖您的 shell 的进程分组机制。喜欢:
pgrep -c ^
pgrep -cvg $$
echo $(pgrep -cvg $$)
echo $(echo $(pgrep -cvg $$))
echo $(echo $(echo $(pgrep -cvg $$)))
对我来说,它输出:
264
263
263
263
263
推荐阅读
- android - 如何在左侧显示文本视图,在右侧显示图像视图?
- vim - Vim 8.0 之谜:`:au BufRead` 处理程序中的`:r!` 命令导致不必要的副作用
- visual-studio-code - 在 VSCode 中,如何从命令行打开文件并找到指定的文本?
- git - 如何计算每个用户在 github repo 中创建的代码行数
- java - jdbc中的ps.setAsciiStream()方法和ps.setCLob()方法有什么区别?
- javascript - 收集多个元素并在输入时触发点击哪个被选中
- frameworks - 在将 Identity server4 (ver 3.0.0) 令牌集成到 Microsoft.AspNet.WebApi (Framework 4.6.2) 时,此请求的授权被拒绝”
- flutter - flutter_webview_plugin:如何在默认浏览器中打开链接
- matillion - 是否可以从 Jython 脚本更新 Matillion Job DateTime 变量?
- python - 无法使用 pip 安装 pymunk