📑
AWS CLI の history 機能
- AWS CLI の history 機能を使うことで、過去に実行したコマンドや実行結果を記録しておくことができる
- AWS CLI の実行結果を記録しておきたい場合や、自動的に実行しているコマンドで稀にエラーが発生しているといった場合の調査に役立つかも
AWS CLI の history 機能とは
- AWS CLI v1.13.0 から追加された機能
- AWS CLI で実行したコマンドの履歴や実行結果を保存してくれる
history 機能の使い方
AWS CLI Command Reference に history コマンドの使い方について情報がある
サクッと試す方法
# history 機能を有効化
# ~/.aws/config に "cli_history = enabled" が設定される
aws configure set cli_history enabled
# 任意の AWS CLI コマンドを実行
aws sts get-caller-identity
aws ec2 describe-regions
# history リスト表示
aws history list
# 直前に実行したコマンドの history を表示
aws history show
# 過去に実行したコマンドを 1つ 指定して history を表示
# xxx には aws history list で表示される UUID (command_id) を指定する
aws history show xxx
# history 機能を無効化
# ~/.aws/config に "cli_history = " が設定される
aws configure set ''
実際の実行例
$ aws configure set cli_history enabled
$ aws sts get-caller-identity
{
"Account": "123456789012",
"UserId": "xxx",
"Arn": "arn:aws:iam::123456789012:user/myusername"
}
$ aws ec2 describe-regions
{
"Regions": [
{
"OptInStatus": "opt-in-not-required",
"Endpoint": "ec2.eu-north-1.amazonaws.com",
"RegionName": "eu-north-1"
},
...
]
}
$ aws history list
445378f1-f5dd-457f-ac99-75d2c7d45a75 2021-03-11 03:32:31 PM ec2 describe-regions 0
5c62d327-fd3f-4eef-a2ff-4ef9bbc773d3 2021-03-11 03:32:24 PM sts get-caller-identity 0
$ aws history show
AWS CLI command entered
at time: 2021-03-11 15:32:31.114
with AWS CLI version: aws-cli/1.18.217 Python/2.7.18 Linux/4.14.219-164.354.amzn2.x86_64 botocore/1.19.57
with arguments: [u'ec2', u'describe-regions']
[0] API call made
at time: 2021-03-11 15:32:31.433
to service: ec2
using operation: DescribeRegions
with parameters: {}
[0] HTTP request sent
at time: 2021-03-11 15:32:31.436
to URL: https://ec2.ap-northeast-1.amazonaws.com/
with method: POST
with headers: {
"Authorization": "AWS4-HMAC-SHA256 Credential=xxx/20210311/ap-northeast-1/ec2/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=b83f...
",
"Content-Length": "41",
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
"User-Agent": "aws-cli/1.18.217 Python/2.7.18 Linux/4.14.219-164.354.amzn2.x86_64 botocore/1.19.57",
"X-Amz-Date": "20210311T153231Z"
}
with body: Action=DescribeRegions&Version=2016-11-15
[0] HTTP response received
at time: 2021-03-11 15:32:31.501
with status code: 200
with headers: {
"Cache-Control": "no-cache, no-store",
"Content-Length": "3875",
"Content-Type": "text/xml;charset=UTF-8",
"Date": "Thu, 11 Mar 2021 15:32:31 GMT",
"Server": "AmazonEC2",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains",
"vary": "accept-encoding",
"x-amzn-requestid": "763badf3-0ac5-4c0c-8ae5-caa0665f25bb"
}
with body: <?xml version="1.0" ?>
<DescribeRegionsResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
<requestId>763badf3-0ac5-4c0c-8ae5-caa0665f25bb</requestId>
<regionInfo>
<item>
<regionName>eu-north-1</regionName>
<regionEndpoint>ec2.eu-north-1.amazonaws.com</regionEndpoint>
<optInStatus>opt-in-not-required</optInStatus>
</item>
...
[0] HTTP response parsed
at time: 2021-03-11 15:32:31.503
parsed to: {
"Regions": [
{
"Endpoint": "ec2.eu-north-1.amazonaws.com",
"OptInStatus": "opt-in-not-required",
"RegionName": "eu-north-1"
},
...
],
"ResponseMetadata": {
"HTTPHeaders": {
"cache-control": "no-cache, no-store",
"content-length": "3875",
"content-type": "text/xml;charset=UTF-8",
"date": "Thu, 11 Mar 2021 15:32:31 GMT",
"server": "AmazonEC2",
"strict-transport-security": "max-age=31536000; includeSubDomains",
"vary": "accept-encoding",
"x-amzn-requestid": "763badf3-0ac5-4c0c-8ae5-caa0665f25bb"
},
"HTTPStatusCode": 200,
"RequestId": "763badf3-0ac5-4c0c-8ae5-caa0665f25bb"
}
}
...
AWS CLI command exited
at time: 2021-03-11 15:32:31.507
with return code: 0
$ aws history show 5c62d327-fd3f-4eef-a2ff-4ef9bbc773d3
AWS CLI command entered
at time: 2021-03-11 15:32:24.458
with AWS CLI version: aws-cli/1.18.217 Python/2.7.18 Linux/4.14.219-164.354.amzn2.x86_64 botocore/1.19.57
with arguments: [u'sts', u'get-caller-identity']
[0] API call made
at time: 2021-03-11 15:32:24.560
to service: sts
using operation: GetCallerIdentity
with parameters: {}
[0] HTTP request sent
at time: 2021-03-11 15:32:24.563
to URL: https://sts.amazonaws.com/
with method: POST
with headers: {
"Authorization": "AWS4-HMAC-SHA256 Credential=xxx/20210311/us-east-1/sts/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=50c0...",
"Content-Length": "43",
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
"User-Agent": "aws-cli/1.18.217 Python/2.7.18 Linux/4.14.219-164.354.amzn2.x86_64 botocore/1.19.57",
"X-Amz-Date": "20210311T153224Z"
}
with body: Action=GetCallerIdentity&Version=2011-06-15
[0] HTTP response received
at time: 2021-03-11 15:32:25.252
with status code: 200
with headers: {
"Content-Length": "407",
"Content-Type": "text/xml",
"Date": "Thu, 11 Mar 2021 15:32:24 GMT",
"x-amzn-RequestId": "e732121e-3849-4cfe-afb2-baa0349b2936"
}
with body: <?xml version="1.0" ?>
<GetCallerIdentityResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<GetCallerIdentityResult>
<Arn>arn:aws:iam::123456789012:user/myusername</Arn>
<UserId>xxx</UserId>
<Account>123456789012</Account>
</GetCallerIdentityResult>
<ResponseMetadata>
<RequestId>e732121e-3849-4cfe-afb2-baa0349b2936</RequestId>
</ResponseMetadata>
</GetCallerIdentityResponse>
[0] HTTP response parsed
at time: 2021-03-11 15:32:25.254
parsed to: {
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/myusername",
"ResponseMetadata": {
"HTTPHeaders": {
"content-length": "407",
"content-type": "text/xml",
"date": "Thu, 11 Mar 2021 15:32:24 GMT",
"x-amzn-requestid": "e732121e-3849-4cfe-afb2-baa0349b2936"
},
"HTTPStatusCode": 200,
"RequestId": "e732121e-3849-4cfe-afb2-baa0349b2936"
},
"UserId": "xxx"
}
AWS CLI command exited
at time: 2021-03-11 15:32:25.256
with return code: 0
history の保存挙動について
-
~/.aws/cli/history/history.db
に history データが保存される -
history.db
の実体は SQLite 3 なのでsqlite3
コマンド等で操作することが可能
保存先発掘の軌跡
tree
コマンドでディレクトリを見た感じ ~/.aws/cli/history/history.db
がそれっぽい
$ tree ~/.aws
/home/ec2-user/.aws
├── cli
│ └── history
│ └── history.db
├── config
└── credentials
file
コマンドで見てみると SQLite であることが分かる
$ file ~/.aws/cli/history/history.db
/home/ec2-user/.aws/cli/history/history.db: SQLite 3.x database
sqlite3
コマンドで中身を見てみる
$ sqlite3 ~/.aws/cli/history/history.db
SQLite version 3.34.0 2020-12-01 16:14:00
Enter ".help" for usage hints.
sqlite> .tables
records
history.db
の中身は records
という Table のみ。
SELECT で中身を見てみる。
sqlite> SELECT * FROM records;
5c62d327-fd3f-4eef-a2ff-4ef9bbc773d3||CLI|CLI_VERSION|1615476744458|"aws-cli/1.18.217 Python/2.7.18 Linux/4.14.219-164.354.amzn2.x86_64 botocore/1.19.57"
5c62d327-fd3f-4eef-a2ff-4ef9bbc773d3||CLI|CLI_ARGUMENTS|1615476744461|["sts", "get-caller-identity"]
5c62d327-fd3f-4eef-a2ff-4ef9bbc773d3|a399c21a-22ff-47a9-ad57-baa8f826b855|BOTOCORE|API_CALL|1615476744560|{"operation": "GetCallerIdentity", "params": {}, "service": "sts"}
5c62d327-fd3f-4eef-a2ff-4ef9bbc773d3|a399c21a-22ff-47a9-ad57-baa8f826b855|BOTOCORE|HTTP_REQUEST|1615476744563|{"url": "https://sts.amazonaws.com/", "headers": {"Content-Length": "43", "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", "X-Amz-Date": "20210311T153224Z", "Authorization": "AWS4-HMAC-SHA256 Credential=xxx/20210311/us-east-1/sts/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=50c00412063c2d749e992394465f965b19a0bc313ae135b852af5cd3807cfe21", "User-Agent": "aws-cli/1.18.217 Python/2.7.18 Linux/4.14.219-164.354.amzn2.x86_64 botocore/1.19.57"}, "body": "Action=GetCallerIdentity&Version=2011-06-15", "method": "POST", "streaming": false}
5c62d327-fd3f-4eef-a2ff-4ef9bbc773d3|a399c21a-22ff-47a9-ad57-baa8f826b855|BOTOCORE|HTTP_RESPONSE|1615476745252|{"body": "<GetCallerIdentityResponse xmlns=\"https://sts.amazonaws.com/doc/2011-06-15/\">\n <GetCallerIdentityResult>\n <Arn>arn:aws:iam::123456789012:user/myusername</Arn>\n <UserId>xxx</UserId>\n <Account>123456789012</Account>\n </GetCallerIdentityResult>\n <ResponseMetadata>\n <RequestId>e732121e-3849-4cfe-afb2-baa0349b2936</RequestId>\n </ResponseMetadata>\n</GetCallerIdentityResponse>\n", "headers": {"x-amzn-RequestId": "e732121e-3849-4cfe-afb2-baa0349b2936", "Date": "Thu, 11 Mar 2021 15:32:24 GMT", "Content-Length": "407", "Content-Type": "text/xml"}, "streaming": false, "context": {"operation_name": "GetCallerIdentity"}, "status_code": 200}
5c62d327-fd3f-4eef-a2ff-4ef9bbc773d3|a399c21a-22ff-47a9-ad57-baa8f826b855|BOTOCORE|PARSED_RESPONSE|1615476745254|{"Account": "123456789012", "UserId": "xxx", "ResponseMetadata": {"HTTPStatusCode": 200, "RequestId": "e732121e-3849-4cfe-afb2-baa0349b2936", "HTTPHeaders": {"x-amzn-requestid": "e732121e-3849-4cfe-afb2-baa0349b2936", "date": "Thu, 11 Mar 2021 15:32:24 GMT", "content-length": "407", "content-type": "text/xml"}}, "Arn": "arn:aws:iam::123456789012:user/myusername"}
5c62d327-fd3f-4eef-a2ff-4ef9bbc773d3||CLI|CLI_RC|1615476745256|0
445378f1-f5dd-457f-ac99-75d2c7d45a75||CLI|CLI_VERSION|1615476751114|"aws-cli/1.18.217 Python/2.7.18 Linux/4.14.219-164.354.amzn2.x86_64 botocore/1.19.57"
445378f1-f5dd-457f-ac99-75d2c7d45a75||CLI|CLI_ARGUMENTS|1615476751117|["ec2", "describe-regions"]
445378f1-f5dd-457f-ac99-75d2c7d45a75|03c96ec0-0139-4eef-9537-d5fb472f3c9d|BOTOCORE|API_CALL|1615476751433|{"operation": "DescribeRegions", "params": {}, "service": "ec2"}
445378f1-f5dd-457f-ac99-75d2c7d45a75|03c96ec0-0139-4eef-9537-d5fb472f3c9d|BOTOCORE|HTTP_REQUEST|1615476751436|{"url": "https://ec2.ap-northeast-1.amazonaws.com/", "headers": {"Content-Length": "41", "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", "X-Amz-Date": "20210311T153231Z", "Authorization": "AWS4-HMAC-SHA256 Credential=xxx/20210311/ap-northeast-1/ec2/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=b83f12fbe5d2cc6a88444443076671a5009da7e59289ab604317b0fed3d80138", "User-Agent": "aws-cli/1.18.217 Python/2.7.18 Linux/4.14.219-164.354.amzn2.x86_64 botocore/1.19.57"}, "body": "Action=DescribeRegions&Version=2016-11-15", "method": "POST", "streaming": false}
445378f1-f5dd-457f-ac99-75d2c7d45a75|03c96ec0-0139-4eef-9537-d5fb472f3c9d|BOTOCORE|HTTP_RESPONSE|1615476751501|{"body": "...", "headers": {"x-amzn-requestid": "763badf3-0ac5-4c0c-8ae5-caa0665f25bb", "Content-Length": "3875", "Strict-Transport-Security": "max-age=31536000; includeSubDomains", "vary": "accept-encoding", "Server": "AmazonEC2", "Cache-Control": "no-cache, no-store", "Date": "Thu, 11 Mar 2021 15:32:31 GMT", "Content-Type": "text/xml;charset=UTF-8"}, "streaming": false, "context": {"operation_name": "DescribeRegions"}, "status_code": 200}
445378f1-f5dd-457f-ac99-75d2c7d45a75|03c96ec0-0139-4eef-9537-d5fb472f3c9d|BOTOCORE|PARSED_RESPONSE|1615476751503|{"Regions": ..., "ResponseMetadata": {"HTTPStatusCode": 200, "RequestId": "763badf3-0ac5-4c0c-8ae5-caa0665f25bb", "HTTPHeaders": {"x-amzn-requestid": "763badf3-0ac5-4c0c-8ae5-caa0665f25bb", "content-length": "3875", "strict-transport-security": "max-age=31536000; includeSubDomains", "vary": "accept-encoding", "server": "AmazonEC2", "cache-control": "no-cache, no-store", "date": "Thu, 11 Mar 2021 15:32:31 GMT", "content-type": "text/xml;charset=UTF-8"}}}
445378f1-f5dd-457f-ac99-75d2c7d45a75||CLI|CLI_RC|1615476751507|0
history
コマンドで表示されるデータが保存されていることが発掘できた
AWS CLI の実装箇所としては https://github.com/aws/aws-cli/blob/develop/awscli/customizations/history/db.py に SQLite への書き込みを行う DatabaseRecordWriter クラスが定義されている
history 機能の使い所を考察
CloudTrail に未対応な AWS API 呼び出し状況の記録
- AWS CLI のコマンド実行は、基本的に AWS API 呼び出しを行うので、実行履歴を確認するなら CloudTrail が使用できる
- しかし、すべての AWS API が CloudTrail に対応している訳ではない
-
history
コマンドは CloudTrail 対応状況に関係なく、 AWS CLI から実行された AWS API 呼び出しを記録できる点が便利
トラブルシューティング
- AWS CLI を使う場合のトラブルシューティングとしては
--debug
オプションを指定して実行するのが一般的(?) - しかし、 AWS CLI のコマンド実行を自動化しているような場合に
--debug
オプションを指定するには、自動化内容を修正する必要が生じたり、出力されるログ内容が膨大になるといった問題がある - history 機能の場合、とりあえずで設定を仕込んでおけるので手軽に導入できる
この記事の内容を試した環境
$ cat /etc/os-release
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
$ aws --version
aws-cli/1.18.217 Python/2.7.18 Linux/4.14.219-164.354.amzn2.x86_64 botocore/1.19.57
Discussion