てくなべ (tekunabe)

ansible / network automation / 学習メモ

ip コマンドの -j オプションで JSON 出力する

はじめに

コマンドの出力結果を機械的に抽出や加工したい場合、JSONなどの構造化データだと正規表現を書くことをぐっと減らせて便利です。

たまたま ip コマンドは -j または --json というオプションで json 出力できることを知りました。

-p オプションを併用すると、改行付きで表示されて見やすいです。

試した結果をまとめます。

IP アドレスの表示

(一部ダミーの値にしています)

JSON 出力

$ ip -j -p addr
[ {
        "ifindex": 1,
        "ifname": "lo",
        "flags": [ "LOOPBACK","UP","LOWER_UP" ],
        "mtu": 65536,
        "qdisc": "noqueue",
        "operstate": "UNKNOWN",
        "group": "default",
        "txqlen": 1000,
        "link_type": "loopback",
        "address": "00:00:00:00:00:00",
        "broadcast": "00:00:00:00:00:00",
        "addr_info": [ {
                "family": "inet",
                "local": "127.0.0.1",
                "prefixlen": 8,
                "scope": "host",
                "label": "lo",
                "valid_life_time": 4294967295,
                "preferred_life_time": 4294967295
            },{
                "family": "inet6",
                "local": "::1",
                "prefixlen": 128,
                "scope": "host",
                "valid_life_time": 4294967295,
                "preferred_life_time": 4294967295
            } ]
    },{
        "ifindex": 2,
        "ifname": "ens192",
        "flags": [ "BROADCAST","MULTICAST","UP","LOWER_UP" ],
        "mtu": 1500,
        "qdisc": "fq_codel",
        "operstate": "UP",
        "group": "default",
        "txqlen": 1000,
        "link_type": "ether",
        "address": "00:50:56:xx:xx:xx",
        "broadcast": "ff:ff:ff:ff:ff:ff",
        "addr_info": [ {
                "family": "inet",
                "local": "192.168.1.100",
                "prefixlen": 24,
                "broadcast": "192.168.1.255",
                "scope": "global",
                "dynamic": true,
                "noprefixroute": true,
                "label": "ens192",
                "valid_life_time": 67514,
                "preferred_life_time": 67514
            },{
                "family": "inet6",
                "local": "2001:db8::1",
                "prefixlen": 64,
                "scope": "global",
                "dynamic": true,
                "noprefixroute": true,
                "valid_life_time": 2591817,
                "preferred_life_time": 604617
            },{
                "family": "inet6",
                "local": "fe80::5686:4062:1:1",
                "prefixlen": 64,
                "scope": "link",
                "noprefixroute": true,
                "valid_life_time": 4294967295,
                "preferred_life_time": 4294967295
            } ]
    },{
        "ifindex": 3,
        "ifname": "virbr0",
        "flags": [ "NO-CARRIER","BROADCAST","MULTICAST","UP" ],
        "mtu": 1500,
        "qdisc": "noqueue",
        "operstate": "DOWN",
        "group": "default",
        "txqlen": 1000,
        "link_type": "ether",
        "address": "52:54:00:xx:xx:xx",
        "broadcast": "ff:ff:ff:ff:ff:ff",
        "addr_info": [ {
                "family": "inet",
                "local": "192.168.122.1",
                "prefixlen": 24,
                "broadcast": "192.168.122.255",
                "scope": "global",
                "label": "virbr0",
                "valid_life_time": 4294967295,
                "preferred_life_time": 4294967295
            } ]
    },{
        "ifindex": 4,
        "ifname": "virbr0-nic",
        "flags": [ "BROADCAST","MULTICAST" ],
        "mtu": 1500,
        "qdisc": "fq_codel",
        "master": "virbr0",
        "operstate": "DOWN",
        "group": "default",
        "txqlen": 1000,
        "link_type": "ether",
        "address": "52:54:00:xx:xx:xx",
        "broadcast": "ff:ff:ff:ff:ff:ff",
        "addr_info": [ ]
    } ]

通常出力(比較用)

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:50:56:xx:xx:xx brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.100/24 brd 192.168.1.255 scope global dynamic noprefixroute ens192
       valid_lft 67528sec preferred_lft 67528sec
    inet6 2001:db8::1/64 scope global dynamic noprefixroute 
       valid_lft 2591832sec preferred_lft 604632sec
    inet6 fe80::5686:4062:1:1/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:xx:xx:xx brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:xx:xx:xx brd ff:ff:ff:ff:ff:ff

ルーティングテープルの表示

JSON 出力

$ ip -j -p route
[ {
        "dst": "default",
        "gateway": "192.168.1.1",
        "dev": "ens192",
        "protocol": "dhcp",
        "metric": 100,
        "flags": [ ]
    },{
        "dst": "192.168.1.0/24",
        "dev": "ens192",
        "protocol": "kernel",
        "scope": "link",
        "prefsrc": "192.168.1.100",
        "metric": 100,
        "flags": [ ]
    },{
        "dst": "192.168.122.0/24",
        "dev": "virbr0",
        "protocol": "kernel",
        "scope": "link",
        "prefsrc": "192.168.122.1",
        "flags": [ "linkdown" ]
    } ]

通常出力(比較用)

$ ip route
default via 192.168.1.1 dev ens192 proto dhcp metric 100 
192.168.1.0/24 dev ens192 proto kernel scope link src 192.168.1.100 metric 100 
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown 

おわりに

他のコマンド、ツールも意外と標準でJSON出力できるということもありそうです。

今一度ヘルプを見るといいかもしれません。

参考

標準機能ではないですが、主要コマンドのパーサーとして jc というものもあります。

github.com