首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

escript

命令

escript

命令摘要

Erlang脚本支持

描述

escript 为运行较短的Erlang程序提供支持,而无需先编译它们,并且提供了一种简单的方法来检索命令行参数。

可以将escript与一个Erlang运行时系统捆绑在一起,以使其自足并可重定位。 在这样的独立系统中,脚本应位于独立系统的顶部bin目录中,并以.escript作为文件扩展名。 此外,(内置)escript程序应该被复制到同一个目录并给出脚本的原始名称(不带.escript扩展名)。 这将允许使用捆绑的Erlang运行时系统。

(内置)escript程序首先确定要使用哪个Erlang运行时系统,然后启动它来执行脚本。 通常,运行时系统与escript程序本身位于相同的Erlang安装中。 但对于带有一个或多个脚本的独立系统,可能会出现这样的情况,即路径中的escript程序实际上启动了捆绑escript的运行时系统。 这是有意的,并且通常在独立系统bin目录不在执行路径中时发生(因为它可能导致其erl程序覆盖所需的一个),并且通过来自bin目录中的符号链接引用escript(s) 路径。

输出

script-name script-arg1 script-arg2...escript escript-flags script-name script-arg1 script-arg2...

escript运行用Erlang编写的脚本。

例子:

代码语言:javascript
复制
$ chmod u+x factorial
$ cat factorial
#!/usr/bin/env escript
%% -*- erlang -*-
%%! -smp enable -sname factorial -mnesia debug verbose
main([String]) ->
    try
        N = list_to_integer(String),
        F = fac(N),
        io:format("factorial ~w = ~w\n", [N,F])
    catch
        _:_ ->
            usage()
    end;
main(_) ->
    usage().

usage() ->
    io:format("usage: factorial integer\n"),
    halt(1).

fac(0) -> 1;
fac(N) -> N * fac(N-1).
$ ./factorial 5
factorial 5 = 120
$ ./factorial
usage: factorial integer
$ ./factorial five
usage: factorial integer

示例中Erlang脚本的标题与普通的Erlang模块不同。第一行旨在成为调用的解释行escript

但是,如果您escript按以下方式调用,则第一行的内容无关紧要,但不能包含Erlang代码,因为它将被忽略:

代码语言:javascript
复制
$ escript factorial 5

示例中的第二行包含对Emacs编辑器的可选指令,该指令使其进入用于编辑Erlang源文件的主要模式。如果指令存在,它必须位于第二行。

如果选择encoding存在的评论,它可以位于第二行。

由上述注释指定的编码适用于脚本本身。但是,I / O服务器的编码必须明确设置如下:

代码语言:javascript
复制
io:setopts([{encoding, unicode}])

standard_io的I / O服务器的默认编码为latin1,因为脚本在非交互式终端中运行(请参阅STDLIB用户指南中的选项摘要)。

在第三行(或第二行,取决于Emacs指令的存在),可以为仿真器指定参数,例如:

代码语言:javascript
复制
%%! -smp enable -sname factorial -mnesia debug verbose

这样的参数行必须以%%!该行开头,其余的行被解释为模拟器的参数。

如果您知道escript可执行文件的位置,则第一行可以直接指定路径escript,例如:

代码语言:javascript
复制
#!/usr/local/bin/escript

与任何其他类型的脚本一样,如果未设置脚本文件的执行位,则Erlang脚本在Unix平台上不起作用。(要打开执行位,请使用chmod +x script-name。)

其余的Erlang脚本文件可以包含Erlang 源代码内联梁文件内联存档文件

一个Erlang脚本文件必须包含该main/1函数。当脚本运行时,该main/1函数将被调用一系列表示指定给脚本的参数的字符串(不以任何方式更改或解释)。

如果main/1脚本中的函数成功返回,则脚本的退出状态为0。如果在执行期间生成异常,则会打印一条短消息,脚本以退出状态终止127

要返回您自己的非零退出代码,请调用halt(ExitCode),例如:

代码语言:javascript
复制
halt(1).

要检索脚本的路径名,请escript:script_name()从脚本中调用(路径名通常但不总是绝对的)。

如果文件包含源代码(如上例所示),则由epp预处理器处理。这意味着,例如,您可以使用预定义的宏(如?MODULE)并包含伪指令等-include_lib指令。例如,使用

代码语言:javascript
复制
-include_lib("kernel/include/file.hrl").

包含函数使用的记录的记录定义file:read_link_info/1。您还可以通过在此处包含编码注释来选择编码,但如果第二行中存在有效的编码注释,则优先。

脚本在运行之前会进行语法和语义的正确性检查。如果有警告(如未使用的变量),则会打印它们,脚本仍将运行。如果出现错误,则会打印并且脚本不会运行并且其退出状态为127

main/1函数的模块声明和导出声明都是可选的。

默认情况下,该脚本将被解释。您可以通过在脚本文件的某个位置包含以下行来强制编译它:

代码语言:javascript
复制
-mode(compile).

解释代码的执行比编译代码慢。如果大部分执行都是在解释代码中进行的,编译它可能是值得的,尽管编译本身需要一点时间。另外,native可以提供而不是compile。这使用本地标志编译脚本,根据escript特性可能会或可能不值得。

如前所述,脚本可以包含预编译的beam代码。在预编译脚本中,脚本头文件的解释与包含源代码的脚本相同。这意味着,你可以做一个beam通过前面加上行开始与该文件的可执行文件#!%%!上面提到的。在预编译脚本中,main/1必须导出该函数。

另一个选择是在脚本中包含整个Erlang存档。 在存档脚本中,脚本标题的解释与包含源代码的脚本相同。 这意味着您可以通过在文件前面加上以#开头的行来创建一个可执行档案文件。 和%%! 上文提到的。 在存档脚本中,必须导出主/ 1功能。 默认情况下调用与escript文件的基本名称相同的模块中的main / 1函数。 通过将flag -escript主模块设置为模拟器标志之一,可以覆盖此行为。 模块必须是具有导出的主/ 1功能的模块的名称。 有关存档和代码加载的更多信息,请参阅代码(3)。

在脚本中有一个头文件通常非常方便,特别是在Unix平台上。但是,标题是可选的,因此您可以直接“执行”Erlang模块,Beam文件或归档文件,而无需向它们添加任何标题。但是你必须按如下方式调用脚本:

代码语言:javascript
复制
$ escript factorial.erl 5
factorial 5 = 120
$ escript factorial.beam 5
factorial 5 = 120
$ escript factorial.zip 5
factorial 5 = 120

escript:create(FileOrBin, Sections) -> ok | {ok, binary()} | {error, term()}

类型

从部分列表中创建一个脚本。 这些部分可以按任意顺序指定。 escript以可选标题开头,后跟强制主体。 如果标题存在,它始终以shebang开头,可能后跟comment和emu_args。 shebang默认为“/ usr / bin / env escript”。 该注释默认为“这是一个 - * - erlang - * - 文件”。 创建的脚本可以作为二进制返回或写入文件。

作为函数如何使用的一个例子,我们创建一个使用emu_args来设置一些模拟器标志的解释脚本。 在这种情况下,它恰好禁用了smp_support。 我们还从新创建的脚本中提取不同的部分:

代码语言:javascript
复制
> Source = "%% Demo\nmain(_Args) ->\n io:format(erlang:system_info(smp_support)).\n".
"%% Demo\nmain(_Args) ->\n    io:format(erlang:system_info(smp_support)).\n"
> io:format("~s\n", [Source]).
%% Demo
main(_Args) ->
    io:format(erlang:system_info(smp_support)).

ok
> {ok, Bin} = escript:create(binary, [shebang, comment, {emu_args, "-smp disable"}, {source, list_to_binary(Source)}]).
{ok,<<"#!/usr/bin/env escript\n%% This is an -*- erlang -*- file\n%%!-smp disabl"...>>}
> file:write_file("demo.escript", Bin).
ok
> os:cmd("escript demo.escript").
"false"
> escript:extract("demo.escript", []).
{ok,[{shebang,default}, {comment,default}, {emu_args,"-smp disable"},
     {source,<<"%% Demo\nmain(_Args) ->\n    io:format(erlang:system_info(smp_su"...>>}]}

可以创建一个没有标题的文本,如下所示:

代码语言:javascript
复制
> file:write_file("demo.erl", ["%% demo.erl\n-module(demo).\n-export([main/1]).\n\n", Source]).
ok
> {ok, _, BeamCode} = compile:file("demo.erl", [binary, debug_info]).
{ok,demo,
    <<70,79,82,49,0,0,2,208,66,69,65,77,65,116,111,109,0,0,0,
      79,0,0,0,9,4,100,...>>}
> escript:create("demo.beam", [{beam, BeamCode}]).
ok
> escript:extract("demo.beam", []).
{ok,[{shebang,undefined}, {comment,undefined}, {emu_args,undefined},
     {beam,<<70,79,82,49,0,0,3,68,66,69,65,77,65,116,
             111,109,0,0,0,83,0,0,0,9,...>>}]}
> os:cmd("escript demo.beam").
"true"

在这里,我们创建一个包含Erlang代码和Beam代码的归档脚本,然后遍历归档中的所有文件,收集它们的内容和一些有关它们的信息:

代码语言:javascript
复制
> {ok, SourceCode} = file:read_file("demo.erl").
{ok,<<"%% demo.erl\n-module(demo).\n-export([main/1]).\n\n%% Demo\nmain(_Arg"...>>}
> escript:create("demo.escript", [shebang, {archive, [{"demo.erl", SourceCode}, {"demo.beam", BeamCode}], []}]).
ok
> {ok, [{shebang,default}, {comment,undefined}, {emu_args,undefined}, {archive, ArchiveBin}]} = escript:extract("demo.escript", []).
{ok,[{shebang,default}, {comment,undefined}, {emu_args,undefined},
     {{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105,
                152,61,93,107,0,0,0,118,0,...>>}]}
> file:write_file("demo.zip", ArchiveBin).
ok
> zip:foldl(fun(N, I, B, A) -> [{N, I(), B()} | A] end, [], "demo.zip").
{ok,[{"demo.beam",
      {file_info,748,regular,read_write,
                 {{2010,3,2},{0,59,22}},
                 {{2010,3,2},{0,59,22}},
                 {{2010,3,2},{0,59,22}},
                 54,1,0,0,0,0,0},
      <<70,79,82,49,0,0,2,228,66,69,65,77,65,116,111,109,0,0,0,
        83,0,0,...>>},
     {"demo.erl",
      {file_info,118,regular,read_write,
                 {{2010,3,2},{0,59,22}},
                 {{2010,3,2},{0,59,22}},
                 {{2010,3,2},{0,59,22}},
                 54,1,0,0,0,0,0},
      <<"%% demo.erl\n-module(demo).\n-export([main/1]).\n\n%% Demo\nmain(_Arg"...>>}]}

escript:extract(File, Options) -> {ok, Sections} | {error, term()}

类型

分析一个文本并摘录它的章节。这是create/2...

即使它们不存在于escript中,也会返回所有部分。如果特定部分恰好与默认值具有相同的值,则将提取的值设置为原子default。如果某个部分缺失,则将提取的值设置为原子undefined

如果escript包含源代码,则选项compile_source仅影响结果。 在这种情况下,Erlang代码会自动编译并返回{source,BeamCode},而不是{source,SourceCode}。

例子:

代码语言:javascript
复制
> escript:create("demo.escript", [shebang, {archive, [{"demo.erl", SourceCode}, {"demo.beam", BeamCode}], []}]).
ok
> {ok, [{shebang,default}, {comment,undefined}, {emu_args,undefined}, {archive, ArchiveBin}]} = escript:extract("demo.escript", []).
{ok,[{{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105,
                152,61,93,107,0,0,0,118,0,...>>}
     {emu_args,undefined}]}

escript:script_name() -> File

类型

返回正在执行的记录的名称。如果函数是在文本上下文之外调用的,则行为是未定义的。

选项接受的选项

-c无论mode属性的值如何都编译脚本。 -d调试脚本。 启动调试器,将包含main / 1函数的模块加载到调试器中,在main / 1中设置断点并调用main / 1。 如果模块是预编译的,则必须使用选项debug_info进行显式编译。 -i无论mode属性的值如何,都要解释escript。 -s执行脚本文件的语法和语义检查。 警告和错误(如果有)写入标准输出,但脚本不会运行。 如果发现任何错误,则退出状态为0,否则为127. -n使用flag + native编译escript。

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com