我想写一个小的Bash函数,我可以将命令作为字符串和搜索针传递,如果命令的执行输出包含给定的搜索针,它应该打印一些“OKAY”,否则“ERROR”。
这就是我到目前为止所提出的:
red=`tput setaf 1`
green=`tput setaf 2`
reset=`tput sgr0`
function psa_test {
result=$($1 2>&1)
echo "Result: $result"
if [[ $result == *"$2"* ]]; then
echo "[${green} OK ${reset}] $3"
else
echo "[${red}ERROR${reset}] $3"
fi
echo " Command: '$1' | Needle: '$2' | Name: '$3'"
}
如果我像那样调用它
psa_test 'curl -v google.com' "HTTP 1.1" "Testing google.com"
效果很好:
# .. output
[ OK ] Testing google.com
Command: 'curl -v google.com' | Needle: 'HTTP 1.1' | Name: 'Testing google.com'
但是如果我的命令中有一些嵌入的字符串,它就不再起作用了,例如:
psa_test 'curl --noproxy "*" http://www1.in.example.com' "HALLO 1" "HTTP www1.in.example.com"
输出:
# Proxy answers with HTML error document ... <html></html> ... saying
# that it can't resolve the domain (which is correct as
# it is an internal domain). But anyway, the --noproxy "*" option
# should omit all proxies!
[ERROR] HTTP www1.in.example.com
Command: 'curl --noproxy "*" http://www1.in.example.com' | Needle: 'HALLO 1' | Name: 'HTTP www1.in.example.com'
请注意,如果我执行
curl --noproxy "*" http://www1.in.example.com
我的shell中的会忽略代理(我们想要的),而
curl --noproxy * http://www1.in.example.com
没有。
如果我尝试使用mysql -u ... -p ... -e "SELECT true"
测试MySQL数据库,我会遇到类似的行为。所以我猜这与报价有关。如果有人能给我一些改进这个功能的提示,我会很高兴的。谢谢!
答案 0 :(得分:2)
尝试将整个命令作为单个字符串提供需要以各种不方便的方式引用。我建议你尝试一种不需要的方法。
#!/bin/bash
red=`tput setaf 1`
green=`tput setaf 2`
reset=`tput sgr0`
psa_test()
{
local needle="$1"
local name="$2"
local -a command=("${@:3}")
local result ; result=$("${command[@]}" 2>&1)
echo "Result: $result"
if
[[ $result == *$needle* ]]
then
echo "[$green OK $reset] $name"
else
echo "[$red ERROR $reset] $name"
fi
echo " Command: ${command[@]} | Needle: $needle | Name: $name"
}
然后你可以通过将你的命令作为一个不带引号的字符串来调用你的函数,就像你在交互式shell中调用它一样,但是先放入前两个参数。
psa_test "HTTP/1.1" "Testing google.com" curl -v google.com
一些注意事项:
该命令存储在一个数组中,并通过扩展其所有元素来执行,单独引用以防止分词(这是"${command[@]}"
所做的)。
数组扩展的双引号非常重要,因为它们告诉shell将数组扩展为每个数组元素一个单词,并防止在每个数组元素内部发生单词拆分(以允许包含空格的数组元素) ,例如)。
您应该在函数内声明变量local。它并不是绝对必要的,但是当你有多个具有相同名称的变量的函数时,它将使脚本更易于调试,并且不易出现令人讨厌的失败模式。
我认为&#34; HTTP / 1.1&#34;是您想要的搜索字符串
如果需要考虑性能,则应尝试使用不同的文本匹配方法(即Bash regex =~
,grep
),以查看哪种方法最适合您的数据。
请注意,上述脚本可以通过以下方式简化:
local -a command=("${@:3}")
shift 2
"${command[@]}"
替换在这种情况下它会有意义,但我利用这个机会来说明构建命令如何作为数组工作,因为它在脚本中通常很有用,但在使用位置参数的简单情况下,它可以很好地工作并提高可读性。