bash脚本计算包含错误文本的响应 - 命令未执行

时间:2015-03-05 04:15:35

标签: bash if-statement syntax

我需要请求一个页面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子句未按预期执行

以下是修订版(基于triplee的评论):

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$

2 个答案:

答案 0 :(得分: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

行尾的分号是多余的;你需要语句之间的语句分隔符,但换行也是一个有效的语句分隔符。

答案 1 :(得分:2)

获得一些解决方案:

OP的问题在于,代码尽管在问题中有多行显示,但仍以行的形式执行。

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

bash中的if复合命令包含if / else形式的这些部分:

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

Compound Commands中搜索man bash了解完整故事。


在OP的情况下,;之前缺少else,导致else分支被解释为{{1}的一部分(已损坏)分支命令;例如:

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 从未被分配 这就是OP的情况(虽然我不清楚为什么他的输出没有包含语法错误信息)。


建议:

  • 在一行上放置多个命令会很快变得难以处理;考虑使用多行,最好是在脚本文件中。
  • 使用$i调试命令以查看是否正在执行所有部分。
  • 在问题中发布代码时,请将其完全以重现问题所需的格式发布。如果该表格太难以解析人眼,请发布更好格式的附加版本(并明确表示它仅用于显示)。
  • 请务必明确您的代码是在命令行上运行 还是从脚本运行。

tripleee's answer对bash代码有很好的风格建议;值得补充的是:

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

    set -x

tripleee声明:

  

我对CygWin并不熟悉,但是如果没有一个shebang它做了正确的事情我会感到有些惊讶 - 它可能在POSIX模式下运行Bash,这意味着许多Bashisms将是语法错误,或者只是表现得不像你想要的那样。

实际上(无论bash是在CygWin(Windows)还是在Unix上运行):

  • 语法,当bash在POSIX mode中运行时,除了进程替换((( ++count_error )) # alternative to count_error=$(( count_error + 1 )) )之外的所有bashisms仍然可用;但是,行为中有许多微妙的变化,因此它总是优先明确控制给定脚本运行的模式。

  • 当bash运行一个没有shebang行的可执行shell脚本时,它会运行它,好像脚本有一个<(...) shebang行;换句话说:它在POSIX模式下运行。