CloudFrontの大量の標準ログオブジェクトに時刻に基づいたプレフィックスを付与してみた
大量のログオブジェクトに対してまとめて時刻に基づいたプレフィックスを付与したい
こんにちは、のんピ(@non____97)です。
皆さんはCloudFrontの標準ログ(S3 Legacy)で出力された大量のログオブジェクトに対して、まとめてに時刻に基づいたプレフィックスを付与したいと思ったことはありますか? 私はあります。
標準ログV2が登場したことによって、S3バケットに出力させる際にパーティションの指定ができるようになりました。
従来は以下記事で紹介しているように、S3バケットにログオブジェクトがPUTされたらLambda関数などを用いてオブジェクトキーを変更を行う手間が必要でした。
やったー
というところですが、元々Lambda関数を用いてプレフィックスを付与していなかった場合は、大量のログオブジェクトがS3バケット内にフラットに存在している形になります。
標準ログV2を導入するにあたって、既存ログオブジェクトのプレフィックスを付与したい場面もあるでしょう。
Lambda関数で大量のログオブジェクトに対して実行すると、それなりの実行時間となり、Lambda関数の課金が気になります。そのため、今回はシェルスクリプトで既存ログオブジェクトにプレフィックスをまとめて付与してみました。
スクリプトの紹介
CloudFrontの標準ログのログオブジェクトはE21YV8QMTCNCR6.2025-01-24-05.15058aee.gz
というように${distribution_id}.${year}-${month}-${day}-${hour}.${id}.gz
というフォーマットです。
標準ログV2のログオブジェクトの一般的なプレフィックスは${distribution_id}/${year}/${month}/${day}/${hour}/
であると思うので、ログオブジェクトのキーから計算することが可能です。
これを利用して各ログオブジェクトからプレフィックスを組み立てます。
スクリプトは以下のとおりです。
#!/bin/bash
set -euo pipefail
###################
# デフォルト設定値
###################
readonly MAX_PARALLEL=20 # s3 mv の同時実行数
readonly RETRY_COUNT=3
readonly RETRY_WAIT=2
readonly LOG_DIR="logs"
DRYRUN=false
DRYRUN_LIMIT=10 # デフォルトの表示件数
TARGET_OBJECT_LIST=""
SHOW_ALL=false # 全件表示フラグ
###################
# 初期化関数
###################
initialize() {
TIMESTAMP="$(date +%Y%m%d_%H%M%S)"
TEMP_DIR="$(mktemp -d)"
readonly TIMESTAMP
readonly TEMP_DIR
readonly LOG_FILE="${LOG_DIR}/move_${TIMESTAMP}.log"
readonly ERROR_LOG="${LOG_DIR}/errors_${TIMESTAMP}.log"
}
###################
# 使用方法の表示
###################
show_usage() {
echo "Usage: $0 -b BUCKET_NAME -a AWS_ACCOUNT_ID [OPTIONS]"
echo ""
echo "Required:"
echo " -b, --bucket BUCKET_NAME S3 bucket name"
echo " -a, --account ACCOUNT_ID AWS account ID"
echo ""
echo "Options:"
echo " -d, --dryrun Show planned moves without executing"
echo " -ol, --object-list Use existing object list instead of fetching from S3"
echo " -n, --limit NUMBER Number of entries to show in dryrun mode (default: 10)"
echo " -A, --show-all Show all entries in dryrun mode"
echo " -h, --help Show this help message"
echo ""
echo "Example:"
echo " $0 -b my-bucket -a 123456789012 --dryrun"
echo " $0 -b my-bucket -a 123456789012 --dryrun --limit 20"
echo " $0 -b my-bucket -a 123456789012 --dryrun --show-all"
echo " $0 --bucket my-bucket --account 123456789012 --file target_object_list.txt"
}
###################
# 引数のバリデーション
###################
validate_args() {
# S3バケットの指定
if [[ -z "${BUCKET_NAME}" ]]; then
echo "Error: Bucket name is required"
show_usage
exit 1
fi
# AWSアカウントIDの指定
if [[ -z "${ACCOUNT_ID}" ]]; then
echo "Error: AWS account ID is required"
show_usage
exit 1
fi
# AWSアカウントIDの形式チェック(12桁の数字)
if ! [[ "${ACCOUNT_ID}" =~ ^[0-9]{12}$ ]]; then
echo "Error: Invalid AWS account ID format. Must be 12 digits."
exit 1
fi
# 移動対象のオブジェクト一覧をまとめたファイル一覧の存在確認
if [[ -n "${TARGET_OBJECT_LIST}" && ! -f "${TARGET_OBJECT_LIST}" ]]; then
echo "Error: Specified file ${TARGET_OBJECT_LIST} does not exist."
exit 1
fi
# dry run時に表示する件数の確認
if [[ -n "${DRYRUN_LIMIT}" ]] && ! [[ "${DRYRUN_LIMIT}" =~ ^[0-9]+$ ]]; then
echo "Error: Limit must be a positive number"
exit 1
fi
}
###################
# 終了時のクリーンアップ処理
###################
cleanup() {
if [[ -d "${TEMP_DIR}" ]]; then
rm -rf "${TEMP_DIR}"
fi
}
###################
# ユーティリティ関数
###################
log() {
local message
message="[$(date '+%Y-%m-%d %H:%M:%S')] $1"
echo "${message}" | tee -a "${LOG_FILE}"
}
get_object_count() {
wc -l <"$1"
}
###################
# 指定したS3バケット内のオブジェクト一覧を取得する関数
###################
fetch_s3_objects() {
local target_object_list
target_object_list="${TEMP_DIR}/target_object_list.txt"
# ターゲットとなるS3ログオブジェクト一覧のファイルが指定された場合
if [[ -n "${TARGET_OBJECT_LIST}" ]]; then
log "Using existing object list: ${TARGET_OBJECT_LIST}"
cp "${TARGET_OBJECT_LIST}" "${target_object_list}"
# ターゲットとなるS3ログオブジェクト一覧のファイルが指定されていない場合
else
log "Checking objects in bucket: ${BUCKET_NAME}"
# バケットが存在し、アクセス可能か確認
if ! aws s3api head-bucket --bucket "${BUCKET_NAME}" >/dev/null 2>&1; then
log "Error: Unable to access bucket: ${BUCKET_NAME}"
exit 1
fi
# バケット直下の.gzオブジェクトを確認し、0なら終了
local first_gz_object
first_gz_object=$(aws s3api list-objects-v2 \
--bucket "${BUCKET_NAME}" \
--delimiter "/" \
--query "Contents[?contains(Key, '/') == \`false\` && ends_with(Key, '.gz')][Key]" \
--max-items 1 \
--output text 2>/dev/null || echo "")
if [[ "${first_gz_object}" == "None" ]] || [[ -z "${first_gz_object}" ]]; then
log "No .gz object found in bucket root: ${BUCKET_NAME}"
exit 0
fi
log "Fetching object from bucket: ${BUCKET_NAME}"
aws s3 ls "s3://${BUCKET_NAME}/" | grep '\.gz$' | awk '{print $4}' >"${target_object_list}"
fi
local target_objects_length
target_objects_length=$(get_object_count "${target_object_list}")
log "Total objects found: ${target_objects_length}"
}
###################
# S3オブジェクトから移動先のオブジェクトのプレフィックスを計算する関数
###################
parse_cloudfront_log_prefix() {
local object_key="$1"
local distribution_id
local timestamp
local year
local month
local day
local hour
distribution_id=$(echo "${object_key}" | cut -d'.' -f1)
timestamp=$(echo "${object_key}" | grep -o '[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{2\}')
year=$(echo "${timestamp}" | cut -d'-' -f1)
month=$(echo "${timestamp}" | cut -d'-' -f2)
day=$(echo "${timestamp}" | cut -d'-' -f3)
hour=$(echo "${timestamp}" | cut -d'-' -f4)
echo "AWSLogs/${ACCOUNT_ID}/CloudFront/${distribution_id}/${year}/${month}/${day}/${hour}/"
}
###################
# 各オブジェクトに標準的なプレフィックスを付与する関数
###################
add_standard_prefix_to_log() {
local object_key="$1"
local new_prefix
new_prefix=$(parse_cloudfront_log_prefix "${object_key}")
local source_object_key="s3://${BUCKET_NAME}/${object_key}"
local target_object_key="s3://${BUCKET_NAME}/${new_prefix}${object_key}"
if [[ "${DRYRUN}" = true ]]; then
aws s3 mv "${source_object_key}" "${target_object_key}" --dryrun
return 0
fi
for attempt in $(seq 1 ${RETRY_COUNT}); do
if [[ ${attempt} -gt 1 ]]; then
log "Retry attempt ${attempt} for ${object_key}"
sleep ${RETRY_WAIT}
fi
if aws s3 mv "${source_object_key}" "${target_object_key}" 2>/dev/null; then
echo "${object_key}" >>"${TEMP_DIR}/processed.txt"
return 0
fi
done
echo "${object_key}" >>"${ERROR_LOG}"
return 1
}
###################
# 指定したS3バケット内のオブジェクトに対して処理を行う関数
###################
process_cloudfront_logs() {
local target_objects_length
target_objects_length=$(get_object_count "${TEMP_DIR}/target_object_list.txt")
log "Total objects to process: ${target_objects_length}"
local processed=0
local pids=()
while IFS= read -r object_key; do
if [[ "${DRYRUN}" = false || "${SHOW_ALL}" = true || ${processed} -lt ${DRYRUN_LIMIT} ]]; then
# バックグラウンドで処理実行
add_standard_prefix_to_log "${object_key}" &
pids+=($!)
# 並列実行数の上限に達したら待機
if ((${#pids[@]} >= MAX_PARALLEL)); then
wait "${pids[0]}"
pids=("${pids[@]:1}")
fi
fi
: $((processed++))
# 100件ごとに進捗を表示
if [[ "${DRYRUN}" = false && $((processed % 100)) -eq 0 ]]; then
log "Progress: ${processed} objects processed"
fi
done <"${TEMP_DIR}/target_object_list.txt"
# 残りのジョブの完了を待機
wait
# 結果の集計
local completed
completed=$(get_object_count "${TEMP_DIR}/processed.txt" 2>/dev/null || echo 0)
local errors
errors=$(get_object_count "${ERROR_LOG}" 2>/dev/null || echo 0)
log "$(if [[ "${DRYRUN}" = true ]]; then echo "Dry run"; else echo "Migration"; fi) completed"
if [[ "${DRYRUN}" = false ]]; then
log "Objects processed: ${completed}"
log "Errors: ${errors}"
fi
}
###################
# メイン処理
###################
main() {
log "Script started with bucket: ${BUCKET_NAME}, account: ${ACCOUNT_ID}"
log "Mode: $(if [[ "${DRYRUN}" = true ]]; then echo "Dry run"; else echo "Execution"; fi)"
fetch_s3_objects
# 実行モードの場合、確認を求める
if [[ "${DRYRUN}" = false ]]; then
echo ""
echo "This will move objects in bucket: ${BUCKET_NAME}"
read -rp "Are you sure you want to proceed? [y/N] " response
if [[ ! "${response}" =~ ^[Yy]$ ]]; then
log "Operation cancelled by user"
exit 0
fi
log "Proceeding with object movement"
fi
process_cloudfront_logs
}
###################
# コマンドライン引数の処理
###################
while [[ $# -gt 0 ]]; do
case $1 in
-b | --bucket)
BUCKET_NAME="$2"
shift 2
;;
-a | --account)
ACCOUNT_ID="$2"
shift 2
;;
-d | --dryrun)
DRYRUN=true
shift
;;
-ol | --object-list)
TARGET_OBJECT_LIST="$2"
shift 2
;;
-n | --limit)
DRYRUN_LIMIT="$2"
shift 2
;;
-A | --show-all)
SHOW_ALL=true
shift
;;
-h | --help)
show_usage
exit 0
;;
*)
echo "Error: Unknown option $1"
show_usage
exit 1
;;
esac
done
# 引数のバリデーション
validate_args
# 初期設定
initialize
trap 'cleanup' EXIT
mkdir -p "${LOG_DIR}"
# メイン処理の実行
main
はい、せっかくなのでdryrun機能や、ログオブジェクト一覧を保存したファイルを読み込ませて実行する機能も追加してみました。
また、一件一件実行すると非常に時間がかかるため、MAX_PARALLEL
の数分だけバックグラウンドプロセスを用いた並列処理を行うようにしています。
やってみた
dry run
実際に試してみます。
まず、dry runです。
対象のS3バケット上には以下のようにログオブジェクトが存在しています。
> s3-tree aurora-postgresql-log
aurora-postgresql-log
├── E21YV8QMTCNCR6.2025-01-24-05.15058aee.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー10.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー11.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー12.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー13.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー14.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー15.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー16.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー2.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー3.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー4.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー5.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー6.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー7.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー8.gz
├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー9.gz
├── E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー17.gz
├── E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー18.gz
├── E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー19.gz
├── E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー20.gz
├── E21YV8QMTCNCR6.2025-01-25-06.e256b268のコピー21.gz
├── E21YV8QMTCNCR6.2025-01-26-06.e256b268のコピー22.gz
└── E21YV8QMTCNCR6.2025-01-27-23.e256b268のコピー23.gz
dry runで実行してみます。
> bash move_cloudfront_s3_legacy_logs.sh \
--bucket aurora-postgresql-log \
--account <AWSアカウントID> \
--dryrun
[2025-02-16 10:02:38] Script started with bucket: aurora-postgresql-log, account: <AWSアカウントID>
[2025-02-16 10:02:38] Mode: Dry run
[2025-02-16 10:02:38] Checking objects in bucket: aurora-postgresql-log
[2025-02-16 10:02:41] Fetching object from bucket: aurora-postgresql-log
[2025-02-16 10:02:42] Total objects found: 25
[2025-02-16 10:02:42] Total objects to process: 25
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー12.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー12.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.15058aee.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.15058aee.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー15.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー15.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー11.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー11.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー13.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー13.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー16.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー16.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー14.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー14.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー10.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー10.gz
[2025-02-16 10:02:44] Dry run completed
25件10件表示されました。
いずれも意図したプレフィックスが付与されています。
念のため全件確認したい場合は--show-all
オプションを付与して下さい。こちらのオプションを付与すると、全件のdry run結果を確認することも可能です。
> bash move_cloudfront_s3_legacy_logs.sh \
--bucket aurora-postgresql-log \
--account <AWSアカウントID> \
--dryrun \
--show-all
[2025-02-16 10:09:26] Script started with bucket: aurora-postgresql-log, account: <AWSアカウントID>
[2025-02-16 10:09:26] Mode: Dry run
[2025-02-16 10:09:26] Checking objects in bucket: aurora-postgresql-log
[2025-02-16 10:09:29] Fetching object from bucket: aurora-postgresql-log
[2025-02-16 10:09:31] Total objects found: 25
[2025-02-16 10:09:31] Total objects to process: 25
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー4.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー4.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー15.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー15.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー16.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー16.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー12.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー12.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー7.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー7.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー18.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/06/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー18.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー8.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー8.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー17.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/06/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー17.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.15058aee.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.15058aee.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー6.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー6.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー10.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー10.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー5.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー5.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー14.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー14.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー3.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー3.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー11.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー11.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー2.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー2.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー9.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー9.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー13.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー13.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-25-06.e256b268のコピー21.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/25/06/E21YV8QMTCNCR6.2025-01-25-06.e256b268のコピー21.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー19.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/06/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー19.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-26-06.e256b268のコピー22.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/26/06/E21YV8QMTCNCR6.2025-01-26-06.e256b268のコピー22.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー20.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/06/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー20.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-27-23.e256b268のコピー23.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/27/23/E21YV8QMTCNCR6.2025-01-27-23.e256b268のコピー23.gz
[2025-02-16 10:09:35] Dry run completed
また、--limit <件数>
のオプションを付与すると、指定した件数だけdry runを実行します。
bash move_cloudfront_s3_legacy_logs.sh \
--bucket aurora-postgresql-log \
--account <AWSアカウントID> \
--dryrun \
--limit 1
[2025-02-16 10:02:52] Script started with bucket: aurora-postgresql-log, account: <AWSアカウントID>
[2025-02-16 10:02:52] Mode: Dry run
[2025-02-16 10:02:52] Checking objects in bucket: aurora-postgresql-log
[2025-02-16 10:02:54] Fetching object from bucket: aurora-postgresql-log
[2025-02-16 10:02:56] Total objects found: 25
[2025-02-16 10:02:56] Total objects to process: 25
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.15058aee.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.15058aee.gz
[2025-02-16 10:02:57] Dry run completed
実行モード
それでは実際にプレフィックスを付与するように実行してみます。
> bash move_cloudfront_s3_legacy_logs.sh \
--bucket aurora-postgresql-log \
--account <AWSアカウントID>
[2025-02-16 10:10:13] Script started with bucket: aurora-postgresql-log, account: <AWSアカウントID>
[2025-02-16 10:10:13] Mode: Execution
[2025-02-16 10:10:13] Checking objects in bucket: aurora-postgresql-log
[2025-02-16 10:10:15] Fetching object from bucket: aurora-postgresql-log
[2025-02-16 10:10:16] Total objects found: 25
This will move objects in bucket: aurora-postgresql-log
Are you sure you want to proceed? [y/N] y
[2025-02-16 10:10:21] Proceeding with object movement
[2025-02-16 10:10:22] Total objects to process: 25
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.15058aee.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.15058aee.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー11.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー11.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー7.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー7.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー10.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー10.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー18.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/06/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー18.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー16.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー16.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー17.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/06/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー17.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー15.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー15.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー14.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー14.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー5.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー5.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー4.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー4.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー9.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー9.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー3.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー3.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー8.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー8.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー6.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー6.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー13.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー13.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー2.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー2.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー12.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー12.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー19.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/06/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー19.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー20.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/06/E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー20.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-26-06.e256b268のコピー22.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/26/06/E21YV8QMTCNCR6.2025-01-26-06.e256b268のコピー22.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-25-06.e256b268のコピー21.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/25/06/E21YV8QMTCNCR6.2025-01-25-06.e256b268のコピー21.gz
move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-27-23.e256b268のコピー23.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/27/23/E21YV8QMTCNCR6.2025-01-27-23.e256b268のコピー23.gz
[2025-02-16 10:10:28] Migration completed
[2025-02-16 10:10:28] objects processed: 25
[2025-02-16 10:10:28] Errors: 0
正常に実行が完了しました。
S3バケット内のオブジェクト一覧を確認してみます。
> s3-tree aurora-postgresql-log
aurora-postgresql-log
└── AWSLogs
└── <AWSアカウントID>
└── CloudFront
└── E21YV8QMTCNCR6
└── 2025
└── 01
├── 24
│ ├── 05
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.15058aee.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー10.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー11.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー12.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー13.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー14.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー15.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー16.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー2.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー3.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー4.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー5.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー6.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー7.gz
│ │ ├── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー8.gz
│ │ └── E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー9.gz
│ └── 06
│ ├── E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー17.gz
│ ├── E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー18.gz
│ ├── E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー19.gz
│ └── E21YV8QMTCNCR6.2025-01-24-06.e256b268のコピー20.gz
├── 25
│ └── 06
│ └── E21YV8QMTCNCR6.2025-01-25-06.e256b268のコピー21.gz
├── 26
│ └── 06
│ └── E21YV8QMTCNCR6.2025-01-26-06.e256b268のコピー22.gz
└── 27
└── 23
└── E21YV8QMTCNCR6.2025-01-27-23.e256b268のコピー23.gz
はい、各オブジェクトに意図したプレフィックスが付与されていますね。
事前に用意したオブジェクトリストを用いて実行
事前に用意したオブジェクトリストを用いて実行することも可能です。
以下のようにオブジェクト名のリストを保存したテキストファイルを用意します。
E21YV8QMTCNCR6.2025-01-24-05.15058aee.gz
E21YV8QMTCNCR6.2025-01-24-05.e256b268.gz
E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー.gz
E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー10.gz
E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー11.gz
E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー12.gz
E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー13.gz
こちらを指定して実行します。
> bash move_cloudfront_s3_legacy_logs.sh \
--bucket aurora-postgresql-log \
--account <AWSアカウントID> \
--object-list target.txt \
--dryrun
[2025-02-17 09:09:02] Script started with bucket: aurora-postgresql-log, account: <AWSアカウントID>
[2025-02-17 09:09:02] Mode: Dry run
[2025-02-17 09:09:02] Using existing object list: target.txt
[2025-02-17 09:09:02] Total objects found: 7
[2025-02-17 09:09:02] Total objects to process: 7
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー11.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー11.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー10.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー10.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー12.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー12.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー13.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268のコピー13.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.15058aee.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.15058aee.gz
(dryrun) move: s3://aurora-postgresql-log/E21YV8QMTCNCR6.2025-01-24-05.e256b268.gz to s3://aurora-postgresql-log/AWSLogs/<AWSアカウントID>/CloudFront/E21YV8QMTCNCR6/2025/01/24/05/E21YV8QMTCNCR6.2025-01-24-05.e256b268.gz
[2025-02-17 09:09:04] Dry run completed
指定したログオブジェクトに対してdry runが実行されたことが分かります。
標準ログV2移行後の形式に合わせたい場合に
CloudFrontの大量の標準ログオブジェクトに時刻に基づいたプレフィックスを付与してみました。
標準ログV2移行後の形式に合わせたい場合に使用してみて下さい。
この記事が誰かの助けになれば幸いです。
以上、クラウド事業本部 コンサルティング部の のんピ(@non____97)でした!