A record of the experience of writing shell script -- the disaster caused by special characters

Keywords: Programming Redis Unix Windows Linux

This article first appeared in wechat public account "my little bowl soup". You can pay attention to it by scanning the QR code at the end of the article. Welcome to exchange!

In the process of redis containerization, it involves extending the cpu, memory and maxmemory value of redis instance vertically. The pod managed by statefullset needs to be restarted. Therefore, the status check of the redis cluster is put into the health check, which depends on the native ability of statefullset (the next instance will be restarted after the pod instance is ready, and the endpoints controller will update the pod information to the endpoints resource object after it is ready), instead of writing logic to judge in the redis operator.

You need to Ping redis-cli-h {redis instance IP} to check whether redis is normal. At the same time, you need to use the information output by redis-cli-c-h {redis instance IP} -a {redis password} cluster info to analyze whether the cluster {state value is ok, and whether the cluster {known} nodes value is 1 to determine whether the redis cluster is normal.

If the redis cluster has just been created, the cluster "known" node is 1, and the cluster "state" is fail.

If the redis cluster is upgraded and restarted for vertical capacity expansion (CPU and memory expansion), the cluster "known" nodes is not 1, and the cluster "state" is ok, then the cluster is considered normal, and the next pod can be restarted.

Because string equality judgment is involved, the following judgment is used:

if [ "$cluster_known_nodes"x = "1"x  ]; then
.....
fi

But there is always a problem in the judgment. As shown in the following figure, adding an x after $a will change to adding a at the beginning of the overlay. The result is that the judgment results are not equal. Redirect the result of the execution of redis-cli-c-h {redis instance IP} -a {redis password} cluster info to a file.

vi 1.txt to view the file. In vi, use the set ff command to view the file format as unix, but each line of the file is followed by a ^ M special character, which is the problem.

The main reason is that we can't see the existence of special characters through cat.

Just delete ^ M special characters manually.

It is said on the Internet that ^ M is the line break of windows format text file. You can use the dos2unix command to convert it to UNIX format. However, the cluster info command is executed in linux all the way, and the set ff command redirected to the file is also in UNIX format. It's still hard to understand.

First, use the SED command to replace ^ M, and try to find that sed's / ^ M / / g 'is useless, so choose to replace it with sed's? \ r?? G'. The final script is as follows.

The [[]] of the if statement needs to be executed with bash. If it is executed with sh, an error [[: not found] will be reported.

#!/bin/bash

#You need to use redis cli - H {redis instance IP} ping to check whether redis is normal.
#Output with redis-cli-c-h {redis instance IP} -a {redis password} cluster info
#Whether the value of cluster'u state is ok and the value of cluster'u known'nodes is
#If no is 1, judge whether the redis cluster is normal or not. If the redis cluster has just been created, cluster "known" nodes
#If it is 1, the cluster state is fail; if the redis cluster is upgraded for vertical expansion (expansion of CPU and memory), restart.
#Only when the cluster ﹣ known ﹣ nodes is not 1 and the cluster ﹣ state is ok can the cluster be considered normal and restarted.
#In the next pod, the health check script is changed to maintain the redis cluster status during upgrade, not in the operator.
# Make good use of the feature of "statefullset" to restart the next pod after an instance is ready

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
    # The [[]] of the if statement needs to be executed with bash. If it is executed with sh, an error [[: not found] will be reported.
    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

In general, this weird problem is caused by special characters in the script. You can set list to display special characters in the script. Of course, it's best to run the general DOS 2unix test.sh script edited on windows on linux without any trouble.

Reference resources:

Special usage of parentheses in shell https://www.cnblogs.com/jjzd/p/6397495.html

Error "[[: not found" when running shell script https://www.cnblogs.com/han-1034683568/p/7211392.html

This public account is free * * to provide csdn download service and massive it learning resources * * if you are ready to enter the IT pit and aspire to become an excellent program ape, these resources are suitable for you, including but not limited to java, go, python, springcloud, elk, embedded, big data, interview materials, front-end and other resources. At the same time, we have set up a technology exchange group. There are many big guys who will share technology articles from time to time. If you want to learn and improve together, you can reply [2] in the background of the public account. Free invitation plus technology exchange groups will learn from each other and share programming it related resources from time to time.

Scan the code to pay attention to the wonderful content and push it to you at the first time

Posted by ORiGIN on Wed, 23 Oct 2019 12:01:05 -0700