このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

Erlang実験室:コマンドラインから使うerl

通常、erl(またはwerl)コマンドは対話的なシェル(EShell)を起動するために使いますが、非対話的に何らかの作業をさせるために使うこともできます。HelloWorldプログラムをコマンドラインから実行するには次のようにします。


$ erl -boot start_clean -noshell \
> -eval 'io:fwrite("Hello, world.~n")' -s init stop
Hello, world.
$

この程度だと、OSシェルのechoコマンドでもできるので、Erlangの得意な整数計算をさせてみれば:


$ erl -boot start_clean -noshell \
> -eval 'io:fwrite("~p~n",[12345*12345*12345])' -s init stop
1881365963625
$

巨大な整数計算に使えますよ。

以下に、便利そうなオプションとコマンドラインの例を注釈付きで並べます。OSシェルはMSYSbashです。横に長い出力行は編集してあります。

バージョンの確認

  • -version または +V -- 標準エラー出力にバージョンを書き出してすぐに終了します。


$ erl -version
Erlang (ASYNC_THREADS) (BEAM) emulator version 5.6.3
$
デバッグ情報を表示する

  • -emu_args -- BEAMエミュレータ(仮想機械)に渡される引数を表示します。
  • -init_debug -- initプロセスのデバッグ出力を有効にします。


$ erl -emu_args -init_debug -s init stop
Executing: C:\INSTAL~1\ERL56~1.3\ERTS-5~1.3\bin\beam.dll
C:\INSTAL~1\ERL56~1.3\ERTS-5~1.3\bin\beam.dll --
-root C:\INSTAL~1\ERL56~1.3
-progname erl -- -home C:\ -init_debug -s init stop

{progress,preloaded}
{progress,kernel_load_completed}
{progress,modules_loaded}
{start,heart}
{start,error_logger}
{start,application_controller}
{progress,init_kernel_started}
{apply,{application,load,[ ...(省略) ...]}}
{progress,applications_loaded}
{apply,{application,start_boot,[kernel,permanent]}}
{apply,{application,start_boot,[stdlib,permanent]}}
{apply,{c,erlangrc,[]}}
Hiyama's customized HOME

{progress,started}
Eshell V5.6.3 (abort with ^G)
1> $


上の例で、-home C:\ となっていますが、bashがなぜか環境変数HOMEPATHを書き換えてしまうので、ユーザーホームの設定に失敗しています。CMD.exeをシェルに使えば、%HOMEDRIVE%%HOMEPATH% がホームに設定されます。

Hiyama's customized HOMEって変なメッセージは、テスト用に作った .erlang の影響です。

-s init stop は後で説明しますが、効果としては、EShellに対して init:stop(). と手入力したのと同じです。

非対話的に使う

  • -noshell -- Erlangシェルを起動しません。ただし、標準入力を閉じてはいません。シェル以外のプログラムが動けば標準入力を読めます。
  • -noinput -- 標準入力(通常はキーボード)をまったく読みません。もちろん、シェルも起動しません。主にバックグラウンド実行のときに使います。


$ erl -noshell -eval 'io:fwrite("~s~n", [io:get_line("erl>")])' \
> -s init stop
erl>hello
hello
$

上の例では、io:get_lineが入力を実行してます。一方、次のようにすると、キーボード入力がERTSにまったく届きません(強制終了するしかない)。


$ erl -noinput -eval 'io:fwrite("~s~n", [io:get_line("erl>")])' \
> -s init stop
erl>

これらのオプションを指定しても自動的にERTSが終了するわけではないので、-s init stop を付けておくか、シグナルにより終了します。

式や関数を実行する

ERTSが起動した直後に、指定された式や関数を実行します。実行はEShellではなくてinitが行うので、-noshell や -noinput と同時に指定しても問題ありません。

  • -eval Expr -- 式(Expr)を評価します。
  • -run Mod [Func [Arg1, Arg2, ...]] -- モジュールModのFuncを、Arg1, Arg2, ... をリストにまとめた1引数を渡して実行します。ただし、Argがないときは引数なしで実行します。Arg1, Arg2, ... はどれも文字列データになります。
  • -s Mod [Func [Arg1, Arg2, ...]] -- -run と同じですが、Arg1, Arg2, ... はどれもアトムデータになります。

-run と -s は使い勝手がよくない*1ので、僕はもっぱら -eval を使っています。ただし、-s init sotp は決まり文句として使いますね。冒頭に挙げたコマンドラインが例です。

ブートスクリプトの指定

$OTP_ROOT/bin のなかに、*.boot というファイルがあります。標準では start_clean.boot と start_sasl.boot が存在します。このブートファイルには、init が初期化時に実行する手続きが書いてあります。

  • -boot BootFile -- ブートファイルの拡張子'.boot'を除いた名前を指定します。start_clean を指定すると最小限の初期化をします。冒頭に挙げたコマンドラインが例です。

コードパス、環境変数の設定

  • -pa Dir1 Dir2 ... -- コードパスの最初にディレクトリを追加します。
  • -pz Dir1 Dir2 ... -- コードパスの最後にディレクトリを追加します。
  • -env Variable Value -- OS環境変数VariableをValueに設定したのと同じ効果があります。

.erlang は実行されてしまう

./.erlang、~/.erlang の実行を抑制するオプションはないようです。バッチ的な実行では .erlang が邪魔になることがあります。~/.erlang を使うのをやめるか、ブートスクリプトを作り直すことになるでしょう(僕はやったことありません)。

*1:-s Mod とすると、Mod:start() が実行されます。推測ですが、-s のsはstartで、アプリケーションをスタートさせる目的で使われていたのではないでしょうか。