Shell脚本IF条件比较字符串异常排查求助
Shell脚本字符串匹配失败问题解决
问题详情
我在Shell脚本中通过IF条件比较字符串时未得到预期结果。我的应用有三类Eventing-Function运行日志,已将日志内容赋值给executionstatus变量,日志内容如下:
"composite_status": "deployed", "name": "Eventing-Function", "num_bootstrapping_nodes": 0, "num_deployed_nodes": 5, "deployment_status": true, "processing_status": true, "redeploy_required": false "composite_status": "deployed", "name": "Eventing-Function-on-expiry", "num_bootstrapping_nodes": 0, "num_deployed_nodes": 5, "deployment_status": true, "processing_status": true, "redeploy_required": false "composite_status": "deployed", "name": "Eventing-Function-dev", "num_bootstrapping_nodes": 0, "num_deployed_nodes": 5, "deployment_status": true, "processing_status": true, "redeploy_required": false
我把其中的deployed提取出来赋值给status变量,名称赋值给name变量,通过for循环遍历5个节点,需求是检查这三类Eventing-Function的状态是否均为deployed,否则触发邮件告警。但比较$status和$cbstatus时匹配失败,调试输出如下:
+ '[' 'deployed deployed deployed ' == 'deployed deployed deployed' ']' + echo 'status is not deployed at ' $url
明显是status变量末尾多了一个空格导致匹配失败,我的脚本代码如下:
for url in "${uat_urls[@]}" do executionstatus=$(curl -sX GET -u ${admin}:${password} 'http://'${url}':8009/api/v1/status') status=$(echo $executionstatus | grep -o '"composite_status": "[^"]*'| grep -o '[^"]*$' |tr '\n' ' ') name=$(echo $executionstatus | grep -o '"name": "[^"]*'| grep -o '[^"]*$') cbstatus=$(printf "deployed deployed deployed") echo $status echo $cbstatus if [ "${status}" != "${cbstatus}" ]; then echo "status is not deployed at " $url >> status.txt # mail that the eventing function is not deployed echo "$(<status.txt )" | mailx -r "xyz.testcom" -s "FE CB AS eventing service status" $mail_me rm status.txt else echo "status is not deployed at " $url >> status.txt fi done
解决方案
方法1:直接去除status变量末尾空格
在提取status后,用Shell内置语法或sed去掉末尾多余空格:
# 方式A:用sed去除末尾所有空白字符 status=$(echo $executionstatus | grep -o '"composite_status": "[^"]*'| grep -o '[^"]*$' |tr '\n' ' ' | sed 's/[[:space:]]*$//') # 方式B:用Shell参数扩展去除最后一个空格 status=$(echo $executionstatus | grep -o '"composite_status": "[^"]*'| grep -o '[^"]*$' |tr '\n' ' ') status=${status% }
方法2:改用数组存储状态(更健壮)
用空格拼接字符串容易出问题,直接将每个状态存入数组,逐个校验是否为deployed:
for url in "${uat_urls[@]}" do executionstatus=$(curl -sX GET -u ${admin}:${password} 'http://'${url}':8009/api/v1/status') # 将提取到的每个状态存入数组 read -ra status_array <<< "$(echo $executionstatus | grep -o '"composite_status": "[^"]*'| grep -o '[^"]*$')" # 检查所有状态是否都是deployed all_deployed=true for s in "${status_array[@]}"; do if [ "$s" != "deployed" ]; then all_deployed=false break fi done if [ "$all_deployed" = false ]; then echo "status is not deployed at $url" >> status.txt echo "$(<status.txt)" | mailx -r "xyz.testcom" -s "FE CB AS eventing service status" $mail_me rm status.txt else echo "all eventing functions are deployed at $url" >> status.txt fi done
方法3:用jq解析JSON(推荐)
如果接口返回的是标准JSON格式,用专门的JSON解析工具jq提取状态,避免正则匹配的各种问题:
for url in "${uat_urls[@]}" do # 用jq提取每个对象的composite_status,存入数组 status_array=($(curl -sX GET -u ${admin}:${password} 'http://'${url}':8009/api/v1/status' | jq -r '.composite_status')) all_deployed=true for s in "${status_array[@]}"; do if [ "$s" != "deployed" ]; then all_deployed=false break fi done if [ "$all_deployed" = false ]; then echo "status is not deployed at $url" >> status.txt echo "$(<status.txt)" | mailx -r "xyz.testcom" -s "FE CB AS eventing service status" $mail_me rm status.txt else echo "all eventing functions are deployed at $url" >> status.txt fi done
内容的提问来源于stack exchange,提问作者narasimman bala
相关产品推荐
相关产品推荐

