一次寫shell腳本的經歷記錄——特殊字符惹的禍

本文首發於微信公衆號「個人小碗湯」,掃碼文末二維碼便可關注,歡迎一塊兒交流!html

redis在容器化的過程當中,涉及到縱向擴pod實例cpu、內存以及redis實例的maxmemory值,statefulset管理的pod須要重啓。因此把redis集羣的狀態檢查放到了健康檢查中,依賴statefulset的原生能力(pod實例ready後才重啓下一個,ready後endpoints controller將pod信息更新到endpoints資源對象中),而沒有在redis operator中寫邏輯去判斷。前端

須要用redis-cli -h {redis實例IP} ping查看redis是否正常,同時用redis-cli -c -h {redis實例IP} -a {redis密碼} cluster info輸出的信息解析clusterstate的值是否爲ok,以及clusterknown_nodes的值是否爲1,判斷redis集羣是否正常;java

若是redis集羣剛建立,clusterknownnodes爲1,cluster_state爲fail;node

若是redis集羣爲縱向擴容(擴CPU、內存)升級重啓,clusterknownnodes不爲1,cluster_state爲ok時才認爲集羣正常,才能重啓下一個pod。python

由於涉及到字符串相等判斷,因此用如下這樣判斷:linux

if [ "$cluster_known_nodes"x = "1"x  ]; then
.....
fi複製代碼

可是判斷一直有問題,以下圖,在$a後面加個x,會變爲在開頭覆蓋式的加a,結果就是判斷結果不相等。在這裏插入圖片描述把redis-cli -c -h {redis實例IP} -a {redis密碼} cluster info執行的結果重定向到文件裏。面試

vi 1.txt查看文件,在vi裏用set ff命令查看文件格式爲unix,可是文件每一行後面都有一個^M的特殊字符,這就是問題所在了。在這裏插入圖片描述redis

最主要是經過cat都看不出來特殊字符的存在。在這裏插入圖片描述spring

手動把^M特殊字符刪掉就行了。在這裏插入圖片描述shell

網上說^M是windows格式文本文件的換行符rn,能夠用dos2unix命令轉爲unix格式。可是執行cluster info命令全程在linux中操做,並且重定向到文件中set ff命令看到也是unix格式。這點仍是很費解。

先用sed命令將^M換掉,試了sed 's/^M//g'沒有用,因此選擇用sed 's?r??g'替換,最終腳本以下。

if語句的[[]]須要用bash執行,用sh執行會報錯[[: not found

#!/bin/bash

#須要用redis-cli -h {redis實例IP} ping查看redis是否正常
#用redis-cli -c -h {redis實例IP} -a {redis密碼} cluster info輸出
#的信息解析cluster_state的值是否爲ok,以及cluster_known_nodes的值是
#否爲1,判斷redis集羣是否正常;若是redis集羣剛建立,cluster_known_nodes
#爲1,cluster_state爲fail;若是redis集羣爲縱向擴容(擴CPU、內存)升級重啓
#cluster_known_nodes不爲1,cluster_state爲ok時才認爲集羣正常,才能重啓
#下一個pod,改健康檢查腳本旨在維護升級時redis集羣狀態,不在operator中維護
# 利用好statefulset一個實例ready後重啓下一個pod的特性

pingres=$(redis-cli -h $(hostname) ping)

# cluster_state:ok
# cluster_slots_assigned:16384
# cluster_slots_ok:16384      
# cluster_slots_pfail:0        
# cluster_slots_fail:0        
# cluster_known_nodes:6        
# cluster_size:3                
# cluster_current_epoch:15      
# cluster_my_epoch:12          
# cluster_stats_messages_sent:270782059
# cluster_stats_messages_received:270732696
pingres=$(echo "${pingres}" | sed 's?\r??g')
if [[ "$pingres"x = "PONG"x ]]; then
    clusterinfo=$(redis-cli -c -h ${PODIP} cluster info)
    # redis-cli -c -h ${PODIP} cluster info output info include ^M(win \n\r) char lead to error, so use sed 's?\r??g'
    clusterknownnodes=$(echo "${clusterinfo}" | grep cluster_known_nodes | sed 's?\r??g' | awk -F ':' '{print $2}')
    clusterstate=$(echo "${clusterinfo}" | grep cluster_state | sed 's?\r??g' | awk -F ':' '{print $2}')

    echo "clusterknownnodes: ${clusterknownnodes} --- clusterstate: ${clusterstate}"
    # [[ need run this script use /bin/bash instead of /bin/sh
    # if語句的[[]]須要用bash執行,用sh執行會報錯[[: not found
    if [[ "${clusterknownnodes}"x = "1"x && "${clusterstate}"x = "ok"x ]]; then
        echo "--1--"
        exit 0
    elif [[ "${clusterknownnodes}"x != "1"x && "${clusterstate}"x = "ok"x ]]; then
        echo "--2--"
        exit 0
    # create redis cluster
    elif [[ "${clusterknownnodes}"x = "1"x && "${clusterstate}"x != "ok"x ]]; then
        echo "--3--"
        exit 0
    elif [[ "${clusterknownnodes}"x != "1"x && "${clusterstate}"x != "ok"x ]]; then
        echo "--4--"
        exit 1
    else
        echo "--5--"
        exit 1
    fi
else
    exit 1
fi複製代碼

通常這種怪異的問題都是腳本里有特殊字符形成的,能夠在腳本中set list顯示特殊字符。固然windows上編輯過的腳本在linux上運行通常dos2unix test.sh這樣轉換一下最好,免的遇到麻煩。

參考:

shell中括號的特殊用法 linux if多條件判斷https://www.cnblogs.com/jjzd/p/6397495.html

運行shell腳本時報錯"[[ : not found"解決方法https://www.cnblogs.com/han-1034683568/p/7211392.html

本公衆號免費提供csdn下載服務,海量IT學習資源,若是你準備入IT坑,勵志成爲優秀的程序猿,那麼這些資源很適合你,包括但不限於java、go、python、springcloud、elk、嵌入式 、大數據、面試資料、前端 等資源。同時咱們組建了一個技術交流羣,裏面有不少大佬,會不定時分享技術文章,若是你想來一塊兒學習提升,能夠公衆號後臺回覆【2】,免費邀請加技術交流羣互相學習提升,會不按期分享編程IT相關資源。

掃碼關注,精彩內容第一時間推給你

image

相關文章
相關標籤/搜索