AWSを学ぶならLinuxも一緒に！ CLI出力を自在に操り、インフラ管理を効率化するメリット

## まえがき

こんにちは！AWSを活用してインフラ構築・運用を行っている皆さん、AWS CLIは便利ですよね！しかし、時々「情報量が多すぎる…」「欲しい情報だけ抜き出すのが面倒…」と感じることはありませんか？

例えば、`aws ec2 describe-instances` コマンド。アカウント内の全EC2インスタンスの詳細情報を取得できますが、デフォルトではJSON形式で非常に多くの情報が出力されます。

```json
{
    "Reservations": [
        {
            "ReservationId": "r-xxxxxxxxxxxxxxxxx",
            "OwnerId": "xxxxxxxxxxxx",
            "Groups": [],
            "Instances": [
                {
                    "Architecture": "x86_64",
                    "BlockDeviceMappings": [
                        {
                            "DeviceName": "/dev/xvda",
                            "Ebs": {
                                "AttachTime": "2025-04-05T13:34:49+00:00",
                                "DeleteOnTermination": true,
                                "Status": "attached",
                                "VolumeId": "vol-xxxxxxxxxxxxxxxxx"
                            }
                        }
                    ],
                    "ClientToken": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
                    "EbsOptimized": false,
                    "EnaSupport": true,
                    "Hypervisor": "xen",
                    "NetworkInterfaces": [
                        {
                            "Association": {
                                "IpOwnerId": "amazon",
                                "PublicDnsName": "ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com",
                                "PublicIp": "xxx.xxx.xxx.xxx"
                            },
                            "Attachment": {
                                "AttachTime": "2025-04-05T13:34:48+00:00",
                                "AttachmentId": "eni-attach-xxxxxxxxxxxxxxxxx",
                                "DeleteOnTermination": true,
                                "DeviceIndex": 0,
                                "Status": "attached",
                                "NetworkCardIndex": 0
                            },
                            "Description": "",
                            "Groups": [
                                {
                                    "GroupId": "sg-xxxxxxxxxxxxxxxxx",
                                    "GroupName": "default"
                                }
                            ],
                            "Ipv6Addresses": [],
                            "MacAddress": "xx:xx:xx:xx:xx:xx",
                            "NetworkInterfaceId": "eni-xxxxxxxxxxxxxxxxx",
                            "OwnerId": "xxxxxxxxxxxx",
                            "PrivateDnsName": "ip-xxx-xxx-xxx-xxx.ap-northeast-1.compute.internal",
                            "PrivateIpAddress": "xxx.xxx.xxx.xxx",
                            "PrivateIpAddresses": [
                                {
                                    "Association": {
                                        "IpOwnerId": "amazon",
                                        "PublicDnsName": "ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com",
                                        "PublicIp": "xxx.xxx.xxx.xxx"
                                    },
                                    "Primary": true,
                                    "PrivateDnsName": "ip-xxx-xxx-xxx-xxx.ap-northeast-1.compute.internal",
                                    "PrivateIpAddress": "xxx.xxx.xxx.xxx"
                                }
                            ],
                            "SourceDestCheck": true,
                            "Status": "in-use",
                            "SubnetId": "subnet-xxxxxxxxxxxxxxxxx",
                            "VpcId": "vpc-xxxxxxxxxxxxxxxxx",
                            "InterfaceType": "interface",
                            "Operator": {
                                "Managed": false
                            }
                        }
                    ],
                    "RootDeviceName": "/dev/xvda",
                    "RootDeviceType": "ebs",
                    "SecurityGroups": [
                        {
                            "GroupId": "sg-xxxxxxxxxxxxxxxxx",
                            "GroupName": "default"
                        }
                    ],
                    "SourceDestCheck": true,
                    "Tags": [
                        {
                            "Key": "Name",
                            "Value": "xxxxxxxxxx"
                        }
                    ],
                    "VirtualizationType": "hvm",
                    "CpuOptions": {
                        "CoreCount": 1,
                        "ThreadsPerCore": 1
                    },
                    "CapacityReservationSpecification": {
                        "CapacityReservationPreference": "open"
                    },
                    "HibernationOptions": {
                        "Configured": false
                    },
                    "MetadataOptions": {
                        "State": "applied",
                        "HttpTokens": "required",
                        "HttpPutResponseHopLimit": 2,
                        "HttpEndpoint": "enabled",
                        "HttpProtocolIpv6": "disabled",
                        "InstanceMetadataTags": "disabled"
                    },
                    "EnclaveOptions": {
                        "Enabled": false
                    },
                    "BootMode": "uefi-preferred",
                    "PlatformDetails": "Linux/UNIX",
                    "UsageOperation": "RunInstances",
                    "UsageOperationUpdateTime": "2025-04-05T13:34:48+00:00",
                    "PrivateDnsNameOptions": {
                        "HostnameType": "ip-name",
                        "EnableResourceNameDnsARecord": true,
                        "EnableResourceNameDnsAAAARecord": false
                    },
                    "MaintenanceOptions": {
                        "AutoRecovery": "default"
                    },
                    "CurrentInstanceBootMode": "legacy-bios",
                    "NetworkPerformanceOptions": {
                        "BandwidthWeighting": "default"
                    },
                    "Operator": {
                        "Managed": false
                    },
                    "InstanceId": "i-xxxxxxxxxxxxxxxxx",
                    "ImageId": "ami-xxxxxxxxxxxxxxxxx",
                    "State": {
                        "Code": 16,
                        "Name": "running"
                    },
                    "PrivateDnsName": "ip-xxx-xxx-xxx-xxx.ap-northeast-1.compute.internal",
                    "PublicDnsName": "ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com",
                    "StateTransitionReason": "",
                    "AmiLaunchIndex": 0,
                    "ProductCodes": [],
                    "InstanceType": "t2.micro",
                    "LaunchTime": "2025-04-05T13:34:48+00:00",
                    "Placement": {
                        "GroupName": "",
                        "Tenancy": "default",
                        "AvailabilityZone": "ap-northeast-1a"
                    },
                    "Monitoring": {
                        "State": "disabled"
                    },
                    "SubnetId": "subnet-xxxxxxxxxxxxxxxxx",
                    "VpcId": "vpc-xxxxxxxxxxxxxxxxx",
                    "PrivateIpAddress": "xxx.xxx.xxx.xxx",
                    "PublicIpAddress": "xxx.xxx.xxx.xxx"
                }
            ]
        }
    ]
}
```

この中から特定のインスタンスIDやパブリックIPアドレス、特定のタグが付いたインスタンスだけを探し出すのは、目視では大変ですし、スクリプトで処理するにしても一手間かかります。

実は、ここで**Linuxの知識とコマンド**が非常に役立ちます。AWS CLIの強力な機能とLinuxの柔軟なテキスト処理能力を組み合わせることで、AWSの運用管理はもっと効率的で快適になります。

この記事では、AWSを学ぶ際にLinuxスキルを併せて習得することのメリットを、具体的なAWS CLIの活用例を交えてご紹介します。

## なぜAWSと一緒にLinuxを学ぶべきなのか？

1.  **AWSの基盤理解が深まる**: EC2インスタンスの多くはLinuxベースで動作しています。Linuxのファイルシステム、プロセス管理、ネットワーク設定などを理解していると、EC2インスタンス内部で何が起こっているのか、トラブルシューティングが必要な際にどこを見ればよいのかが格段に分かりやすくなります。
2.  **AWS CLIの出力整形が自由自在**: AWS CLIの出力（特にJSON）は、Linuxコマンド（`jq`, `grep`, `awk`, `sed`など）と組み合わせることで、必要な情報だけを抽出したり、見やすい形式や後続処理に適した形式に整形したりできます。
3.  **効率的な運用・自動化**: LinuxのシェルスクリプトとAWS CLIを組み合わせれば、定型的なAWS操作（例えば、特定のタグが付いたインスタンスの一括停止・起動、特定条件のS3オブジェクトのリストアップなど）を自動化できます。
4.  **トラブルシューティング能力の向上**: CloudWatch Logsなどで収集したログデータも、結局はテキストデータです。Linuxのテキスト処理コマンドを駆使すれば、大量のログからエラー箇所や特定のパターンを素早く見つけ出すことができます。
5.  **汎用性の高いスキル**: LinuxスキルはAWSに限りません。オンプレミスのサーバー管理、コンテナ技術（Docker, Kubernetes）、他のクラウドプラットフォームでも必須となる場面が多く、エンジニアとしての基礎体力を高めることに繋がります。

## 実践！LinuxコマンドでAWS CLI出力を整形する

先ほどの `aws ec2 describe-instances` を例に、Linuxコマンド（特に `jq` コマンド）を使って出力を整形してみましょう。

(`jq` はJSONを処理するための非常に強力なコマンドラインツールです。もしインストールされていなければ、`sudo yum install jq` などでインストールしてください。)

### 例1: インスタンスIDと現在の状態だけをリストアップする

```bash
aws ec2 describe-instances --query 'Reservations[].Instances[].[InstanceId, State.Name]' --output text
```

または `jq` を使う場合：

```bash
aws ec2 describe-instances | jq -r '.Reservations[].Instances[] | [.InstanceId, .State.Name] | @tsv'
```

**実行結果イメージ:**

```
i-xxxxxxxxxxxxxxxxx running
i-yyyyyyyyyyyyyyyyy stopped
i-zzzzzzzzzzzzzzzzz running
```

AWS CLIの `--query` オプションや `jq` を使うことで、ネストされたJSONから必要な情報だけを抽出し、タブ区切り（`@tsv`）や指定した形式で表示できます。

### 例2: 特定のタグ（例: `Env=Production`）を持つインスタンスのIDとパブリックIPを表示する

まず、`--filters` オプションで絞り込みます。

```bash
aws ec2 describe-instances --filters "Name=tag:Env,Values=Production" "Name=instance-state-name,Values=running" --query 'Reservations[].Instances[].[InstanceId, PublicIpAddress]' --output text
```

`jq` を使ってフィルタリングと整形を同時に行う場合：

```bash
aws ec2 describe-instances | jq -r '.Reservations[].Instances[] | select(.State.Name == "running") | select(.Tags[]? | .Key == "Env" and .Value == "Production") | [.InstanceId, .PublicIpAddress // "N/A"] | @tsv'
```

**実行結果イメージ:**

```
i-aaaaaaaaaaaaaaaaa 12.34.56.78
i-bbbbbbbbbbbbbbbbb 98.76.54.32
```

`jq` の `select()` 関数を使うことで、より柔軟な条件でフィルタリングできます。また、`// "N/A"` の部分で、パブリックIPが存在しない場合に "N/A" を表示するようにしています。

### 例3: CSV形式で出力して表計算ソフトで使いたい

```bash
aws ec2 describe-instances | jq -r '.Reservations[].Instances[] | [.InstanceId, .InstanceType, .State.Name, (.Tags[]? | select(.Key=="Name") | .Value // "NoNameTag"), .PublicIpAddress // "N/A"] | @csv'
```

**実行結果イメージ (CSV形式):**

```csv
"i-xxxxxxxxxxxxxxxxx","t2.micro","running","MyWebServer","xx.xxx.xxx.xx"
"i-yyyyyyyyyyyyyyyyy","m5.large","stopped","BatchServer","N/A"
"i-zzzzzzzzzzzzzzzzz","t3.small","running","NoNameTag","yy.yyy.yyy.yy"
```

`jq` の `@csv` を使うと、CSV形式で簡単に出力できます。Nameタグがないインスタンスに対応するために `select(.Key=="Name") | .Value // "NoNameTag"` のような処理も可能です。

このように、Linuxコマンド、特に `jq` を使いこなせると、AWS CLIの出力を自由自在に加工し、必要な情報を効率的に取得・活用できます。

## まとめ

AWSは非常に強力で便利なクラウドプラットフォームですが、その機能を最大限に引き出し、効率的に運用管理を行うためには、基盤となるLinuxの知識とスキルが非常に有効です。

* AWS CLIの出力を `jq` や `grep`, `awk` で整形し、必要な情報だけを抽出する。
* シェルスクリプトとAWS CLIを組み合わせて定型作業を自動化する。
* EC2インスタンス内部の挙動を理解し、トラブルシューティングを迅速に行う。

これらはすべて、Linuxスキルがあってこそ実現できることです。

これからAWSを学ぼうとしている方、すでにAWSを使っているけれどCLIの出力に苦労している方は、ぜひLinuxの学習にも時間を投資してみてください。最初は基本的なコマンドからで構いません。`ls`, `cd`, `cat`, `grep`, `ps`, `df`, `ssh` などの基本を抑え、次に `jq` や `awk`、シェルスクリプトへとステップアップしていくことで、AWSの世界がより一層広がり、インフラエンジニアとしての市場価値も高まるはずです。

AWSとLinux、この二つのスキルを掛け合わせることで、よりスマートで効率的なクラウド活用を実現しましょう！