AWS S3上に保存されているファイルの更新タイムスタンプチェック

■はじめに
===

AWSのS3上に保存されている特定のファイルが更新されたら、EC2インスタンス内にファイルをダウンロードしたいといったような事があるかと思います。

awscliのaws s3 syncコマンドを実行する事で、rsyncのように、S3バケット内の更新ファイルをEC2インスタンス内にダウンロードする事が可能ですので、aws s3 syncコマンドをcrontabで定期的に実行するという方法があるかと思います。


```
$ aws s3 sync s3://test-web-data-store/test/ /home/ec2-user/
download: s3://test-web-data-store/test/test2.txt to ./test2.txt
download: s3://test-web-data-store/test/test.txt to ./test.txt
$
```


個人的な興味で、S3上のファイルのタイムスタンプをチェックして、ファイルが更新されている場合のみダウンロードするみたいな事が出来ないかなと思い、試してみました。

以下のように、S3上に保存されているファイルのタイムスタンプをチェックし、ファイルが更新されている場合にダウンロードするのは可能でした。

■前提
===

以下のようなS3バケットを作成します。
s3://test-web-data-store/

例として、S3バケット内に以下のようなテストファイルを作成し、ファイルのタイムスタンプをチェックするようにします。
s3://test-web-data-store/test/test.txt

S3のファイルをダウンロードしたいEC2インスタンスには、以下のようなIAMロールを割り当てて、S3へアクセスできるようにしておきます。

Policy Name: AmazonS3FullAccess-test-web-data-store-201408310305

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:ListAllMyBuckets"],
      "Resource": "arn:aws:s3:::*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:GetBucketLocation"
      ],
      "Resource": "arn:aws:s3:::test-web-data-store"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject"
      ],
      "Resource": "arn:aws:s3:::test-web-data-store/*"
    }
  ]
}
```


■S3上にテスト用ファイル作成
===

S3バケット内に以下のようなテスト用ファイルを作成します。
s3://test-web-data-store/test/test.txt

```
$ date
Sun Dec 21 17:13:13 UTC 2014
$ aws s3 ls s3://test-web-data-store/test/
2014-12-21 16:53:39          0
$

$ date > /tmp/test.txt
$

$ aws s3 cp /tmp/test.txt s3://test-web-data-store/test/
upload: ../../tmp/test.txt to s3://test-web-data-store/test/test.txt
$

$ aws s3 ls s3://test-web-data-store/test/
2014-12-21 16:53:39          0
2014-12-21 17:14:05         29 test.txt
$
```

```
$ rm -f /tmp/test.txt
$ ll /tmp/test.txt
ls: cannot access /tmp/test.txt: No such file or directory
$
```

■S3上に保存されているファイルのタイムスタンプ確認例
===

簡素ではありますが、以下のようなコマンドで、S3上のファイルのタイムスタンプを取得できます。

```
$ aws s3 ls s3://test-web-data-store/test/ | grep 'test.txt' | awk '{print $1,$2}'
2014-12-21 17:14:05
$
```

例えば、以下のようなシェルを作成し、crontabで10分おきに定期実行するようにすれば、s3://test-web-data-store/test/test.txtのタイムスタンプが更新されたら、EC2インスタンス内に/tmp/test.txtとしてダウンロードしてくるといった事が可能です。

s3://test-web-data-store/test/test.txtのタイムスタンプが更新されていたら、/tmp/test.txtとしてダウンロードするテストシェルです。

```
$ vi s3_download_test.sh
```

```shell-session:s3_download_test.sh
#!/bin/sh

S3_BUCKET="s3://test-web-data-store/test"
S3_CHECK_FILE="test.txt"

OLD_TIMESTAMP_FILE="/tmp/old_file_timestamp.txt"
NEW_TIMESTAMP_FILE="/tmp/new_file_timestamp.txt"

DOWNLOAD_DIR="/tmp"

if [ -f ${NEW_TIMESTAMP_FILE} ] ; then
        mv ${NEW_TIMESTAMP_FILE} ${OLD_TIMESTAMP_FILE}
fi

# S3バケット上のファイルのタイムスタンプを取得
aws s3 ls ${S3_BUCKET}/ | grep "${S3_CHECK_FILE}" | awk '{print $1,$2}' > ${NEW_TIMESTAMP_FILE}

if [ -f ${OLD_TIMESTAMP_FILE} ] ; then

        DIFF_COUNT=`diff ${NEW_TIMESTAMP_FILE} ${OLD_TIMESTAMP_FILE} | wc -l`

        if [ ${DIFF_COUNT} -ge 1 ] ; then

                echo "diff [${S3_BUCKET}/${S3_CHECK_FILE}]"
                echo "aws s3 cp ${S3_BUCKET}/${S3_CHECK_FILE} ${DOWNLOAD_DIR}/"
                aws s3 cp ${S3_BUCKET}/${S3_CHECK_FILE} ${DOWNLOAD_DIR}/

        else

                echo "not diff [${S3_BUCKET}/${S3_CHECK_FILE}]"

        fi
fi
```

```
$ chmod 754 s3_download_test.sh
```

s3://test-web-data-store/test/test.txtのタイムスタンプが更新されていない状態で、s3_download_test.shを実行しても、/tmp/test.txtはダウンロードされません。


```
$ aws s3 ls s3://test-web-data-store/test/test.txt
2014-12-21 17:14:05         29 test.txt
$

$ ./s3_download_test.sh
not diff [s3://test-web-data-store/test//test.txt]
$

$ aws s3 ls s3://test-web-data-store/test/test.txt
2014-12-21 17:14:05         29 test.txt
$
$ ll /tmp/test.txt
ls: cannot access /tmp/test.txt: No such file or directory
$
```


s3://test-web-data-store/test/test.txtのタイムスタンプが更新された状態で、s3_download_test.shを実行すると、/tmp/test.txtをダウンロード出来ます。

```
$ date >> test.txt
$ date >> test.txt
$

$ aws s3 cp test.txt s3://test-web-data-store/test/
upload: ./test.txt to s3://test-web-data-store/test/test.txt
$
$ rm test.txt
$ ll test.txt
ls: cannot access test.txt: No such file or directory
$ ll /tmp/test.txt
ls: cannot access /tmp/test.txt: No such file or directory
$

$ aws s3 ls s3://test-web-data-store/test/test.txt
2014-12-21 17:37:49         58 test.txt
$

$ ./s3_download_test.sh
diff [s3://test-web-data-store/test/test.txt]
aws s3 cp s3://test-web-data-store/test/test.txt /tmp/
download: s3://test-web-data-store/test/test.txt to ../../tmp/test.txt
$

$ ll /tmp/test.txt
-rw-rw-r-- 1 ec2-user ec2-user 58 Dec 21 17:45 /tmp/test.txt
$
```

一応、S3バケットに保存されたファイルのタイムスタンプをチェックすることでも、ファイルが更新されたか否かを判定してダウンロードする事は可能なようですね。