lsyncdで更新ファイルを検知してaws s3へファイルアップロード

皆さま, こんにちわ

10月になってしまって涼しくなって来たと思ったら三連休は暑いですね〜

今日は, aws s3ネタです.

やりたいこと

対象ディレクトリ配下でファイル更新があったもののみs3にアップロードしたい, という場合には aws s3 cp を使えば良いという話. 毎回対象ディレクトリを aws s3 sync してもよいのですが, それだとファイル数が多いと検索に時間がかかってしまい, 1ファイルをアップロードするのにも十数分とか掛かってしまうことがある. (時間はファイル数によって上下します) そのため, 更新したファイルだけを検知して aws s3 cp をその都度実行した方が効率が良いだろうということで採用した.

仕組み

更新(タイムスタンプが変更), もしくは新規作成されたファイルがあった場合に, lsyncdで検知させ, スクリプト(aws s3 cp)を実行させる.

f:id:namio6243:20181007123429p:plain

検証環境

前提

  • 検証環境に記載されているソフトウェアがインストールされていること.
  • 使用するIAMユーザーのアクセスキーID, シークレットアクセスキーを取得済み

構築

公式サイトの手順通りに credintialをdatacenter側のサーバに登録

下記の通りに設定したら aws s3 ls コマンドでバケット情報が取得できることを確認する. docs.aws.amazon.com

ファイル更新検知時に実行させるスクリプトを作成

私はshellで書くのが楽だったのでshellにしちゃいましたが, 他のスクリプトでも良いと思います.

s3-upload.sh

#!/bin/bash
# aws s3バケット名
S3_BUCKET_NAME='************'
# 送信元のファイルパスを設定
SRC_PATH="${1}"

  # 送信元ファイルパスから不要な部分をカットして送信先用に使う. 例として17に設定してますが, 文字数それぞれで合わせてください.
  DST_PATH=`echo ${SRC_PATH} | cut -c 17-`
  if [ -f ${SRC_PATH} ]; then
    # excludeオプションを使って, 更新検知から除外したいファイルを指定する. includeオプションも一緒に設定しないとexcludeが効かないので要注意.
    aws s3 cp ${SRC_PATH} s3://${S3_BUCKET_NAME}${DST_PATH} --include "*" --exclude "*.log"
  else
    # ファイルが削除されたら, s3側も同じように削除されるように設定する.
    aws s3 rm s3://${S3_BUCKET_NAME}${DST_PATH}
  fi
lsyncdにスクリプトを登録

lsyncdのconfigに作成したスクリプトを登録します. ファイルパスなどは各自読み換えて設定して下さい.

lsyncd_to_s3.conf

settings{
        logfile = "/var/log/lsyncd/s3-upload.log",
        statusFile = "/var/log/lsyncd/s3-upload.stat",
        statusInterval = 5,
        nodeaemon = false,
}

exec = function(event)
    local src_path = event.sourcePathname
    spawnShell(event, "/bin/bash /opt/lsyncd/s3-upload.sh " .. src_path .. " || :" );
end

s3_upload = {
    maxProcesses = 2,
    delay = 0,
    onCreate = exec,
    onDelete = exec,
    onMove = exec,
}

sync {
    s3_upload,
    source = "/opt/s3_src_dir",
}
lsyncdを起動

上記で作成したconfigのパスを引数に指定して実行.

$ lsyncd -pidfile /var/run/lsyncd.pid /etc/lsyncd_to_s3.conf

起動してれば, こんな感じです.

$ ps -ef | grep lsyncd
test      3295     1  0 13:18 ?        00:26:48 lsyncd -pidfile /var/run/lsyncd.pid /etc/lsyncd_to_s3.conf
該当ディレクトリ配下にファイルを配置してみる

適当にファイルをtouchで作成.

$ touch /opt/s3_src_dir/test.txt

あとは, s3にファイルがアップロードされていることを確認して, アップされてればOK.

総括

  • 構築してみて思ったのは, やはり送信元のファイル更新からs3への同期は, 体感的にはほぼ即時反映になった. (速い!)
  • 1日とか1時間に1回の頻度で同期する, みたいな使い方しかしない場合はここまでやらないでOKだなーと思った. (定期的に s3 sync 叩けば良し)
  • 枯れた技術ではあるが, 他に代替えも見当たらないのでlsyncdは便利.