【Amazon S3 Streaming】AWS CLIを使って標準入出力とS3を直接つなぐ【小ネタ】
よく訓練されたアップル信者、都元です。ひさびさのブログになってしまいました。リハビリも兼ねて、小ネタにて。
ローカルファイルシステムと標準入出力
まずは基礎的過ぎる話から。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
要するに自由自在です。
まとめ
シェルスクリプト上で、ちょっとしたステートを複数の場所から見える場所に保存しておきたい時、このような仕組みを知っておくと便利かもしれません。
脚注
- ここでは<<の直後に記述した_EOF_が現れるまで標準入力から入力する。 ↩