RDSのインスタンスに保存されているログをダウンロードする方法として、ググると download_db_log_file_portion
を使う方法がたくさん出てきます。しかし、問題がありましたので、 downloadCompleteLogFile
というAPIを使うスクリプトを書きました。
download_db_log_file_portion の問題点:
- awscliだと途中で途切れる(ページネーションしても途切れてしまう)
- APIを直接叩くにも細かく分割が必要で、ダウンロードに時間がかかる
- 文字化けする(日本語の含まれる場合に ? に置き換えられてしまう)
downloadCompleteLogFile
であればいずれの問題も解消します。
downloadCompleteLogFileにアクセスするスクリプト
downloadCompleteLogFile
にアクセスするには自力でSigV4署名する必要があります。IAMユーザまたはIAMロールが必要です。
このPythonスクリプトはダウンロードするcurlコマンドをSigV4署名して作成します。Pythonスクリプト自身はダウンロードを実行しませんので、作成されたcurlコマンドをあとから実行する使い方です。
~/.aws/config
, ~/.aws/credentials
に適切な権限の設定があることが前提です。
import boto3
from botocore.awsrequest import AWSRequest
import botocore.auth as auth
import urllib.request
import pprint
profile = "default"
instance_id = "database-1"
region = "ap-northeast-1"
session = boto3.session.Session(profile_name = profile)
credentials = session.get_credentials()
sigv4auth = auth.SigV4Auth(credentials, "rds", region)
rds_client = session.client('rds')
files = rds_client.describe_db_log_files(DBInstanceIdentifier = instance_id)
for file in files["DescribeDBLogFiles"]:
file_name = file["LogFileName"]
# ファイル名からダウンロード除外を判定
if not file_name.startswith("error/"):
continue
if file_name == "error/postgres.log":
continue
# downloadCompleteLogFileのAPIのURL
remote_host = "rds." + region + ".amazonaws.com"
url = "https://" + remote_host + "/v13/downloadCompleteLogFile/" + instance_id + "/" + file_name
# SigV4署名
awsreq = AWSRequest(method = "GET", url = url)
sigv4auth.add_auth(awsreq)
req = urllib.request.Request(url, headers = {
"Authorization": awsreq.headers['Authorization'],
"Host": remote_host,
"X-Amz-Date": awsreq.context['timestamp'],
})
# ダウンロード進捗用のechoコマンド
echo_cmd = "echo '" + file_name + "' >&2"
print(echo_cmd)
# curlコマンド
header = " ".join(["-H '" + k + ": " + v + "'" for (k, v) in req.headers.items()])
cmd = "curl " + header + " '" + url + "'"
print(cmd)
このPythonは次のような出力をします。
echo 'error/postgresql.log.2020-11-05-23' >&2
curl -H 'Authorization: AWS4-HMAC-SHA256 Credential=AKIAXXXXXXXXXXXXXXXX/20201105/ap-northeast-1/rds/aws4_request, SignedHeaders=host;x-amz-date, Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' -H 'Host: rds.ap-northeast-1.amazonaws.com' -H 'X-amz-date: 20201105T231307Z' 'https://rds.ap-northeast-1.amazonaws.com/v13/downloadCompleteLogFile/database-1/error/postgresql.log.2020-11-05-23'
これをBashで実行します。
$ python download-rds-log.py | bash > log.txt
curlコマンドを出力しているので、並列実行などに改良することも可能です。改良しなくてもdownload_db_log_file_portionを使うよりはずっと高速です。
リンク
SigV4署名については以下の記事にも書きました。