3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ケーシーエスキャロットAdvent Calendar 2020

Day 20

aws cli と jq コマンド

Last updated at Posted at 2020-12-20

こちらの記事は ケーシーエスキャロット Advent Calendar 2020 の20日目の記事です。

昨日は aooki さんの WMS の地図画像を Google Map 上に表示する でした、クロスブラウザ問題まだまだあるんですね…。

さて皆さん、aws cli は使用していますか?
AWSコンソールで見れば手軽に状況や結果は確認できますが、複数の確認を行う時はポチポチを複数行わないといけませんよね。

そんな時、aws cli を使用すれば、複数の結果を json でひとまとめで確認できます。
…が、結果が多数あると確認作業が大変なことは変わりません。

例えば、aws ec2 describe-instances のコマンドを使用すればインスタンス情報が取得出来ますが、色々な情報を出力されすぎて対象のデータを目視で探し出すのも大変です。

そんな時、jq コマンドを使用すれば特定の情報を抜き出すことが出来ます。

jq

json データの加工・フィルターが行えるコマンド。
オフィシャルのマニュアルはこちらを参照。

準備

まずはインストールから始めましょう。
Windows10WSL(ubuntu18.04) 環境下へインストールしてみます。

$ sudo apt -y install jq
$ jq --version
jq-1.5-1-a5b5cbe

基本編

jq での基本的なコマンドは、

  1. . (ルート)
  2. [] (リスト)

の2つです。

また、| (パイプ)を繋げることによって、下階層のデータに対して操作が行えます。

test1.json
{
    "schema": "value",
    "list": [
        {
            "param_a": 111
        }, 
        {
            "param_a": 222
        }
    ]
}

例えば、上記のような json があったとして schema キーの値を取得したい場合は以下のようにします。

$ cat test1.json | jq '.schema'
"value"

また、代わりに list キーを指定すると以下になります。

$ cat test1.json | jq '.list'
[
  {
    "param_a": 111
  },
  {
    "param_a": 222
  }
]

さらに | で繋げて .[] を指定すると以下の結果になります。

$ cat test1.json  | jq '.list | .[]'
{
  "param_a": 111
}
{
  "param_a": 222
}

※ 一見、違いが分かりにくいですが、最上位の [] が外れています。

さらにさらに param_a| で繋げると以下の結果となります。

$ cat test1.json | jq '.list | .[] | .param_a'
111
222

応用編

前述した aws ec2 describe-instances コマンドで取得できる json データから一部抜粋した以下の内容を例に進めます。

test2.json
{
    "Reservations": [
        {
            "Instances": [
                {
                    "InstanceId": "i-111",
                    "BlockDeviceMappings": [
                        {
                            "DeviceName": "/dev/xvda1",
                            "Ebs": {
                                "VolumeId": "vol-111aaa"
                            }
                        },
                        {
                            "DeviceName": "/dev/xvda2",
                            "Ebs": {
                                "VolumeId": "vol-111bbb"
                            }
                        }
                    ]
                },
                {
                    "InstanceId": "i-222",
                    "BlockDeviceMappings": [
                        {
                            "DeviceName": "/dev/xvda1",
                            "Ebs": {
                                "VolumeId": "vol-222ccc"
                            }
                        },
                        {
                            "DeviceName": "/dev/xvda2",
                            "Ebs": {
                                "VolumeId": "vol-222ddd"
                            }
                        }
                    ]
                }
            ]
        }
    ]
}

例えば、VolumeId の値を列挙しようとした場合、基本編で記載した通り | で繋げていけば取得出来ます。

$ cat test2.json | jq '.Reservations | .[] | .Instances | .[] | .BlockDeviceMappings | .[] | .Ebs | .VolumeId'
"vol-111aaa"
"vol-111bbb"
"vol-222ccc"
"vol-222ddd"

因みに .xxx | .[].xxx[] と記載できるので、以下でも同じ結果が得られます。

$ cat test2.json  | jq '.Reservations[] | .Instances[] | .BlockDeviceMappings[] | .Ebs | .VolumeId'
"vol-111aaa"
"vol-111bbb"
"vol-222ccc"
"vol-222ddd"

もっと言えば、| で繋げて記載しなくても実現出来たりますが、| で区切った方が階層が分かりやすいようにも思います。(この辺りは好みの問題ですね)

$ cat test2.json | jq '.Reservations[].Instances[].BlockDeviceMappings[].Ebs.VolumeId'
"vol-111aaa"
"vol-111bbb"
"vol-222ccc"
"vol-222ddd"

もう少し発展させて、DeviceName キーの値が /dev/xvda1VolumeId 値のみを取得したい場合はどうすれば良いでしょう?
答えは、select を使用すれば実現できます。

$ cat test2.json  | jq '.Reservations[] | .Instances[] | .BlockDeviceMappings[] | select(.DeviceName == "/dev/xvda1") | .Ebs.VolumeId'
"vol-111aaa"
"vol-222ccc"

selectDeviceName/dev/xvda1 のもののみ抽出しています。

さらに発展させて一緒に InstanceId も取得する場合は以下となります。

$ cat test2.json  | jq '.Reservations[] | .Instances[] | .InstanceId, (.BlockDeviceMappings[] | select(.Devi
ceName == "/dev/xvda1") | .Ebs.VolumeId)'
"i-111"
"vol-111aaa"
"i-222"
"vol-222ccc"

InstanceId, で繋げた上で VolumeId() で括りました。

でも、この出力結果だと分かりづらいですね。
InstanceId,VolumeId のように csv 形式で出力してみたいと思います、最後に @csv を付けると実現できます。

$ cat test2.json  | jq '.Reservations[] | .Instances[] | [.InstanceId, (.BlockDeviceMappings[] | select(.Dev
iceName == "/dev/xvda1") | .Ebs.VolumeId)] | @csv'
"\"i-111\",\"vol-111aaa\""
"\"i-222\",\"vol-222ccc\""

※ 取得する項目は [] で括っていますが、@csv で出力するには array 形式でないといけないからです。

一応、csv 形式で出力されましたが、" が邪魔ですね…。
そんな場合は、-r を指定すると取り除けます。

$ cat test2.json  | jq -r '.Reservations[] | .Instances[] | [.InstanceId, (.BlockDeviceMappings[] | select(.
DeviceName == "/dev/xvda1") | .Ebs.VolumeId)] | @csv'
"i-111","vol-111aaa"
"i-222","vol-222ccc"

まとめ

いかがでしたでょうか?
aws cli からデータを取得後、jq でフィルターする一連の処理をシェルスクリプトで記載しておけば、叩くだけで取得が行えるので便利です。

なお、例題に挙げた aws ec2 describe-instances でも --filters --query を使用することにより jq のようなことは可能です。
うまく組み合わせれば、各々の絞り込みが簡潔になりそうですね。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?