linux 下強(qiáng)大的 JSON 解析命令 jq

介紹

jq is like sed for JSON data - you can use it to slice and filter and map and transform structured data with the same ease that sed, awk, grep and friends let you play with text.

jq 可以對 JSON 數(shù)據(jù)進(jìn)行切片、過濾、映射和轉(zhuǎn)換崖媚,和sed, awk, grep 命令一樣簡單好用。

jq is written in portable C, and it has zero runtime dependencies. You can download a single binary, scp it to a far away machine of the same type, and expect it to work.

jq 是用 C語言編寫的慌植,沒有運(yùn)行時(shí)依賴。獨(dú)立二進(jìn)制文件,可以使用 scp 復(fù)制到其他服務(wù)器直接運(yùn)行。

安裝

Linux

# 下載 https://stedolan.github.io/jq/download/
$ wget https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 -O /usr/local/bin/jq

# 執(zhí)行權(quán)限
$ chmod +x /usr/local/bin/jq

OS X

$ brew install jq

使用

以 njmon 的 json 輸出來演示 jq 的常用方式蛉艾,高級用法見官方手冊。

jq "."

以 json格式化輸出。

$ njmon -s 1 -c 1 | jq '.'
{
  "timestamp": {
    "datetime": "2020-03-14T19:59:22",
    "UTC": "2020-03-14T11:59:22",
    "snapshot_seconds": 1,
    "snapshot_maxloops": 1,
    "snapshot_loop": 0
  },
 ..... 省略其他輸出
}

指定 key 查詢

$ njmon -s 1 -c 1 | jq '.timestamp'
{
  "datetime": "2020-03-14T20:14:00",
  "UTC": "2020-03-14T12:14:00",
  "snapshot_seconds": 1,
  "snapshot_maxloops": 1,
  "snapshot_loop": 0
}

$ njmon -s 1 -c 1 | jq '.timestamp.datetime'
"2020-03-14T20:14:43"

--raw-output/-r

標(biāo)準(zhǔn)輸出伺通,即不格式化為帶引號的json 字符串

$ njmon -s 1 -c 1 | jq '.timestamp.datetime'
"2020-03-14T20:14:43"

$ njmon -s 1 -c 1 | jq -r '.timestamp.datetime'
2020-03-14T20:14:43

@csv:格式化輸出

還有其他格式方式: @html,@sh,@base64,@base64d等。

$ njmon -s 1 -c 1 | jq -r 'keys' | jq -r '@csv'
"cpu_total","cpuinfo","cpus","disks","filesystems","identity","lscpu","networks","os_release","proc_meminfo","proc_version","proc_vmstat","stat_counters","timestamp","uptime"

數(shù)組

$ njmon -s 1 -c 1 | jq '.cpus'
{
  "cpu0": {
    "user": 0.999,
    "nice": 0,
    "sys": 0.999,
    "idle": 99.87,
    "iowait": 0,
    "hardirq": 0,
    "softirq": 0,
    "steal": 0,
    "guest": 0,
    "guestnice": 0
  },
  "cpu1": {
    "user": 2.996,
    "nice": 0,
    "sys": 0.999,
    "idle": 97.873,
    "iowait": 0,
    "hardirq": 0,
    "softirq": 0,
    "steal": 0,
    "guest": 0,
    "guestnice": 0
  }
}

$ njmon -s 1 -c 1 | jq '.cpus[]'
{
  "user": 0.999,
  "nice": 0,
  "sys": 0.999,
  "idle": 99.92,
  "iowait": 0,
  "hardirq": 0,
  "softirq": 0,
  "steal": 0,
  "guest": 0,
  "guestnice": 0
}
{
  "user": 2.998,
  "nice": 0,
  "sys": 0.999,
  "idle": 97.922,
  "iowait": 0,
  "hardirq": 0,
  "softirq": 0,
  "steal": 0,
  "guest": 0,
  "guestnice": 0
}

函數(shù)

keys:獲取JSON中的key信息

$ njmon -s 1 -c 1 | jq 'keys'
[
  "cpu_total",
  "cpuinfo",
  "cpus",
  "disks",
  "filesystems",
  "identity",
  "lscpu",
  "networks",
  "os_release",
  "proc_meminfo",
  "proc_version",
  "proc_vmstat",
  "stat_counters",
  "timestamp",
  "uptime"
]

select(boolean_expression):搜索指定條件內(nèi)容

$ njmon -s 1 -c 1 | jq '.filesystems[] | select(.fs_dir == "/home")'
{
  "fs_dir": "/home",
  "fs_type": "ext4",
  "fs_opts": "rw,seclabel,relatime,data=ordered",
  "fs_freqs": 0,
  "fs_passno": 0,
  "fs_bsize": 4096,
  "fs_size_mb": 11502,
  "fs_free_mb": 11448,
  "fs_used_mb": 54,
  "fs_full_percent": 0.463,
  "fs_avail": 10842,
  "fs_files": 757392,
  "fs_files_free": 757110,
  "fs_namelength": 255
}

has(key):判斷是否存在某個(gè)key

$ njmon -s 1 -c 1 | jq 'has("cpus")'
true

$ njmon -s 1 -c 1 | jq 'has("cpus2")'
false

length:查看輸出長度或個(gè)數(shù)

# 5個(gè)字段
$ njmon -s 1 -c 1 | jq '.timestamp | length'
5

# 長度19
$ njmon -s 1 -c 1 | jq '.timestamp.datetime | length'
19

實(shí)際場景

nacos 工具腳本

在做自動部署腳本時(shí)逢享,需要寫個(gè) Nacos 工具腳本罐监,實(shí)現(xiàn)操作 Nacos 實(shí)例狀態(tài)查看、下線瞒爬、上線等弓柱。針對 Nacos 的 json 結(jié)構(gòu)數(shù)據(jù),使用 jq 來進(jìn)行處理侧但。腳本如下:

nacosUtils.sh

#!/bin/bash
# Nacos工具腳本

# 使用方法
usage() {
   echo "Usage: sh $0 {instance|instances|offline|online} URL NAMESPACE_ID SERVICE_NAME IP PORT [FORCE]"
   echo "\n"
   echo "\t {instance|instances|offline|online} 方法名稱"
   echo "\t\t -instance:查詢某個(gè)健康實(shí)例狀態(tài)矢空,true表示在線狀態(tài),false表示下線狀態(tài), 返回空表示實(shí)例不存在"
   echo "\t\t -instances:查詢健康實(shí)例總數(shù)"
   echo "\t SERVICE_NAME 系統(tǒng)名稱"
   echo "\t IP 實(shí)例IP"
   echo "\t PORT 實(shí)例啟動端口號"
   echo "\t FORCE 方法為offline時(shí)禀横,true表示強(qiáng)制下線屁药,非true表示校驗(yàn)是否多于2個(gè)健康實(shí)例"
   echo "\n"
   echo "示例:"
   echo "\t 啟動:sh $0 instance http://127.0.0.1/nacos ****** serviceName x.x.x.x 8090"
}

# 判斷參數(shù)
if [ $# -lt 4 ];
then
  usage
  exit 1
fi

# nacos url
URL=$2
# nacos 命名空間
NAMESPACE_ID=$3
# 系統(tǒng)名稱
SERVICE_NAME=$4
# 實(shí)例 IP地址
IP=$5
# 端口
PORT=$6
# 強(qiáng)制下線標(biāo)識
FORCE=$7

# 查看實(shí)例url
instanceListUrl="$URL/v1/ns/catalog/instances?serviceName=$SERVICE_NAME&clusterName=DEFAULT&pageSize=10&pageNo=1&namespaceId=$NAMESPACE_ID"
# 更新實(shí)例
instanceUrl="$URL/v1/ns/instance?serviceName=$SERVICE_NAME&ip=$IP&port=$PORT&namespaceId=$NAMESPACE_ID"

# 查詢健康且上線的實(shí)例個(gè)數(shù)
function instances() {
  echo `curl -X GET -s $instanceListUrl | jq -r ".list[] | select(.healthy == true) | select(.enabled == true) | .ip" | wc -l`
}

# 查詢健康實(shí)例狀態(tài)  在線:true;下線:false, 沒有查詢到: 空
function instance() {
  echo `curl -X GET -s $instanceListUrl | jq -r ".list[] | select(.ip == \"$IP\") | select(.port == $PORT) | select(.healthy == true) | .enabled"`
}

# 下線  健康實(shí)例總數(shù)為1時(shí)柏锄,不可下線唯一的服務(wù)
function offline() {
  if [ "X$FORCE" != "Xtrue" ];then
    counts=`instances`
    if [ $counts -lt 2 ];then
      curl -X GET -s $instanceListUrl | jq .
      echo "$SERVICE_NAME 實(shí)例總數(shù)小于2個(gè)酿箭,不可下線唯一的服務(wù)!V和蕖缭嫡!"
      exit 1
    fi
  fi

  result=`curl -X PUT -s "$instanceUrl&enabled=false"`
  echo $result
}

# 上線
function online() {
  enabledFlag=`instance`
  if [ "X$enabledFlag" == "Xtrue" ]; then
    curl -X GET -s $instanceListUrl | jq .
    echo "$SERVICE_NAME 實(shí)例為上線狀態(tài),無需執(zhí)行上線L啤8局!"
  else
    result=`curl -X PUT -s "$instanceUrl&enabled=true"`
  fi
  echo $result
}

case "$1" in
        'instance')
            instance
            ;;

        'instances')
            instances
            ;;

        'offline')
            offline
            ;;

        'online')
            online
            ;;

        *)
            usage
            exit 1
            ;;
esac

exit 0

njmon 結(jié)果格式化

njmon與nmon類似笤成,但輸出為 JSON 格式评架,用于服務(wù)器性能統(tǒng)計(jì)。

$ njmon -s 1 -c 1 | jq .
{
  "timestamp": {
    "datetime": "2020-03-14T19:59:22",
    "UTC": "2020-03-14T11:59:22",
    "snapshot_seconds": 1,
    "snapshot_maxloops": 1,
    "snapshot_loop": 0
  },
 ..... 省略其他輸出
}

擴(kuò)展閱讀

微信公眾號:daodaotest

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載炕泳,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者古程。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市喊崖,隨后出現(xiàn)的幾起案子挣磨,更是在濱河造成了極大的恐慌,老刑警劉巖荤懂,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茁裙,死亡現(xiàn)場離奇詭異,居然都是意外死亡节仿,警方通過查閱死者的電腦和手機(jī)晤锥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人矾瘾,你說我怎么就攤上這事女轿。” “怎么了壕翩?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵蛉迹,是天一觀的道長。 經(jīng)常有香客問我放妈,道長北救,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任芜抒,我火速辦了婚禮珍策,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宅倒。我一直安慰自己攘宙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布拐迁。 她就那樣靜靜地躺著模聋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪唠亚。 梳的紋絲不亂的頭發(fā)上链方,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天,我揣著相機(jī)與錄音灶搜,去河邊找鬼祟蚀。 笑死,一個(gè)胖子當(dāng)著我的面吹牛割卖,可吹牛的內(nèi)容都是我干的前酿。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼鹏溯,長吁一口氣:“原來是場噩夢啊……” “哼罢维!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起丙挽,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤肺孵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后颜阐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體平窘,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年凳怨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瑰艘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片是鬼。...
    茶點(diǎn)故事閱讀 39,727評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖紫新,靈堂內(nèi)的尸體忽然破棺而出均蜜,到底是詐尸還是另有隱情,我是刑警寧澤芒率,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布囤耳,位于F島的核電站,受9級特大地震影響敲董,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜慰安,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一腋寨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧化焕,春花似錦萄窜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至凤类,卻和暖如春穗泵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谜疤。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工佃延, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人夷磕。 一個(gè)月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓履肃,卻偏偏與公主長得像,于是被迫代替她去往敵國和親坐桩。 傳聞我的和親對象是個(gè)殘疾皇子尺棋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容