如何从shell中获取Erlang的发布版本号?

133
许多程序使用类似以下命令返回其版本号:

Many programs return their version number with a command like:


$ program --version
program (platform info) v1.2.3

这对于脚本安装或程序维护以及系统管理员和朋友们进行其他受控自动化操作非常有用。

问题

如何轻松获取Erlang(OTP)的版本号?

网络上的方法

以下是一些不令人满意的解决方案(来自trapexit论坛和其他教程/Erlang文档):

模拟器

$ erl
1> erlang:system_info(otp_release).
"R13B03"

难以编写脚本。我还没有找到一种方法可以让erl从shell提示符中执行单个命令。

版本文件

$ cat /usr/lib/erlang/releases/RELEASES
[{release,"OTP  APN 181 01","R13B03","5.7.4",
      [{kernel,"2.13.4","/usr/lib/erlang/lib/kernel-2.13.4"},
       {stdlib,"1.16.4","/usr/lib/erlang/lib/stdlib-1.16.4"},
       {sasl,"2.1.8","/usr/lib/erlang/lib/sasl-2.1.8"}],
      permanent}].

使用 shell 解析天堂。

另一个选择是检查安装路径,但这不是可移植的(我的安装路径中并未包含版本号)。

个人背景:我正在编写一个脚本,在几台机器上安装带插件的相同版本的 RabbitMQ。一些插件对 OTP 版本有最低要求,这就是这个问题的起点。


RELEASES有什么不好的呢?它可以轻松地被Erlang解析 :-) - Julian Fondren
哦,那没关系!我编辑了帖子以便更好理解。我的意思是用 shell 工具解析 Erlang 字符串。我的目标是为一个 Erlang 包编写 SA 任务脚本。 - Eric Platon
我还不理解 Erlang 语法,我只想检查安装的版本是否支持 Riak。我收藏了这个问题,并希望有一天 Erlang 可以提供一种更简单的方式向依赖它的工具的管理员报告其版本。 - Iain Samuel McLean Elder
erl --version。 - Michael Dimmitt
12个回答

177
 erl -eval 'erlang:display(erlang:system_info(otp_release)), halt().'  -noshell

3
这在我的Windows 7上打印出(无错误记录器)错误:"进程<0.0.0>中的错误。-1 - Jonas
@Jonas 尝试使用 werl 而不是 erl。 - tmj
1
@andPat,你的建议对我来说返回了erlang _shell_的版本(例如7.0.2),而不是erlang本身(在我的情况下为18)。 - gdw2
7
从Erlang的文档中了解到:从OTP 17版本开始,OTP发行版本号对应于主要OTP版本号。没有给定erlang:system_info()参数可以得到确切的OTP版本信息。在我的开发机器上,下面是一个更丑陋的命令,它还打印出次要版本号。 - Jay
3
在 Windows 7 上,我必须将单引号替换为双引号。erl -eval "erlang:display(erlang:system_info(otp_release)), halt()." -noshell - yohosuff
显示剩余2条评论

121
其他答案只显示OTP 17及以后的主要版本(来自erlang文档:system_info)。这个可以在我的开发机器上显示主要和次要版本号:
erl -eval '{ok, Version} = file:read_file(filename:join([code:root_dir(), "releases", erlang:system_info(otp_release), "OTP_VERSION"])), io:fwrite(Version), halt().' -noshell

这将从适当的文件中读取,如文档所述。

4
谢谢,这很有用!还可以去掉引号和\n,并通过一次更改使代码更短:erl -eval '{ok, Version} = file:read_file(filename:join([code:root_dir(), "releases", erlang:system_info(otp_release), "OTP_VERSION"])), io:fwrite(Version), halt().' -noshell - Dogbert
1
在Windows 7上,我必须将单引号与双引号交换(反之亦然)。 erl -eval "{ok, Version} = file:read_file(filename:join([code:root_dir(), 'releases', erlang:system_info(otp_release), 'OTP_VERSION'])), io:fwrite(Version), halt()." -noshell - yohosuff

51

(因为我最近三个月已经搜索了至少3次,所以我在这里添加了这个答案)

从版本17.0开始,版本号采用新的格式(17.0、17.1等),但是erlang:system_info(otp_release).只返回主要版本号。

为了获取完整的版本号,需要检查releases文件夹下的OTP_RELEASE文件的内容。

$ which erl
/usr/bin/erl
$ cd /usr/bin
$ ls -l erl
../lib/erlang/bin/erl
$ cd ../lib/erlang/
$ cat releases/17/OTP_RELEASE
17.3

编辑

# Some versions seem to have OTP_VERSION instead of OTP_RELEASE
$ cat releases/17/OTP_VERSION
17.4

根据您的描述,我无法找到该文件,“find / -name“ OTP_RELEASE”也无法找到它,但是我已经安装了OTP 17.x。我如何知道“x”是什么? - NobbZ
2
@NobbZ 我更新了答案并添加了额外的信息,我刚刚检查了一下,在我安装的当前Erlang/OTP版本(17.4)中,该文件实际上被称为OTP_VERSION - juan.facorro
3
使用以下一行命令:cat $(dirname $(dirname \which erl`)/$(readlink `which erl`))/../releases/*/OTP_*` - Lol4t0

20

要获取 EShell(Erlang Shell)的版本信息,您可以使用:

erlang:system_info(version).

并且检索 Erlang OTP (开放电信平台) 版本:

erlang:system_info(otp_release).


在此输入图片描述


3
最佳答案。虽然你希望“--version”能够运行。 - Charlie

14

init文档,由 'man erl' 链接。

-eval Expr

在系统初始化期间扫描、解析和评估任意表达式Expr。如果其中任何一步失败(语法错误、解析错误或在评估期间出现异常),Erlang 将停止并显示错误消息。以下是一个示例,该示例种子随机数生成器:

% erl -eval '{X,Y,Z} = now(), random:seed(X,Y,Z).'

这个例子使用 Erlang 作为十六进制计算器:

% erl -noshell -eval 'R = 16#1F+16#A0, io:format("~.16B~n", [R])'  -s erlang halt
BF

如果指定了多个-eval表达式,则按照指定的顺序依次计算。-eval表达式与-s和-run函数调用一起按照指定的顺序进行逐个计算。与-s和-run一样,未终止的计算会阻止系统初始化过程。

因此,

$ erl -noshell -eval 'io:fwrite("~s\n", [erlang:system_info(otp_release)]).' -s erlang halt

谢谢你,朱利安,提供的详细信息。我怎么会忘记在手册中搜索“eval”关键字呢? - Eric Platon

8
/usr/lib/erlang/releases/18/OTP_VERSION 中查找。

可以,没问题。和问题中的release file部分一样,你的提议的问题在于它假设了安装路径的知识。这里的好处是获得完整的版本号。对我来说:18.2.1 - Eric Platon
这个文件在CentOS 7上不存在。 - Eduardo Cuomo
/usr/lib/erlang/releases - 通过 Ansible 安装 - Olga

4

erl +V 或者你可以使用 erl -version

结果: Erlang (SMP, ASYNC_THREADS) (BEAM) 模拟器版本 5.8.5


5
这将返回erl模拟器版本,而不是Erlang发行版的版本号(例如“R15B03”)。这一切可能会很容易;-) - Eric Platon

2

打开终端并输入命令 erl

您将获得以下输出:

Erlang R16B03 (erts-5.10.4) [source] [64-bit] [smp:4:4] [async-threads:10] [kernel-poll:false] Eshell V5.10.4 (abort with ^G)

Erlang R16B03 (erts-5.10.4) [source] [64-bit] [smp:4:4] [async-threads:10] [kernel-poll:false] - 这是语言版本

Eshell V5.10.4 (abort with ^G) - 这是 shell 版本


2

根据Jay的回答,我编写了以下可用的shell函数:

erlang () {
    if [[ $@ == "-v" ]]; then
        command erl -eval '{ok, Version} = file:read_file(filename:join([code:root_dir(), "releases", erlang:system_info(otp_release), "OTP_VERSION"])), io:fwrite(Version), halt().' -noshell
    else
        command erl
    fi
}

我经常会忘记命令是erl而不是erlang,所以这让我健忘的大脑可以像使用elixir一样使用erlang,以及erlang -v


2
在您的PATH中查找erl,并读取RELEASES文件以提取erlang版本号。
awk -F, 'NR==1 {gsub(/"/,"",$3);print $3}' "$(dirname $(readlink -f $(which erl)))/../releases/RELEASES"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接