bash 计算包含错误文本的响应的脚本 - 命令未执行
bash script to count responses containing error text - command not executed
我需要请求一个页面 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$
您在 if
后使用双圆括号的语法很奇怪。无论如何,检查是否成功的正确惯用方法是
if curl http://www.example.com/example/path | grep -iq error; then
检查 curl
的成功或失败会更稳健,但如果网站总是 returns 一个 200 结果代码,你就不能这样做(也许改变网站以便出现问题时如实报告4xx或5xx HTTP错误代码?)
作为文体评论,您应该为自己的变量使用小写字母,并且 counter
循环会比 for
循环更优雅。
iterations=10000
for ((counter = 0; counter < iterations; ++counter)); do
行尾的分号是多余的;您需要在语句之间使用语句分隔符,但换行符也是有效的语句分隔符。
要获得一些解决方案:
OP 的问题是,尽管问题中包含多行代码,但代码仍作为 单 行执行。
多个命令甚至单个控制流语句的组件称为复合命令 [=121] =];例如,if
,当 放在 单行 行时 必须 由 [= 分隔15=] 个实例,而换行符会自动分隔语句。
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
调试您的命令以查看是否所有部分都在执行。
- 当 post 在问题中输入代码时,post 它完全以重现问题所需的形式出现。如果这种形式对于人眼来说太难解析,post 具有更好格式的 附加 版本(并明确它仅用于显示)。
- 一定要弄清楚你的代码是运行命令行还是来自脚本。
对 bash 代码有很好的文体建议;有一个值得添加:
在 bash 中,您可以使用算术计算递增变量 C 风格:
(( ++count_error )) # alternative to count_error=$(( count_error + 1 ))
三重状态:
I'm not familiar with CygWin but I would be vaguely surprised if it did the right thing without a shebang -- it's probably running Bash in POSIX mode, which means many of the Bashisms will be syntax errors, or just not behave like you want.
事实上(无论 bash 运行s 在 CygWin (Windows) 还是在 Unix 上:
语法方面,当bash时,除了进程替换(<(...)
)之外的所有bash主义仍然可用POSIX mode 中的 运行 秒;但是,行为 有许多细微的变化,因此最好明确控制给定脚本 运行 所处的模式。
当 bash 运行 是一个没有 shebang 行的可执行 shell 脚本时,它 运行 就像脚本有一个bash
shebang 行;换句话说:它在 POSIX 模式下 而不是 运行。
我需要请求一个页面 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$
您在 if
后使用双圆括号的语法很奇怪。无论如何,检查是否成功的正确惯用方法是
if curl http://www.example.com/example/path | grep -iq error; then
检查 curl
的成功或失败会更稳健,但如果网站总是 returns 一个 200 结果代码,你就不能这样做(也许改变网站以便出现问题时如实报告4xx或5xx HTTP错误代码?)
作为文体评论,您应该为自己的变量使用小写字母,并且 counter
循环会比 for
循环更优雅。
iterations=10000
for ((counter = 0; counter < iterations; ++counter)); do
行尾的分号是多余的;您需要在语句之间使用语句分隔符,但换行符也是有效的语句分隔符。
要获得一些解决方案:
OP 的问题是,尽管问题中包含多行代码,但代码仍作为 单 行执行。
多个命令甚至单个控制流语句的组件称为复合命令 [=121] =];例如,if
,当 放在 单行 行时 必须 由 [= 分隔15=] 个实例,而换行符会自动分隔语句。
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
调试您的命令以查看是否所有部分都在执行。 - 当 post 在问题中输入代码时,post 它完全以重现问题所需的形式出现。如果这种形式对于人眼来说太难解析,post 具有更好格式的 附加 版本(并明确它仅用于显示)。
- 一定要弄清楚你的代码是运行命令行还是来自脚本。
在 bash 中,您可以使用算术计算递增变量 C 风格:
(( ++count_error )) # alternative to count_error=$(( count_error + 1 ))
三重状态:
I'm not familiar with CygWin but I would be vaguely surprised if it did the right thing without a shebang -- it's probably running Bash in POSIX mode, which means many of the Bashisms will be syntax errors, or just not behave like you want.
事实上(无论 bash 运行s 在 CygWin (Windows) 还是在 Unix 上:
语法方面,当bash时,除了进程替换(
<(...)
)之外的所有bash主义仍然可用POSIX mode 中的 运行 秒;但是,行为 有许多细微的变化,因此最好明确控制给定脚本 运行 所处的模式。当 bash 运行 是一个没有 shebang 行的可执行 shell 脚本时,它 运行 就像脚本有一个
bash
shebang 行;换句话说:它在 POSIX 模式下 而不是 运行。