一个Shell工具:jsondiff.sh

我最近忙着重构一个历史项目,不过由于客观条件所限,没有测试用例可用,以至于我不得不通过人肉对比新旧服务器的结果集是否一致来判断对错。既然说懒惰是程序员的美德,所以我想还是写一个工具吧,加之结果集为JSON,于是便有了jsondiff.sh。

逻辑很简单,无非就是通过curl在不同的服务器上取得结果集,然后diff即可,不过这里有几点需要注意的地方:首先,JSON就一行,直接diff会失去意义;其次,JSON中汉字会被编码,不利于查看;另外,JSON中字段顺序是无所谓的,所以diff前最好排序。说明一下,在格式化JSON数据的时候,我没有用Bash,而是用的PHP:

#!/bin/bash 


RM=/bin/rm 


PHP=/usr/bin/php 


CURL=/usr/bin/curl 


DIFF=/usr/bin/diff 


VIMDIFF=/usr/bin/vimdiff 


COLORDIFF=/usr/bin/colordiff 


usage() { 


    echo "Usage: $0 --uri=<URI> --old=<IP> --new=<IP>" 


} 


format() { 


    $PHP -R ' 


        function ksort_recursive(&$array) { 


            if (!is_array($array)) { 


                return; 


            } 


            ksort($array); 


 


            foreach (array_keys($array) as $key) { 


                ksort_recursive($array[$key]); 


            } 


        } 


        $options = JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE; 


 


        $array = json_decode($argn, true); 


        ksort_recursive($array); 


 


        echo json_encode($array, $options); 


    ' 


} 


request() { 


    $CURL -s -H "Host: $1" "http://$2$3" 


} 


 


eval set -- $( 


    getopt -q -o "h" -l "host:,uri:,old:,new:,vim,help" -- "$@" 


) 


while true; do 


    case "$1" in 


        --host)    HOST=$2; shift 2;; 


        --uri)     URI=$2;  shift 2;; 


        --old)     OLD=$2;  shift 2;; 


        --new)     NEW=$2;  shift 2;; 


        --vim)     VIM="Y"; shift 1;; 


        -h|--help) usage;   exit 0;; 


        --)                 break;; 


    esac 


done 


if [[ -z "$URI" || -z "$OLD" || -z "$NEW" ]]; then 


    usage 


    exit 1 


fi 


if [[ -z "$HOST" ]]; then 


    HOST="www.foobar.com" 


fi 


OLD_FILE=$(mktemp) 


NEW_FILE=$(mktemp) 


request "$HOST" "$OLD" "$URI" | format > $OLD_FILE 


request "$HOST" "$NEW" "$URI" | format > $NEW_FILE 


if [[ "$VIM" == "Y" ]]; then 


    $VIMDIFF $OLD_FILE $NEW_FILE 


elif [[ -x "$COLORDIFF" ]]; then 


    $COLORDIFF -u $OLD_FILE $NEW_FILE 


else 


    $DIFF -u $OLD_FILE $NEW_FILE 


fi 


$RM -f $OLD_FILE 


$RM -f $NEW_FILE 

其中「getopt」的用法值得注意一下,相关参考资料如下:

相关推荐