MD5でファイルが同じかどうかを判定することがあります。
S3ではETAGにMD5値が格納されているという事になっていますが、
結論から言うと、Multipart Updateされた場合と、そうでない場合で異なります。
s3 cpコマンドで試してみる(9M)
9Mのテストファイルを作ります。
1
2
3
4
| $ dd if=/dev/zero of=~/test9M bs=1M count=9
9+0 レコード入力
9+0 レコード出力
9437184 バイト (9.4 MB) コピーされました、 0.0269213 秒、 351 MB/秒
|
Bucketにコピーします。
1
2
| $ aws s3 cp ~/test9M s3://gside-test/test9M
upload: ../test9M to s3://gside-test/test9M
|
このコマンドでアップロードされた9Mのファイルは、ETAGがこんな感じ
1
2
3
4
5
6
7
8
9
| $ aws s3api head-object --bucket gside-test --key test9M
{
"Metadata": {},
"ETag": "\"d126ef08817d0490e207e456cb0ae080-2\"",
"ContentLength": 9437184,
"LastModified": "Sat, 22 Oct 2016 14:20:04 GMT",
"ContentType": "binary/octet-stream",
"AcceptRanges": "bytes"
}
|
ETagの値は “d126ef08817d0490e207e456cb0ae080-2” とハイフン付きの値です。
一方MD5はというと
1
2
| $ md5sum ~/test9M
b82b4ab87e44976024abc14a1670dac
|
ETAGの値とは違ってますね。Multipartアップロードされたのが原因です。
s3 cpコマンドで試してみる(8M)
8Mのテストファイルで同様のことをやってみます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| $ dd if=/dev/zero of=~/test8M bs=1M count=8
8+0 レコード入力
8+0 レコード出力
8388608 バイト (8.4 MB) コピーされました、 0.0204059 秒、 411 MB/秒
$ aws s3 cp ~/test8M s3://gside-test/test8M
upload: ../test8M to s3://gside-test/test8M
$ aws s3api head-object --bucket gside-test --key test8M
{
"LastModified": "Sat, 22 Oct 2016 14:19:07 GMT",
"AcceptRanges": "bytes",
"Metadata": {},
"ContentType": "binary/octet-stream",
"ETag": "\"96995b58d4cbf6aaa9041b4f00c7f6ae\"",
"ContentLength": 8388608
}
$ md5sum ~/test8M
96995b58d4cbf6aaa9041b4f00c7f6ae
|
今度はEtagとMD5が一致しています。Multipartでアップロードされなかったからですね。
解決策
s3api put-objectコマンドを使います。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| $ aws s3api put-object --bucket gside-test --key test9M --body ~/test9M
{
"ETag": "\"b82b4ab87e44976024abc14a1670dac0\""
}
$ aws s3api head-object --bucket gside-test --key test9M
{
"AcceptRanges": "bytes",
"ContentLength": 9437184,
"Metadata": {},
"ContentType": "binary/octet-stream",
"ETag": "\"b82b4ab87e44976024abc14a1670dac0\"",
"LastModified": "Sat, 22 Oct 2016 14:36:02 GMT"
}
|
今度はEtagとMD5が一致しています。
最後に
MD5とETAGを比較して、同一性を検証しているようなスクリプトを書いててハマりました。
AWSコンソールからアップロードした場合は64Mを超える辺りから、Multipart Uploadになるようです。
気をつけましょう。