(この記事は Elixir (その2)とPhoenix Advent Calendar 2016 22日目の記事です)
今回は、Timexを使うコードを、escriptでコマンド化した際、実行時エラーが出るのを回避する方法を解説
escriptでのコマンド化についても、軽く解説します
【2021/7/30追記】
この方法、下記最新ElixirおよびOTPバージョンでは使えないことを確認しました
escriptで日時周りを使いたい場合は、Timexの代わりにElixir標準モジュールのDateTimeやCalendar等をご利用ください
Erlang/OTP 24 [erts-12.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit]
Elixir 1.12.0 (compiled with Erlang/OTP 24)
escriptでElixirコードをコマンド化
まず、メインモジュールにmain()関数を追加します
コンソールから呼び出したときは、この関数が呼ばれます
defmodule Sample do
def main( args \\ [] ) do
…
mix.exsの「def project」配下にescript利用を追記し、「def script」にメインモジュールのモジュール名を追加します(ここではElixirプロジェクト名を「sample」としています)
defmodule Sample.MixProject do
use Mix.Project
def project do
[
…
escript: escript(),
deps: deps()
]
end
def escript() do
[ main_module: Sample ]
end
…
escriptでコマンド化します
> mix escript.build
コンソールでの実行は、以下の通りです
> escript sample
Windows以外だと、以下でも実行できます
# chmod 755 ./sample
# ./sample
Timex利用コードのコマンド化で実行時エラーが出る
Timexmモジュールを導入します
defmodule Sample.Mixfile do
…
defp deps do
…
{ :timex, "~> 3.0" },
…
# mix deps.get
コマンド化して実行すると、以下エラーが出ます
# mix escript.build
# escript sample
Could not start application tzdata: exited in: Tzdata.App.start(:normal, [])
** (EXIT) an exception was raised:
** (MatchError) no match of right hand side value: {:error, {:shutdown, {:failed_to_start_child, Tzdata.EtsHolder, {%ArgumentError{message: "unknown application: :tzdata"}, [{Application, :app_dir, 1, [file: 'lib/application.ex', line: 428]},
{Application, :app_dir, 2, [file: 'lib/application.ex', line: 437]}, {Tzdata.EtsHolder, :release_dir, 0, [file: 'lib/tzdata/ets_holder.ex', line: 86]}, {Tzdata.EtsHolder, :make_sure_a_release_dir_exists, 0, [file: 'lib/tzdata/ets_holder.ex', line: 70]},
{Tzdata.EtsHolder, :make_sure_a_release_is_on_file, 0, [file: 'lib/tzdata/ets_holder.ex', line: 64]}, {Tzdata.EtsHolder, :init, 1, [file: 'lib/tzdata/ets_holder.ex', line: 10]}, {:gen_server, :init_it, 6, [file: 'gen_server.erl', line: 328]},
{:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 247]}]}}}}
(tzdata) lib/tzdata/tzdata_app.ex:15: Tzdata.App.start/2
(kernel) application_master.erl:273: :application_master.start_it_old/4
これを回避するには、tzdataモジュールのバージョンを固定で指定します(元ネタはこちら)
defmodule Sample.Mixfile do
…
defp deps do
…
{ :tzdata, "== 0.1.8", override: true },
…
ビルドし直して、実行すると、エラーが出なくなります
# mix deps.get
# mix escript.build
# escript sample
p.s.OptionParseやコマンド終了ステータス等については、「Elixirでいい感じのCLIをパッと作ってサッと共有(できるようになる。そう、Elixir 1.3ならね)」が参考になります
p.s.
6/17(土)の「第3回 ☆ データサイエンスLT&勉強会 ☆ in LINE福岡!」、60名を超える規模で盛り上がりました
7/28(金)、「Fukuoka CTO meetup」という福岡のCTOが集まってディスカッションするイベントで講演することになりました
技術チームのマネジメントや、技術選定の基準となる考え方、地方でCTOとして働く理由、どのようにCTOになったのか等について、アレコレお話すると思います