kubernetes集群管理之经过jq来截取属性

系列目录html

首先要声明,这里的jq并非批前端框架里的jquery,而是一个处理json的命令行工具.前端

jq工具相比yq,它更加成熟,功能也更增强大,主要表如今如下几个方面jquery

  • 支持递归查找(我点对咱们平时查看文件很方便)linux

  • 支持条件过滤git

  • 支持控制语句github

  • 支持数组范围索引正则表达式

这个工具在macos和windows都提供在线包安装服务,linux并无官方包服务,须要下载后放到usr/bin目录下shell

下载地址macos

centos下也能够经过如下方式安装编程

wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -ivh epel-release-latest-7.noarch.rpm
yum repolist

基本语法

基本语法格式以下

jq [options] <jq filter> [file...]

须要把文件放在最后面,可是也无所谓,不少时候咱们并不处理本地的json,而是经过标准输入来处理其它来源类型的json

我本地存有一个叫做test.json的json文件,咱们能够经过jq . test.json查看文件里的全部内容

{
  "json": [
    "rigid",
    "better for data interchange"
  ],
  "yaml": [
    "slim and flexible",
    "better for configuration"
  ],
  "object": {
    "key": "value",
    "array": [
      {
        "name": null
      },
      {
        "name": true
      },
      {
        "name": 24
      }
    ]
  },
  "paragraph": "Blank lines denote\nparagraph breaks\n",
  "content": "Or we\ncan auto\nconvert line breaks\nto save space"
}

jq输出的json文件默认都是格式化过的,方便咱们查看

咱们仿照上一节,来获取json数组里的全部值.

tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq .json test.json
[
  "rigid",
  "better for data interchange"
]

经过如下命令获取array数组

tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq .object.array test.json
[
  {
    "name": null
  },
  {
    "name": true
  },
  {
    "name": 24
  }
]

经过与上节jq相似的命令获取array里面的值

tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq .object.array[].name test.json
null
true
24

数组也能够在中括号里面指定索引(跟绝大多数编程语言同样,从0开始)也与前面的yq相似,不一样的是这里可使用[start:end]的方式来索引范围

上面的例子咱们此次不取所有,只取第0个和第一个

tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq .object.array[0:2] test.json
[
  {
    "name": null
  },
  {
    "name": true
  }
]

除了索引范围之后,还能够索引不连续的对象,语法为[index1,index2,...]形式

例如,如下操做获取第零个和第二个对象

tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq .object.array[0,2] test.json
{
  "name": null
}
{
  "name": 24
}

以上操做并索引并不必定按照从小到大的顺序,好比如下也是能够的

tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq .object.array[1,0,2] test.json
{
  "name": true
}
{
  "name": null
}
{
  "name": 24
}

可空对象

有时候咱们不肯定一个对象是否存在,这时候咱们能够在对象后面跟个问号?来代表不肯定这个对象是否存在

好比jq .yml? test.json代表你不肯定yml这个属性在要查询的对象中是否存在,若是这个对象是不存在的,则返回的值为null

实际上你会发现,上面不写问号返回的值也是null,并不会报错.在这里体现的不明显,可是对数组类型的若是一个对象不存在写为数组形式就会报错

好比jq .yml[] test.json就会出现jq: error (at test.json:25): Cannot iterate over null (null)错误

而使用jq .yml[]? test.json即使yml对象不存在也不会报错

使用逗号,来取多个对象

假如咱们想要同时取json和yaml这两个对象,可使用,把两个命令分开,把它们的结果合在一块

tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq .json,.yaml test.json
[
  "rigid",
  "better for data interchange"
]
[
  "slim and flexible",
  "better for configuration"
]

使用括号

上面的使用都逗号的命令里咱们已经使用两条命令了,实际工做中可能有更加复杂的命令组合,这时候可使用()来组织.在jq里使用()和在其它编程语言里使用相同.

使用管道符|

在jq里管道符概念和linux上概念基本相同.能够把上一个命令的结果做为下一个命令的输出.前面的.object.array也能够写做管道模式.object|.array先用.object取object的全部对象,而后结果做为下级管道的输入值,.array从管道结果里取array数组

tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq '.object|.array' test.json
[
  {
    "name": null
  },
  {
    "name": true
  },
  {
    "name": 24
  }
]

递归查找子对象

在kubernetes 的jsonpath里,可使用..来查找子对象,很是方便,唯一很差的是若是子对象包含数组类型则显示为Map[xxx]类型,而且展现的结果再也不是json格式,可读性不是特别好.比较遗憾的是,在jq里并不支持..这种语法,而是更为复杂一些,须要使用管道符.

命令的格式以下

..|.对象名?

首先这里使用了..表示从根对象开始取,而后使用管道符,后面之因此使用可空对象(对象后面带问号)是由于它会在每一层都查找,不使用可空对象的话找不到就会报错.

假如咱们并不知道array对象的上一层是什么,可是知道这个对象存在.可使用下面命令来获取.

tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq '..|.array?' test.json
null
[
  {
    "name": null
  },
  {
    "name": true
  },
  {
    "name": 24
  }
]
null
null
null

这里之因此会出现好多的null,由于jq会进入每一层对象里面查找,找不到就返回null.为了展现美观,咱们也能够作一些简的处理

tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq '..|.array?' test.json|sed 's/null//g'

[
  {
    "name":
  },
  {
    "name": true
  },
  {
    "name": 24
  }
]

以上命令使用sed把null替换为空,这里不够优雅的地方在于把第一个name的值null也替换为空了.

这里的命令外层加了引号,之因此要加引号是由于这个管道是jq管道,若是不加引号就会被shell识别为shell命令管道,从而致使错误.

过滤对象

咱们使用示例来讲明,使用如下命令获取kubernetes集群中的一个pod的conditions信息

[centos@k8s-master ~]$ kubectl get pod consul-0 -ojson|jq '.status.conditions[]'
[
  {
    "lastProbeTime": null,
    "lastTransitionTime": "2019-05-14T07:19:28Z",
    "status": "True",
    "type": "Initialized"
  },
  {
    "lastProbeTime": null,
    "lastTransitionTime": "2019-05-14T07:25:06Z",
    "status": "True",
    "type": "Ready"
  },
  {
    "lastProbeTime": null,
    "lastTransitionTime": "2019-05-14T07:25:06Z",
    "status": "True",
    "type": "ContainersReady"
  },
  {
    "lastProbeTime": null,
    "lastTransitionTime": "2019-05-14T07:19:28Z",
    "status": "True",
    "type": "PodScheduled"
  }
]

如今我想要过滤typeReady的对象,可使用如下命令

[centos@k8s-master ~]$ kubectl get pod consul-0 -ojson|jq '.status.conditions[]|select(.type=="Ready")'
{
  "lastProbeTime": null,
  "lastTransitionTime": "2019-05-14T07:25:06Z",
  "status": "True",
  "type": "Ready"
}

以上命令把status里的conditions数组对象作为输入传递给管道下一级,而后使用select函数里面传入条件.

以上是彻底匹配type属性值为Ready,若是想要模糊匹配,则能够经过管道使用contains函数

[centos@k8s-master ~]$ kubectl get pod consul-0 -ojson|jq '.status.conditions[]|select(.type|contains("Ready"))'
{
  "lastProbeTime": null,
  "lastTransitionTime": "2019-05-14T07:25:06Z",
  "status": "True",
  "type": "Ready"
}
{
  "lastProbeTime": null,
  "lastTransitionTime": "2019-05-14T07:25:06Z",
  "status": "True",
  "type": "ContainersReady"
}

这样,两个type值包含Ready的所有被选择出来了.

正则匹配

上面的过滤条件中,因为Ready是大写的,所以不管是相等比较仍是包含比较,都必须使用大写,若是是小写则没法匹配到.可是不少时候咱们可能对大小写是不清楚的,咱们但愿匹配的时候区分大小写,这在jq里也是能够作到的,咱们使用match函数,match函数为正则匹配函数.接收一个数组形式的参数,数组的第一项为要匹配的内容,第二项为开关(好比g表明全局开关,i则表明不区分大小写)

咱们把上面的示例改造以下

[centos@k8s-master ~]$ kubectl get pod consul-0 -ojson|jq '.status.conditions[]|select(.type|match(["ready","i"]))'
{
  "lastProbeTime": null,
  "lastTransitionTime": "2019-05-14T07:25:06Z",
  "status": "True",
  "type": "Ready"
}
{
  "lastProbeTime": null,
  "lastTransitionTime": "2019-05-14T07:25:06Z",
  "status": "True",
  "type": "ContainersReady"
}

这样使用正则表达式咱们就能够不区分大小写匹配了.

以上只列出了工做中可能经常使用的功能,详细功能能够查看官方文档

相关文章
相关标签/搜索