【问题标题】:bash script to count responses containing error text - command not executed用于计算包含错误文本的响应的 bash 脚本 - 命令未执行
【发布时间】:2015-03-05 04:15:34
【问题描述】:

我需要请求一个页面 n 次并计算返回的错误页面数

ITERATIONS=100000
COUNTER=0; 
COUNT_ERROR=0; 
COUNT_EXPECTED=0; 
while (( $COUNTER < $ITERATIONS )); do 
COUNTER=$((COUNTER + 1)); 
curl http://www.example.com/example/path | grep -cim1 error; 
if (( $? == 0 )); then 
COUNT_ERROR=$((COUNT_ERROR + 1)) 
else 
COUNT_EXPECTED=$((COUNT_EXPECTED + 1))
fi; 
sleep 0.1; 
done; 
echo COUNT_ERROR=$COUNT_ERROR COUNT_EXPECTED=$COUNT_EXPECTED

这个脚本正在返回

COUNT_ERROR=0 COUNT_EXPECTED=0

...所以 if 子句没有按预期执行

这是修订版(基于三元组的 cmets):

iterations=100000; count_error=0; count_expected=0; for ((counter = 0; counter < iterations; ++counter)); do if curl http://www.example.com/example/path | grep -iq error; then count_error=$((count_error + 1)) else count_expected=$((count_expected + 1)); fi; sleep 0.1; done; echo count_error=$count_error count_expected=$count_expected

但是输出仍然是

count_error=0 count_expected=0

注意:测试机器包括 Windows 7 w/CygWin 和 MBP OSX Yosemite

这是完整的输出:

bash-3.1$ iterations=10; count_error=0; count_expected=0; for ((counter = 0; counter < iterations; ++counter)); do if curl http://www.example.com/example/path
| grep -iq jetty; then count_error=$((count_error + 1)) else count_expected=$((count_expected + 1)); fi; sleep 0.1; done; echo count_error=$count_error count_e
xpected=$count_expected
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  114k  100  114k    0     0   431k      0 --:--:-- --:--:-- --:--:--  431k
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  114k  100  114k    0     0   666k      0 --:--:-- --:--:-- --:--:--  666k
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  114k  100  114k    0     0   735k      0 --:--:-- --:--:-- --:--:--  735k
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  114k  100  114k    0     0   490k      0 --:--:-- --:--:-- --:--:--  490k
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  114k  100  114k    0     0   408k      0 --:--:-- --:--:-- --:--:--  408k
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  114k  100  114k    0     0   735k      0 --:--:-- --:--:-- --:--:--  735k
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  114k  100  114k    0     0   735k      0 --:--:-- --:--:-- --:--:--  735k
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  114k  100  114k    0     0   565k      0 --:--:-- --:--:-- --:--:--  565k
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  114k  100  114k    0     0   432k      0 --:--:-- --:--:-- --:--:--  432k
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  114k  100  114k    0     0   925k      0 --:--:-- --:--:-- --:--:--  925k
count_error=0 count_expected=0
bash-3.1$

【问题讨论】:

  • 您的原始代码本身没有问题;您稍后发布的单行代码不应该工作,因为在 else 之前缺少 ;
  • 也许添加 set -x(和 curl -s 让它安静下来)并复制粘贴准确你运行的内容和它产生的输出。
  • 感谢 mklement0 在 else 修复之前丢失的 ;
  • 现在它正在工作,我发现高度非线性的响应曲线......大约 1 秒内迭代 10 次,但 100 次迭代不是 10 秒,更像是 20 秒,而 1000 次则不是100 秒,更像是 5 分钟
  • @BaltoStar:很高兴语法问题得到解决;我已经在答案中总结了结果;至于时间问题:我建议你做更多的调查,然后问一个单独的问题。

标签: bash if-statement syntax


【解决方案1】:

要获得一些解决方案:

OP 的问题是,尽管代码在问题中以多行表示,但仍作为 单行 行执行。

多个命令,甚至是 在 bash 中称为复合命令的单个控制流语句的组件;例如,if,当放在单行行上时,必须;实例分隔,而换行符会自动分隔语句。

bash 中的if 复合命令在其 if/else 形式中包含以下部分:

if [[ ... ]]; then ...;  else ...; fi  # Note the `;` chars. separating the components.

man bash 中搜索Compound Commands 以获取完整故事。


在 OP 的情况下,;else 之前丢失,导致else 分支被解释为if 分支命令的(损坏的)部分;例如:

$ if true; then echo TRUE else echo FALSE; fi  # note missing ';' before `else`
TRUE else echo FALSE

这里,缺少的; 导致整个else 分支被解释为echo 的附加参数。

在其他情况下,由于语法错误两个分支都不会执行:

$ if true; then i='TRUE'  else i='FALSE'; fi
-bash: else: command not found

在这里,整个命令中断,$i 从未被分配。
这就是 OP 的情况(尽管我不清楚他的输出为什么不包含语法错误消息)。


建议:

  • 在一行中放置多个命令会很快变得笨拙;考虑使用多行,最好在脚本文件中。
  • 使用set -x 调试您的命令以查看是否所有部分都在执行。
  • 在问题中发布代码时,准确地以重现问题所需的形式发布。如果该表单对于人眼来说太难解析,请发布格式更好的附加版本(并明确它只是为了显示)。
  • 请务必明确您的代码是在命令行上运行还是从脚本运行。

tripleee's answer 对 bash 代码有很好的文体建议;有一点值得补充:

  • 在 bash 中,您可以使用算术评估以 C 风格递增变量:

    (( ++count_error )) # alternative to count_error=$(( count_error + 1 ))
    

三人状态:

我不熟悉 CygWin,但如果它在没有 shebang 的情况下做正确的事情,我会感到有点惊讶——它可能在 POSIX 模式下运行 Bash,这意味着许多 Bashism 将是语法错误,或者只是不正常如你所愿。

事实上(不管 bash 是在 CygWin (Windows) 还是在 Unix 上运行):

  • 语法方面,当 bash 在 POSIX mode 中运行时,除了进程替换 (&lt;(...)) 之外的所有 bashism 仍然可用;但是,行为有许多细微的变化,因此最好明确控制给定脚本运行的模式。

  • 当 bash 运行没有 shebang 行的可执行 shell 脚本时,它会像脚本有 bash shebang 行一样运行它;换句话说:它确实在 POSIX 模式下运行。

【讨论】:

  • 请注意,Windows7 CygWin bash 无法识别 ((counter++)) 语法,但 MSYS2 bash 可以
  • @BaltoStar:有趣;我在 bash 4.1.10 附带的 CygWin 安装中没有看到它 - 你有什么版本?
【解决方案2】:

if 后面带有双圆括号的语法很奇怪。无论如何,检查成功的正确惯用方法是

if curl http://www.example.com/example/path | grep -iq error; then 

检查curl 的成功或失败会更可靠,但如果网站总是返回 200 结果代码,则不能这样做(可能更改网站,使其如实报告 4xx 或 5xx HTTP那么出现问题时的错误码呢?)

作为一种风格说明,您应该为自己的变量使用小写字母,counter 循环作为for 循环会更优雅。

iterations=10000
for ((counter = 0; counter < iterations; ++counter)); do

行尾的分号是多余的;您需要在语句之间使用语句分隔符,但换行符也是有效的语句分隔符。

【讨论】:

  • 感谢 Tripleee,我做了您建议的惯用语和风格更改,但我的输出仍然是 count_error=0 count_response=0
  • Works for me 在这里。你是如何运行脚本的?是否有有效的shebang line
  • 我在 Windows 7 上的 CygWin bash 上运行 - 我还需要 shebang 吗?
  • 我在 if/else 中添加了 echo,输出显示两个子句都没有被执行
  • 听起来像是更基本的东西。我对 CygWin 不熟悉,但如果它在没有 shebang 的情况下做正确的事情,我会感到惊讶——它可能在 POSIX 模式下运行 Bash,这意味着许多 Bashism 将是语法错误,或者只是不像你想要的那样表现.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
  • 2018-11-02
  • 2013-10-18
  • 2018-05-06
  • 2017-01-04
相关资源
最近更新 更多