一个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」的用法值得注意一下,相关参考资料如下:

使用的时候,允许使用多种工具,缺省情况下会优先使用「colordiff」,需要的话还可以激活「vimdiff」。本文刚写完没多久我就发现一个命令行解析JSON的好工具「jq」,如果早知道有它的话能节省不少时间,就当练习写Shell了吧。

一个Shell工具:jsondiff.sh》上有4个想法

发表评论

电子邮件地址不会被公开。 必填项已用*标注