話題の記事

【Amazon S3 Streaming】AWS CLIを使って標準入出力とS3を直接つなぐ【小ネタ】

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

よく訓練されたアップル信者、都元です。ひさびさのブログになってしまいました。リハビリも兼ねて、小ネタにて。

ローカルファイルシステムと標準入出力

まずは基礎的過ぎる話から。linuxシェル上で、ローカルファイルシステム上のファイルを標準出力に書き出したい時、例えばこんなコマンドを使いますね。

$ cat foo.txt

次に、シェルからちょっとしたテキストファイルを作成したいとき、下記のようにechoとリダイレクトを使って書き込みをすることがあると思います。

$ echo foobar >foo.txt

複数行に渡るファイルであれば、ヒアドキュメント *1を使ってこんな感じでしょうか。

$ cat << _EOF_ >bar.txt
aaa
bbb
_EOF_

ローカルファイルシステムとAmazon S3

さて一方で。AWS CLIでは、下記のようにs3 cpサブコマンドで、S3とローカルファイルシステム間でファイルのコピーが可能です。

$ aws s3 cp foo.txt s3://example-bucket/
upload: ./foo.txt to s3://example-bucket/foo.txt

$ aws s3 cp s3://example-bucket/foo.txt .
download: s3://example-bucket/foo.txt to ./foo.txt

Amazon S3と標準入出力

さて本日の主題はここ。標準入力から(ローカルファイルシステムを介さず)直接S3にファイルを置きたい、あるいは、S3上にあるファイル(ローカルファイルシステム介さずに)を直接標準出力に書き出したい、ということです。さて、あまりグダグダ説明するもんでもないので、コマンド例を下記に。

$ echo foobar | aws s3 cp - s3://example-bucket/foo.txt

$ cat << _EOF_ | aws s3 cp - s3://example-bucket/bar.txt
pipe heredoc> aaa
pipe heredoc> bbb
pipe heredoc> _EOF_

このように、パイプの先にAWS CLIを繋げ、コピー元の部分を-にすれば、パイプから流れてきた内容をそのままS3にアップロードしてくれます。ちなみに上記のpipe heredoc> の部分はシェルが自動的に出してくるものです。

逆に、S3上のオブジェクトをcatのように表示したい場合は、こう。

$ aws s3 cp s3://example-bucket/bar.txt -
aaa
bbb

同じく、コピー先を-にすれば、それをそのまま標準出力に流してくれます。

パイプに流せるなら圧縮展開もできるはずだ

というわけで、入力したテキストをgzipで圧縮してからS3に上げてみます。

cat << _EOF_ | gzip | aws s3 cp - s3://example-bucket/baz.txt.gz
pipe pipe heredoc> miyamoto
pipe pipe heredoc> daisuke
pipe pipe heredoc> _EOF_

そして、ダウンロードした圧縮ファイルをそのままgunzipに流して展開してから表示してみます。

$ aws s3 cp s3://example-bucket/baz.txt.gz - | gunzip
miyamoto
daisuke

そのままaws s3 cp s3://example-bucket/baz.txt.gz -を実行すると、文字化けというか、まぁバイナリをそのまま出力した感じになってしまいます。そりゃそうですね。

ならば、例えば16進ダンプしてみたり。

$ aws s3 cp s3://example-bucket/baz.txt.gz - | hexdump
0000000 1f 8b 08 00 73 e0 35 55 00 03 cb cd ac 4c cc cd
0000010 2f c9 e7 4a 49 cc 2c 2e cd 4e e5 02 00 21 b7 87
0000020 cd 11 00 00 00
0000025

要するに自由自在です。

まとめ

シェルスクリプト上で、ちょっとしたステートを複数の場所から見える場所に保存しておきたい時、このような仕組みを知っておくと便利かもしれません。

脚注

  1. ここでは<<の直後に記述した_EOF_が現れるまで標準入力から入力する。