アットウィキロゴ

[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