【Powershell】ローカルフォルダをAWS CLIを使用してAmazon S3へアップロードするps1スクリプトを作成！！

# 1 はじめに
AWS CLIを使用するとローカル ⇔ Amazon S3間でリソースのやり取りが簡単にできるようになります。
主にファイルのやり取りをよく行いますが、一気にリソースのやり取りを行いたい場合、フォルダ（ディレクトリ）単位でリソースのやり取りを行うことが可能です。
今回はその処理をスクリプトに落とし込んだものをご紹介致します。

# 2 概要
<b><目標></b>
スクリプトを実行することにより、指定のAmazon S3パケットへローカルフォルダ（ディレクトリ）をアップロードする。

<b><機能要件></b>
・ローカル ⇒ S3へディレクトリ単位でリソースのアップロードを行う
・アップロード元ディレクトリは複数選択できるようにする
・アップロード元ディレクトリの選択は別途設定ファイルに記載する形で行う
・処理をPowershellスクリプト（ps1）を使用して行う

<b><実現方法></b>
Windows10
WindowsServer 2012/2016/2019

# 3 アップロードスクリプト
本スクリプトは以下GitHubにも上げておりますのでよろしければそちらでもご確認ください。
https://github.com/chibiharu/PowerShell-Tools/tree/master/Local_Directory_Upload_to_AWS_S3
## 3.1 使用手順
<b>① アップロード対象リストの作成</b>
S3へアップロードするディレクトリを登録するアップロード対象リストを作成します。
Windows左下の『スタート画面』-『Windowsアクセサリ』-『メモ帳』を開きます。
メモ帳にアップロード対象ディレクトリのフルパスを記載します。
※ パス末尾に「\」は付けません

```:アップロード対象リスト(Upload_Target.conf）
C:\Program Files
C:\Program Files (x86)
C:\ProgramData
```

リストを作成したら、『ctrl』+『s』でファイル名を以下にリネームし、文字コードを『SJIS』に変更をし、任意のパスに保存してください。
<b><ファイル名></b>
'===========================
・変更前 ⇒ 新しいドキュメント.txt
・変更後 ⇒ Upload_Target.conf
'===========================
<b><文字コード></b>
'===========================
・変更後 ⇒ SJIS（ANSI）
'===========================

<b>② スクリプトの作成</b>
Windows左下の『スタート画面』-『Windowsアクセサリ』-『メモ帳』を開きます。
メモ帳に以下コードを貼り付けます。

``` powershell:S3自動アップロードスクリプト
#######################################################################################
# <説明>
# ローカルディレクトリをAmazon S3へAWS CLIコマンドを使用し、再帰的アップロードを行う
# 
# <更新日>
# 作成日：20210710
# 最終更新日：20211016
#
# <使用時における注意事項>
# ・アップロード対象リスト、及び本スクリプトの文字コードは「ANSI(SJIS)」を指定すること
# ・-
#
# <コメント>
# ・-
# ・-
#
#######################################################################################

#######################################################################################
# 事前設定
#######################################################################################

# 今月の月（yyyyM）を取得
$str_month = Get-Date -Format "yyyyM"

# 今日の日付（yyyyMMdd）を取得
$str_data = Get-Date -Format "yyyyMMdd"

# 現在の時刻（yyyyMMddhhmmss）を取得
$str_time = Get-Date -Format "yyyyMMddhhmmss"

# スクリプトの設置ディレクトリを取得
$CurrentDir = Split-Path $MyInvocation.MyCommand.Path


#######################################################################################
# パラメータ設定
#######################################################################################

##### >>>>> [設定開始]

# アップロード対象リスト(デフォルトではカレントディレクトリを指定)
$upload_list = "${CurrentDir}/Upload_Target.conf"

# 実行ログの出力先フォルダ(デフォルトではカレントディレクトリを指定)
# ※ 末尾に「\」は付けない
$logdir = "${CurrentDir}"

# アップロード先S3バケットのURI
$s3uri = "<S3バケットのURIを指定>"

# AWS CLI プロファイル生成
$Env:AWS_ACCESS_KEY_ID="<アクセスキーID>"
$Env:AWS_SECRET_ACCESS_KEY="<シークレットアクセスキーID>"
$Env:AWS_DEFAULT_REGION="<リージョン名>"

##### <<<<< [設定終了]

# ログファイル名
$logname = "\$str_data.log"

# ログファイルフルパス
$output_log = "$logdir$logname"

# アップロード先S3バケットのURI
$s3bucket = "${s3uri}${str_time}/"


#######################################################################################
## 実行前処理
#######################################################################################

# スクリプトの開始時刻（yyyyMMdd - hhmmss）を取得
$start_time = Get-Date -Format "yyyy-MM-dd hh:mm:ss"

# ログ見出し出力（Start）
Write-Output "************** Local_Directory_Backup_to_Amazon_S3 $start_time Start **************" | Out-File -Append -Encoding default $output_log


#######################################################################################
# S3へのアップロード処理
#######################################################################################

# バックアップ対象リストの読み込み
$line = get-content $upload_list
  foreach($param in $line){
  Write-Output $param
    # アップロード元ディレクトリが存在するか確認
    if (Test-Path $param) {
      # 処理を続ける
    }else{
      Write-Host "[Error] [messages] --> <<<指定したアップロード元ディレクトリのパスが存在しません>>>"
      Write-Host "[Error] [messages] --> <<<指定したアップロード元ディレクトリのパスが存在しません>>>" | Out-File -Append -Encoding default $output_log
      Exit
    }
    # ファイル/フォルダ名を取得する
    $pathname = Split-Path $param -Leaf
    # ローカルディレクトリをAmazon S3へコピーする。>> 今日の日付のログファイルを作成し、実行ログをログファイルに出力する。
    aws s3 cp $param ${s3bucket}${pathname}/ --recursive | Out-File -Append -Encoding default $output_log
  }


#######################################################################################
# 実行後処理
#######################################################################################

# スクリプトの終了時刻（yyyyMMdd - hhmmss）を取得
$end_time = Get-Date -Format "yyyy-MM-dd hh:mm:ss"

# ログ見出し出力（End）
Write-Output "**************  Local_Directory_Backup_to_Amazon_S3 $end_time End  **************" | Out-File -Append -Encoding default $output_log
```
スクリプトを貼り付けたら、『ctrl』+『s』でファイルを以下拡張子にリネームし、文字コードを『SJIS』に変更をし、任意のパスに保存してください。
※スクリプト名は任意の名前を指定して下さい

<b><拡張子></b>
'===========================
・変更前 ⇒ **.txt
・変更後 ⇒ **.ps1
'===========================
<b><文字コード></b>
'===========================
・変更後 ⇒ SJIS（ANSI）
'===========================

<b>③ スクリプトの実行</b>
スクリプトを右クリック ⇒「Powershellを実行」をクリックし、処理を開始します。

## 3.2 進行状況の確認
ログファイルを参照することで現在の進行状況を確認することができます。

```:進行状況(例)
************** Local_Directory_Backup_to_Amazon_S3 2021-10-17 09:34:58 Start **************
Completed 47 Bytes/133 Bytes (123 Bytes/s) with 2 file(s) remaining
upload: <アップロード中のリソースのフルパス>
Completed 47 Bytes/133 Bytes (123 Bytes/s) with 1 file(s) remaining
Completed 133 Bytes/133 Bytes (342 Bytes/s) with 1 file(s) remaining
upload: <アップロード中のリソースのフルパス>
Completed 776 Bytes/~35.7 GiB (1.1 KiB/s) with ~28 file(s) remaining (calculating...)
upload: <アップロード中のリソースのフルパス>
Completed 776 Bytes/~35.7 GiB (1.1 KiB/s) with ~27 file(s) remaining (calculating...)
Completed 13.5 KiB/~35.7 GiB (18.5 KiB/s) with ~27 file(s) remaining (calculating...)
```
## 3.3 動作確認
S3バケット、及びログファイルを参照しアップロード処理が無事完了しているか確認します。

<b>● S3バケットの確認</b>
S3バケットにて、アップロード対象ディレクトリがアップロードされているか確認します。

<b>● 実行ログの確認</b>
ログファイルを参照し、以下点を確認します。
・エラーが出力されていないこと
・最下行に処理の終了ログが出力されていること

# 4 まとめ
後はこちらのスクリプトをタスクスケジューラ等で定期実行するよう設定すれば、特定のフォルダ（ディレクトリ）を定期的にS3へバックアップしてくれるようになります。

この作業はもちろんGUIでも行えますが、基本CLIで出来ることはCLI化してしまうことをおすすめします。
GUIはコンソールのUIがすぐ変わってしまったりしますからね。

では本記事は以上になります。ありがとうございました。