此处文档中的bash脚本未按预期运行

此处文档中的bash脚本未按预期运行,bash,Bash,下面是一个失败的最小测试用例 #!/bin/tcsh #here is some code in tcsh I did not write which spawns many processes. #let us pretend that it spawns 100 instances of stupid_test which the user kills #manually after an indeterminate period /bin/bash <<EOF #!/bin

下面是一个失败的最小测试用例

#!/bin/tcsh

#here is some code in tcsh I did not write which spawns many processes.
#let us pretend that it spawns 100 instances of stupid_test which the user kills
#manually after an indeterminate period

/bin/bash <<EOF
#!/bin/bash
while true
do
if [[ `ps -e | grep stupid_test | wc -l` -gt 0 ]]
then
  echo 'test program is still running'
  echo `ps -e | grep stupid_test | wc -l`
  sleep 10
else
  break
fi
done
EOF

echo 'test program finished'
预期的行为是运行,直到愚蠢的_测试被终止(在这种情况下,由用户手动),然后在接下来的十秒钟内终止。观察到的行为是,即使在程序被终止后,脚本也不会终止,并计算
ps-e | grep dumby|u test | wc-l
==1(并且它不再显示在ps下)

如果bash脚本直接运行,而不是在here文档中运行,则会恢复预期的行为


我觉得我做错了什么愚蠢的事,我根本不是最有经验的黑客。它为什么这样做?

通常,当您尝试
grep
进程名称时,会为
grep
本身获得额外的匹配行,例如:

$ ps xa | grep something
57386 s002  S+     0:00.01 grep something
因此,即使没有匹配过程,也会得到一条匹配行。您可以通过在管道中添加
grep-v grep
来解决此问题:

ps -e | grep stupid_test | grep -v grep | wc -l
正如所建议的,一个更好的修复方法是像这样编写
grep

ps -e | grep [s]tupid_test
模式的含义完全相同,但这样它将不再匹配
grep
本身,因为字符串
“grep[s]tupid\u test”
与正则表达式
/[s]tupid\u test/
不匹配

顺便说一句,我会像这样重写你的脚本,cleaner:

/bin/bash <<EOF
while :; do
  s=$(ps -e | grep [s]tupid_test)
  test "$s" || break
  echo test program is still running
  echo "$s"
  sleep 10
done
EOF

/bin/bash如果你想调用
bash
,那么你需要
/bin/bash,你也有一些野性。
pgrep对于这种情况是非常有用的工具。如果我使用
ps-x
,我观察到ps的行为,但是对于
ps-e
@aestrivex,你在哪种操作系统中?在Linux中可以
ps-e
也像你对我说的那样工作。在中间,如果不是行计数,就让它用<代码> PS-E.GRP-StudioTyTest打印匹配过程,然后您应该得到一些行,匹配过程将循环从退出作为进一步的优化,<代码> GRP'[StupIDyTest >避免首先匹配自身。
/bin/bash <<EOF
while :; do
  s=$(ps -e | grep [s]tupid_test)
  test "$s" || break
  echo test program is still running
  echo "$s"
  sleep 10
done
EOF
/bin/bash <<EOF
while ps -e | grep [s]tupid_test
do
  echo test program is still running
  sleep 10
done
EOF