bash:将结果赋给变量时换行计数不同
假设我想看看一个程序已经运行了多少个副本。我可以这样做:bash:将结果赋给变量时换行计数不同,bash,shell,scripting,Bash,Shell,Scripting,假设我想看看一个程序已经运行了多少个副本。我可以这样做: ps ax | grep -c "$0" 该命令本身会产生预期的结果。但是,如果我尝试将输出分配给一个变量,它将递增1!无论我如何尝试: var=$(ps ax | grep "$0" | sed -n '$=') var=`ps ax | grep -c "$0"` 有人能告诉我捕获正确输出的正确方法吗 如果能知道为什么会发生这种情况,那也太好了 更新 在@fedorqui的第一次回复后,我意识到我还不够清楚。让我详细说明: 我在同
ps ax | grep -c "$0"
该命令本身会产生预期的结果。但是,如果我尝试将输出分配给一个变量,它将递增1!无论我如何尝试:
var=$(ps ax | grep "$0" | sed -n '$=')
var=`ps ax | grep -c "$0"`
有人能告诉我捕获正确输出的正确方法吗
如果能知道为什么会发生这种情况,那也太好了
更新
在@fedorqui的第一次回复后,我意识到我还不够清楚。让我详细说明:
我在同一个bash脚本中运行上述三个命令。当我运行第一个程序时,它打印出数字2:程序本身和grep进程,并将该程序作为参数。当我在变量赋值中运行这些相同的命令时,会存储数字3
请注意,我使用两种不同的方法计算行数,grep和sed。在这两种情况下,它们都返回3,而不是正确答案2
下面是一个要在test.sh文件中尝试的合并示例:
echo -n "without assignment: "
ps ax | grep -c "$0"
var=$(ps ax | grep "$0" | sed -n '$=')
echo "using sed method: $var"
var=`ps ax | grep -c "$0"`
echo "using grep method: $var"
我的debian box上的结果:
without assignment: 2
using sed method: 3
using grep method: 3
再次提出问题:为什么会发生这种情况,以及如何预防或解决
因为grep
进程本身由ps
返回
您可以选择以下任一选项:
“欺骗”grep
通过包围其中一个搜索使其自身不匹配
字符类[]
中的字符,它不会更改
功能:
或者,在这种情况下
管道连接到grep-v grep
,使流程不匹配:
var=$(ps ax | grep -v grep | grep "$0")
请看一个例子。这里我们有一个进程
sleep
:
$ sleep 20 &
[1] 5602
如果我们在ps
的输出中检查它,它会出现两次
$ ps -ef| grep sleep
me 5602 5433 0 09:49 pts/2 00:00:00 sleep 20
me 5607 5433 0 09:49 pts/2 00:00:00 grep --colour=auto sleep
因此,我们可以使用字符类:
$ ps -ef| grep [s]leep
me 5602 5433 0 09:49 pts/2 00:00:00 sleep 20
或grep退出grep流程:
$ ps -ef| grep sleep | grep -v grep
me 5602 5433 0 09:49 pts/2 00:00:00 sleep 20
- 命令替换本身在子shell中运行,因此这是一个
进程bash
- 您对
(bash
)的搜索,即$0
也会在当时的进程表中结束,因此这是另一个包含字符串grep-cbash
的进程(bash
)。请注意,这可能不会在运行时显示在进程表中,具体取决于系统的繁忙程度grep
- 您有两个(或任意两个)实际运行的
进程(会话)可能是其余的bash
ps ax | grep -c "[b]ash"
在执行命令替换时,它仍然会计算子shell:
var=$(ps ax | grep -c "[b]ash")
因此,您需要手动从该计数中删除一个
示例:
$ var=$(ps ax | grep -c "bash")
$ echo $var
4
$ var=$(ps ax | grep -c "[b]ash")
$ echo $var
3
您的命令也计算grep命令行
ps ax | grep -v grep | grep -c "$0"
应该从计数中省略grep如果$0是
grep
;-)我真的很欣赏这个全面的答案,但这不是解决办法。我在同一个bash脚本中运行所有3行。当我运行第一个程序时,它会输出2:正如你所说的程序本身和grep进程,并将该程序作为参数。当我将这些命令作为变量赋值运行时,数字3被存储。@blackSmith说得对!尽管我不认为这种情况会发生很多次,但由于grep
将只运行一小会儿,而不是我们通常使用ps
@EricJensen检查的长时间运行的进程,这是非常奇怪的。我用sleep 200&
检查了这个问题,并用代码检查sleep
而不是$0
,它总是返回2。介意提供更多细节吗?@fedorqui我刚刚更新了问题您是说使用var=''或var=$()运行另一个bash shell?因此,如果命令在脚本中运行,那么此时将有两个命令在运行?这可能是答案,但是我仍然需要一个搜索脚本本身运行实例的解决方案。还有比搜索0美元更好的主意吗?每次程序运行时,都需要确保上一个实例没有继续运行。@EricJensen在$(foobar)
中,命令foobar
在子shell中运行。。您可以通过$$
找到当前进程的PID,例如您的脚本。。另外,由于您的脚本将作为bash
的参数运行,您可能应该搜索脚本名称并与PPID和$$
组合以获得所需内容。对我来说,使用/script.sh
运行脚本可以解决问题。如果我使用bash script.sh
运行,它会得到一个额外的进程。另外,我想知道:为什么您想知道您的脚本有多少个实例正在运行?如果要避免并发,还有其他更安全的方法。例如,在启动时创建一个虚拟目录,以便另一个看到它的实例将确定脚本正在运行。完成后,删除dir。@fedorqui基本上就是锁文件的概念,对吗?也许我应该走那条路。我想看一些关于锁文件和过程监控的阅读材料。。。不是为了这个项目,只是为了general@triplee注意这不是重复的,请检查问题末尾给出的样本。问题在于,ps-ef | grep$0
返回的进程比var=$(ps-ef | grep$0)
少一个进程。在中有一个非常有趣的线程。我认为创建一个dir,作为一个原子操作,是最好的方法,但是在那里我看到了许多其他(也许更好)的解决方案。