Linux Bash脚本错误地计算自身的实例
我已经创建了一个Linux Bash脚本错误地计算自身的实例,linux,bash,grep,ps,Linux,Bash,Grep,Ps,我已经创建了一个bash脚本,它统计自身启动的实例 在这里(在这个例子中,我展示的是实例,而不是用wc-l)计算它们): (当然,我的脚本名为count\u本身。sh) 执行时,我希望它返回两行,但它返回三行: root@myserver:/# ./count_itself.sh root 16225 0.0 0.0 12400 1176 pts/0 S+ 11:46 0:00 /bin/bash ./count_itself.sh root 16226 0
bash
脚本,它统计自身启动的实例
在这里(在这个例子中,我展示的是实例,而不是用wc-l
)计算它们):
(当然,我的脚本名为count\u本身。sh
)
执行时,我希望它返回两行,但它返回三行:
root@myserver:/# ./count_itself.sh
root 16225 0.0 0.0 12400 1176 pts/0 S+ 11:46 0:00 /bin/bash ./count_itself.sh
root 16226 0.0 0.0 12408 564 pts/0 S+ 11:46 0:00 /bin/bash ./count_itself.sh
root 16228 0.0 0.0 11740 932 pts/0 S+ 11:46 0:00 grep count_itself.sh
使用&
标志执行时(即在后台,手动执行ps-aux
位),它返回两个,这就是我想要的:
root@myserver:/# ./count_itself.sh &
[1] 16233
root@myserver:/# ps -aux | grep count_itself.sh
root 16233 0.0 0.0 12408 1380 pts/0 S 11:48 0:00 /bin/bash ./count_itself.sh
root 16240 0.0 0.0 11740 944 pts/0 S+ 11:48 0:00 grep --color=auto count_itself.sh
我的问题是:为什么脚本中执行的ps-aux
比预期多返回一行?
或者,换句话说,为什么在我的第一个示例中创建id为16226
的进程
编辑(大多数人似乎误解了我的问题):
我想知道为什么执行bash
会返回两个/bin/bash./count\u本身.sh的实例,而不是为什么它返回grep count\u本身.sh
编辑2:
当然,我正在寻找一种方法来避免这种行为,并让脚本只返回/bin/bash./count_本身.sh
一次。这是grep
对ps
输出的标准问题
一种解决方案是在字符周围添加一些方括号
nb=$(ps -aux | grep '[c]ount_itself.sh')
这意味着您的grep
实例本身不匹配,因为进程名称及其参数包含方括号,但它匹配的模式不匹配
正如注释中提到的,应该在变量周围使用双引号以保留空格
结果中出现两个相同shell实例的原因是命令替换在子shell中执行。有关仅显示父进程的详细信息,请参阅。进程替换要求父shell启动子shell,即在子shell中分叉并执行指定的命令。这是必需的,这样父shell就不会受到$(…)
中包含的脚本对环境(变量、当前工作目录、陷阱)所做的任何更改的影响
例如:
$ cat test.sh
#!/bin/bash
a=1
b="$(a=2; echo abc)"
echo "a=$a"
echo "b=$b"
$ ./test.sh
a=1 # Note that the variable 'a' preserved its value
b=abc
分叉的结果是,您看到了脚本的一个额外实例
我认为不可能从输出中可靠地消除这些不需要的进程,因为原则上,脚本可以合法地启动自身的另一个实例(将作为子进程运行),而您无法区分这两种情况
一种黑客解决方案是让脚本在调用时在指定位置(例如在/tmp/your_script\u name
中)创建一个PID文件,并在终止时将其删除。我建议下一种方法:
排除父进程为我的所有进程:
ps --pid $$ -N -a | grep count_itself.sh
这意味着显示所有父级不是我的命令(因此这不包括执行反句子的grep进程和fork进程)最终找到了一种方法,尽管这是一种丑陋的方法,部分灵感来自于他的链接中的问题@TomFenech:
执行:
root@myserver:/# ./count_itself.sh
17725 pts/1 S+ 0:00 \_ /bin/bash ./count_itself.sh
在bg中已运行一个的情况下执行:
root@myserver:/# ./count_itself.sh &
[1] 17733
root@myserver:/# ./count_itself.sh
17733 pts/1 S 0:00 \_ /bin/bash ./count_itself.sh
17739 pts/1 S+ 0:00 \_ /bin/bash ./count_itself.sh
解释(据我所知):
ps f
返回活动进程树
grep'[c]count\u本身.sh'
将上一个命令限制为仅显示count\u本身.sh的实例
返回
17808 pts/1 S+ 0:00 \_ /bin/bash ./count_itself.sh
17809 pts/1 S+ 0:00 \_ /bin/bash ./count_itself.sh
grep-v'\\\\\\\'
排除包含4个空格(相当于一个制表符)的行,然后排除对应于子流程的行
`ps-aux | grep count_本身。sh`
在子shell中执行,即在子进程中。因此,执行脚本的shell被分叉,子shell然后运行ps-aux | grep count_本身。sh
命令。我建议:nb=`ps-aux | grep[c]当你执行ps-aux | grep count_本身时。sh
你的grep像count_本身一样进行计数。你需要提高自己regex@Leon但是显示两次的行是/bin/bash./count_本身.sh
,而不是ps-aux | grep count_本身.sh
@Cyrus?这应该做什么?它返回相同的结果我编辑了我的问题,有没有办法让<代码> PS-AUX <代码>不返回子shell执行?编辑添加一个链接。它仍然回响两行,只有<代码> -PID $ $/COD>标志,如果我添加了<代码> -n>代码>标志,它什么也没回响。我在中间寻找一个结果:PI猜如果用<代码> -n>代码>标志是R。eturning nothing这是因为您是唯一正在运行的实例,如果您想计算自己,可以在结果中添加1。
root@myserver:/# ./count_itself.sh &
[1] 17733
root@myserver:/# ./count_itself.sh
17733 pts/1 S 0:00 \_ /bin/bash ./count_itself.sh
17739 pts/1 S+ 0:00 \_ /bin/bash ./count_itself.sh
17808 pts/1 S+ 0:00 \_ /bin/bash ./count_itself.sh
17809 pts/1 S+ 0:00 \_ /bin/bash ./count_itself.sh