今日もプログラミング

IT技術とかプログラミングのこととか特にJavaを中心に書いていきます

Embulkの環境を丸ごとコピーする

Embulkでプラグインをインストールすると、実行ユーザのホームディレクトリの下に.embulkディレクトリができて、gemがインストールされる。

 

別の環境でも同じようにEmbulkを動かすには、Javaをインストールして、Embulkの実行ファイルをコピーして、ホームディレクトリもコピーするだけ。

なんだけど、アプリケーションはホームディレクトリではなくてアプリケーション用のディレクトリにまとめたい、ということもある。

そこで、その方法について調べてみた。

 

Embulkのホームディレクトリ

".embulk"でgrepしてみると、embulk_bundle.rbに以下のコードがあった。

  user_home = java.lang.System.properties["user.home"] || ENV['HOME']
  unless user_home
    raise "HOME environment variable is not set."
  end
  ENV['GEM_HOME'] = File.expand_path File.join(user_home, '.embulk', Gem.ruby_engine, RbConfig::CONFIG['ruby_version'])

ということは、Javaのシステム変数user.homeを設定してやれば、そこがEmbulkのホームになりそうだ。

 

embulk "-J-Duser.home=/embulk" gem install embulk-input-mysql

と実行したら、/embulkディレクトリにプラグインがインストールされた!

なお、Linuxの場合はオプション指定を""で囲まなくてもいいはず。

 

環境を丸ごとコピーしてみる

/embulkディレクトリに、Embulkの実行ファイルを置く。

そして、上で試した通り、そのディレクトリにプラグインをインストールする。

 

次に、別のマシンにJavaをインストール後、/embulkディレクトリを丸ごとコピーする。

そして、

embulk "-J-Duser.home=/embulk" run test.yml

を実行すると…、

無事実行できた!

 

Bundlerを使う方法

Embulkでは、Bundlerというものを使って、プラグインを含むEmbulkの実行環境をまとめることができる。

これも試してみた。

 

まず、

embulk mkbundle embulk1

のように実行する。すると、embulk1ディレクトリにいろいろファイルが作成される。

次に、embulk1/Gemfileを開いて、インストールしたいプラグインを書く。

gem 'embulk-input-mysql'

特定のバージョンを指定することもできるようだ(詳しくはGemfileにコメントが書いてある)。

そして、

cd embulk1
embulk bundle
cd ..

を実行すると、embulk-input-mysqlがインストールされた。

実行時は、

embulk run -b embulk1 test.yml

のようにすればOK。

 

こちらについても、Embulkの実行ファイルとembulk1フォルダを丸ごとコピーして、動くのが確認できた!

 

EmbulkEmbedを使う場合

EmbulkEmbedを使うと、EmbulkをJavaライブラリ的に使うことができる。

この場合、プラグインはどうなるんだろうか?

 

import java.io.File;
import org.embulk.EmbulkEmbed;
import org.embulk.EmbulkEmbed.Bootstrap;
import org.embulk.config.ConfigLoader;
import org.embulk.config.ConfigSource;

public class EmbulkEmbedTest {
    public static void main(String[] args) throws Exception {
        Bootstrap bootstrap = new EmbulkEmbed.Bootstrap();
        EmbulkEmbed embulk = bootstrap.initializeCloseable();
        try {
            ConfigLoader loader = embulk.newConfigLoader();
            ConfigSource source = loader.fromYamlFile(new File(args[0]));
            embulk.run(source);
        } finally {
            embulk.destroy();
        }
    }
}

のようなクラスを作って、

java -classpath .;embulk.bat EmbulkEmbedTest test.yml

を実行すると、Embulkを実行することはできる。

しかし、プラグインは読み込まれていないようだ…。

 

Embulkのソースを追ってみると、通常はまずorg.embulk.cli.Mainが起動され、そこからembulk_bundle.rbが実行される。

そこで環境変数GEM_HOMEが設定され、プラグインのgemが読み込まれ、そこから更にいろいろ経由してEmbulkEmbedが呼ばれる。

EmbulkEmbedを直接呼ぶと、embulk_bundle.rbが実行されないため、プラグインが読み込まれないようだ。

ひょっとして、環境変数GEM_HOMEを手動で設定すればうまくいくかな?と思って、

set GEM_HOME=/embulk/.embulk/jruby/2.2.0
java -classpath .;embulk.bat EmbulkEmbedTest test.yml

と実行したら、うまくいった!

 

Embulk 0.7.10
OS Windows

 

2015/12/25 Bundlerを使うパターンについて追記しました(hiroysatoさんの記事を参考にしました)。

2015/12/25 EmbulkEmbedを使うケースについて追記しました(ひしだまさんの記事を参考にしました)。