[AWS]「S3」コマンド
1. AWS CLI
(1) ls
# aws s3 ls
# aws s3 ls s3://{バケット名}
# aws s3 ls s3://{バケット名}/{フォルダ名}/
※フォルダ名の後に必ず「/」を付けること。
■プレフィックスのみに絞り込む場合
末尾がスラッシュのもののみに絞り込むことでプレフィックスのみをリスト
# aws s3 ls s3://{バケット名}/{フォルダ名}/ | grep '/$'
件数を取得
# aws s3 ls s3://{バケット名}/{フォルダ名}/ | grep '/$' | wc -l
(2) フォルダの存在確認
if aws s3 ls "s3://${バケット名}/${フォルダ名}/" >/dev/null 2>&1; then
echo "S3フォルダは既に存在します"
else
echo "S3フォルダが存在しません"
fi
(3) ワイルドカードでコピー
S3からローカルにコピー
# aws s3 cp s3://{バケット名}/{フォルダ名}/ . --recursive --exclude "*" --include "*.log"
ローカルからS3にコピー
# aws s3 cp ./ s3://{バケット名}/{フォルダ名}/ --recursive --exclude "*" --include "*.log"
(9) フォルダ作成
# aws s3api put-object --bucket (バケット名) --key "(フォルダ名)/"
(10) フォルダ削除
# aws s3 rm s3://(バケット名)/(フォルダ名)/ --recursive
(11) フォルダを圧縮してS3に作成
# tar cfz - (圧縮するフォルダ名) | aws s3 cp - s3://(バケット名)/(フォルダ名)/(圧縮するフォルダ名).tar.gz
※「-」は標準入力を示す。
2. S3バックアップ用ポリシー
| バケット名 |
example-jp-s3-backup |
■S3BackupObjectAccessPolicy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListAndGetBucketInfo",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::example-jp-s3-backup"
},
{
"Sid": "AllowObjectOperationsInBucket",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:GetObjectTagging",
"s3:PutObjectTagging",
"s3:AbortMultipartUpload",
"s3:ListBucketMultipartUploads",
"s3:ListMultipartUploadParts"
],
"Resource": "arn:aws:s3:::example-jp-s3-backup/*"
}
]
}
■EC2-S3-Backup-Role
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
3. S3バックアップスクリプト
#!/usr/bin/env bash
set -euo pipefail
############################################
# Config
############################################
BUCKET_NAME="www-example-jp-backup"
ENDPOINT_URL="${ENDPOINT_URL:-}"
AWS_PROFILE="${AWS_PROFILE:-default}"
WEB_ROOTS=(
"/var/www/html"
"/var/www_vhosts/www.example.jp/html"
)
MARIADB_DEFAULTS_FILE="/root/.mariadb_config"
WORKDIR="/var/tmp/object_backup_work"
HTTPD_LOG_DIR="/var/log/httpd"
VAR_LOG_DIR="/var/log"
DAILY_BASE_PREFIX="daily"
DAILY_GEN_PREFIX="${DAILY_BASE_PREFIX}/backup"
DAILY_GEN_MAX=6
############################################
# Utils
############################################
log() { echo "[$(date '+%F %T')] $*"; }
aws_s3() {
if [[ -n "${ENDPOINT_URL}" ]]; then
aws --profile "${AWS_PROFILE}" --endpoint-url "${ENDPOINT_URL}" "$@"
else
aws --profile "${AWS_PROFILE}" "$@"
fi
}
############################################
# Rotation
############################################
rotate_daily_generations() {
log "Rotate daily generations"
aws_s3 s3 rm "s3://${BUCKET_NAME}/${DAILY_GEN_PREFIX}.${DAILY_GEN_MAX}/" --recursive || true
for ((i=DAILY_GEN_MAX-1; i>=0; i--)); do
aws_s3 s3 mv \
"s3://${BUCKET_NAME}/${DAILY_GEN_PREFIX}.${i}/" \
"s3://${BUCKET_NAME}/${DAILY_GEN_PREFIX}.$((i+1))/" \
--recursive || true
done
}
############################################
# DB dump command resolver
############################################
db_dump_cmd() {
command -v mariadb-dump >/dev/null 2>&1 && echo "mariadb-dump" && return
command -v mysqldump >/dev/null 2>&1 && echo "mysqldump" && return
echo "ERROR: dump command not found" >&2
exit 1
}
############################################
# Daily backup (web + db)
############################################
create_and_upload_daily_backup() {
local ymd
ymd=$(date '+%Y%m%d')
local tmpdir="${WORKDIR}/daily_${ymd}"
mkdir -p "${tmpdir}"
# validate web roots
for p in "${WEB_ROOTS[@]}"; do
if [[ ! -d "${p}" ]]; then
echo "ERROR: WEB_ROOT not found: ${p}" >&2
exit 1
fi
done
local dumpbin
dumpbin=$(db_dump_cmd)
##########################################
# 1) DB dump (gzip pipe)
##########################################
log "Create compressed MariaDB dump"
${dumpbin} \
--defaults-extra-file="${MARIADB_DEFAULTS_FILE}" \
--single-transaction --routines --events --triggers \
--all-databases \
| gzip > "${tmpdir}/db_${ymd}.sql.gz"
log "Upload DB dump"
aws_s3 s3 cp \
"${tmpdir}/db_${ymd}.sql.gz" \
"s3://${BUCKET_NAME}/${DAILY_GEN_PREFIX}.0/db_${ymd}.sql.gz"
##########################################
# 2) Each WEB_ROOT individually
##########################################
for webroot in "${WEB_ROOTS[@]}"; do
# /var/www/html → var_www_html
local safe_name
safe_name=$(echo "${webroot#/}" | tr '/' '_')
local archive="${tmpdir}/${safe_name}_${ymd}.tar.gz"
log "Create archive for ${webroot}"
tar -czf "${archive}" -C "/" "${webroot#/}"
log "Upload ${archive}"
aws_s3 s3 cp \
"${archive}" \
"s3://${BUCKET_NAME}/${DAILY_GEN_PREFIX}.0/$(basename "${archive}")"
done
rm -rf "${tmpdir}"
log "Daily backup done (path-based filenames)."
}
############################################
# Apache log backup (gzip)
############################################
upload_apache_logs_except_today() {
local today
today=$(date '+%Y%m%d')
log "Compress & upload Apache logs"
shopt -s nullglob
for f in ${HTTPD_LOG_DIR}/www.example.jp-access_log-*.log; do
base=$(basename "$f")
yyyymmdd=$(echo "$base" | sed -n 's/^www\.example\.jp-access_log-\([0-9]\{8\}\)\.log$/\1/p')
[[ -z "$yyyymmdd" ]] && continue
[[ "$yyyymmdd" == "$today" ]] && continue
yymm=$(echo "$yyyymmdd" | cut -c3-6)
dst_prefix="apache_log/${yymm}"
log "gzip & upload: $base"
gzip -c "$f" | \
aws_s3 s3 cp - \
"s3://${BUCKET_NAME}/${dst_prefix}/${base}.gz"
done
shopt -u nullglob
log "Apache logs done"
}
############################################
# Weekly /var/log backup
############################################
create_and_upload_weekly_logs() {
local yymm
yymm=$(date '+%y%m')
local ymd
ymd=$(date '+%Y%m%d')
log "Create compressed weekly /var/log archive"
tar -czf - -C "/" "${VAR_LOG_DIR#/}" \
| aws_s3 s3 cp - \
"s3://${BUCKET_NAME}/weekly/${yymm}/var_log_${ymd}.tar.gz"
log "Weekly backup done"
}
############################################
# Main
############################################
main() {
mkdir -p "${WORKDIR}"
mode="${1:-auto}"
case "$mode" in
daily)
rotate_daily_generations
create_and_upload_daily_backup
upload_apache_logs_except_today
;;
weekly)
create_and_upload_weekly_logs
;;
auto)
rotate_daily_generations
create_and_upload_daily_backup
upload_apache_logs_except_today
[[ "$(date '+%w')" == "0" ]] && create_and_upload_weekly_logs
;;
*)
echo "Usage: $0 {daily|weekly|auto}"
exit 1
;;
esac
}
main "$@"
最終更新:2026年04月07日 07:11