一個Shell工具:jsondiff.sh
我最近忙著重構(gòu)一個歷史項目,不過由于客觀條件所限,沒有測試用例可用,以至于我不得不通過人肉對比新舊服務(wù)器的結(jié)果集是否一致來判斷對錯。既然說懶惰是程序員的美德,所以我想還是寫一個工具吧,加之結(jié)果集為JSON,于是便有了jsondiff.sh。
邏輯很簡單,無非就是通過curl在不同的服務(wù)器上取得結(jié)果集,然后diff即可,不過這里有幾點需要注意的地方:首先,JSON就一行,直接diff會失去意義;其次,JSON中漢字會被編碼,不利于查看;另外,JSON中字段順序是無所謂的,所以diff前***排序。說明一下,在格式化JSON數(shù)據(jù)的時候,我沒有用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」的用法值得注意一下,相關(guān)參考資料如下:
- Getopt in Bash
- Bash: Preserving Whitespace Using set and eval
雖然我的Shell水平有限,但是我盡可能寫得易用:在diff的時候,允許使用多種工具,缺省情況下會優(yōu)先使用「colordiff」,需要的話還可以激活「vimdiff」。