- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
问题
我发现大多数关于 Erlang 的文章和书籍都专注于创建长时间运行的类似服务器的应用程序,而没有涵盖命令行工具的创建过程。
我有一个包含 3 个应用程序的多应用程序 rebar3 项目:
myweb
- 一个 cowboy
基于网络服务; mycli
- 为 myweb
准备 Assets 的命令行工具; mylib
- 两者都使用的库 myweb
和 mycli
, 取决于 NIF。 rebar
和
relx
这样做。所以我试了一下。
mylib
; *.so
文件被嵌入到生成的 escript 文件中,它们无法在运行时加载,因此 NIF 不起作用(参见 erlang rebar escriptize & nifs); rebar3 escriptize
不能很好地处理依赖关系(请参阅 bug 1139 )。 main/1
; main/1
入口点、命令行参数和退出代码处理,同时仍然具有易于打包且不妨碍使用 NIF 的良好目录结构。
最佳答案
无论您是在 Erlang 中启动一个长时间运行的类似守护程序的应用程序,还是 CLI 命令,您始终需要以下内容:
erts
应用程序 - 特定版本中的 VM 和内核 escript
脚本,
sh
,
bash
等
escript
的明显优势在通用 shell 上是
escript
已经在 Erlang VM 的上下文中执行,因此无需处理启动/停止 VM。
erts
也没有任何带有您的包的 OTP 应用程序,您只需将特定的 Erlang 版本作为您的应用程序的依赖项。在第二种情况下,您提供
erts
以及所有必需的 OTP 应用程序以及应用程序包中的依赖项。
erl
Erlang 用来启动系统范围的 VM 的脚本:
# location: /usr/local/lib/erlang/bin/erl
ROOTDIR="/usr/local/lib/erlang"
BINDIR=$ROOTDIR/erts-7.2.1/bin
EMU=beam
PROGNAME=`echo $0 | sed 's/.*\///'`
export EMU
export ROOTDIR
export BINDIR
export PROGNAME
exec "$BINDIR/erlexec" ${1+"$@"}
node_package
Basho 用于为所有主要操作系统打包 Riak 数据库的工具。我在维护
my own fork我正在使用我自己的名为
builderl
的构建工具。 .我只是这么说,所以你知道如果我设法定制它,你也能做到这一点:)
mylib
库)。以下是如何实现这一目标的一些示例:
escript
示例
builderl.esh
example我如何处理从
builderl
加载其他 Erlang 应用程序.那个
escript
脚本假定 Erlang 安装与执行它的文件夹相关。当它是另一个应用程序的一部分时,例如
humbundee
,
load_builderl.hrl
包含文件编译和加载
bld_load
,依次加载所有剩余的模块
bld_load:boot/3
.请注意我如何使用标准 OTP 应用程序而不指定它们的位置 -
builderl
正在被
escript
执行所以所有的应用程序都是从它们的安装位置加载的(在我的系统上是
/usr/local/lib/erlang/lib/
)。如果您的应用程序使用了库,例如
mylib
, 安装在其他地方,您需要做的就是将该位置添加到 Erlang 路径中,例如与
code:add_path
. Erlang 会自动从添加到代码路径列表的文件夹中加载代码中使用的模块。
escript
执行。属于那个嵌入式 Erlang 版本而不是系统范围的版本(即使它已安装)。因此它知道属于该版本的所有应用程序(包括您的应用程序)的位置。例如
riak
正是这样做的 - 在他们的包装中,他们提供了一个
embedded Erlang release包含它自己的
erts
以及所有依赖的 Erlang 应用程序。那样
riak
甚至可以在主机操作系统上不安装 Erlang 的情况下启动。这是来自
riak
的摘录FreeBSD 上的软件包:
% tar -tf riak2-2.1.1_1.txz
/usr/local/sbin/riak
/usr/local/lib/riak/releases/start_erl.data
/usr/local/lib/riak/releases/2.1.0/riak.rel
/usr/local/lib/riak/releases/RELEASES
/usr/local/lib/riak/erts-5.10.3/bin/erl
/usr/local/lib/riak/erts-5.10.3/bin/beam
/usr/local/lib/riak/erts-5.10.3/bin/erlc
/usr/local/lib/riak/lib/stdlib-1.19.3/ebin/re.beam
/usr/local/lib/riak/lib/ssl-5.3.1/ebin/tls_v1.beam
/usr/local/lib/riak/lib/crypto-3.1/ebin/crypto.beam
/usr/local/lib/riak/lib/inets-5.9.6/ebin/inets.beam
/usr/local/lib/riak/lib/bitcask-1.7.0/ebin/bitcask.app
/usr/local/lib/riak/lib/bitcask-1.7.0/ebin/bitcask.beam
(...)
sh
/bash
main
函数)之外,这在原则上与上述没有太大区别。
builderl
生成启动一个 Erlang 应用程序只是为了执行指定的任务(生成
RELEASES
文件),之后节点关闭:
#!/bin/sh
START_ERL=`cat releases/start_erl.data`
APP_VSN=${START_ERL#* }
run_erl -daemon ../hbd/shell/ ../hbd/log "exec erl ../hbd releases releases/start_erl.data -config releases/$APP_VSN/hbd.config -args_file ../hbd/etc/vm.args -boot releases/$APP_VSN/humbundee -noshell -noinput -eval \"{ok, Cwd} = file:get_cwd(), release_handler:create_RELEASES(Cwd, \\\"releases\\\", \\\"releases/$APP_VSN/humbundee.rel\\\", []), init:stop()\""
-boot
选项指定)。
#!/bin/sh
START_ERL=`cat releases/start_erl.data`
APP_VSN=${START_ERL#* }
run_erl -daemon ../hbd/shell/ ../hbd/log "exec erl ../hbd releases releases/start_erl.data -config releases/$APP_VSN/hbd.config -args_file ../hbd/etc/vm.args -boot releases/$APP_VSN/humbundee"
vm.args
如果需要,您可以提供应用程序的其他路径,例如:
-pa lib/humbundee/ebin lib/yolf/ebin deps/goldrush/ebin deps/lager/ebin deps/yajler/ebin
lib
文件夹中)时,才需要这样做,正如 Erlang OTP 所要求的那样)。在适当的嵌入式 Erlang 版本中,应用程序位于
code root/ lib
文件夹,Erlang 能够加载这些应用程序而无需指定任何额外的路径。
sh
的形式拥有多个入口点。或 escript
脚本执行从已安装的版本中选择的应用程序。只要您正确配置了代码根目录和这些应用程序的路径(如上所述),两者都可以工作。 myweb
和
mycli
, 需要在它自己的新上下文中执行,例如启动一个新的 VM 实例并执行所需的应用程序(来自同一个 Erlang 版本)。如果是
myweb
入口点可以是
sh
根据版本启动新节点的脚本(类似于 Riak)。如果是
mycli
入口点可以是
escript
, 任务完成后即完成执行。
sh
启动的,也完全有可能创建一个退出 VM 的短期运行任务。 - 见上面的例子。在那种情况下
mycli
需要单独的发布文件 -
script
和
boot
启动虚拟机。当然,也可以从
escript
启动长期运行的 Erlang VM。 .
cmd
释放。 humbundee
释放。 builder.esh
escript
. $:~/work/humbundee/tmp/rel % ls | tr " " "\n"
bin
erts-7.3
etc
lib
releases
$:~/work/humbundee/tmp/rel % ls bin | tr " " "\n"
builderl.esh
cmd.boot
humbundee.boot
epmd
erl
escript
run_erl
to_erl
(...)
$:~/work/humbundee/tmp/rel % ls lib | tr " " "\n"
builderl-0.2.7
compiler-6.0.3
deploy-0.0.1
goldrush-0.1.7
humbundee-0.0.1
kernel-4.2
lager-3.0.1
mnesia-4.13.3
sasl-2.7
stdlib-2.8
syntax_tools-1.7
yajler-0.0.1
yolf-0.1.1
$:~/work/humbundee/tmp/rel % ls releases/hbd-0.0.1 | tr " " "\n"
builderl.config
cmd.boot
cmd.rel
cmd.script
humbundee.boot
humbundee.rel
humbundee.script
sys.config.src
cmd
入口点将使用应用程序
deploy-0.0.1
和
builderl-0.2.7
以及发布文件
cmd.boot
,
cmd.script
,以及一些 OTP 应用程序。标准
humbundee
入口点将使用除
builderl
之外的所有应用程序和
deploy
.然后是
builderl.esh
escript 将使用应用程序
deploy-0.0.1
和
builderl-0.2.7
.全部来自相同的嵌入式 Erlang OTP 安装。
关于erlang - 用 Erlang 编写的命令行工具的惯用方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36359040/
我想实现一个 Erlang 解释器,最近我在阅读 Erlang 的标准库源代码。我在 erlang.erl 中找到 erlang:display/1 的源代码是: %% display/1 -spec
我即将用 Erlang 构建一个系统(我的问题可以用多个 CPU 更好地解决),我已经浏览了: 向你学习一些 Erlang; Erlang/OTP 在行动 编程 Erlang(阿姆斯壮); Erlan
我真的很难理解 Erlang 中的尾递归。 我有以下 eunit 测试: db_write_many_test() -> Db = db:new(), Db1 = db:write(f
我不确定或者我不知道 erlang 定位不在默认目录中的模块的传统方式。我知道它会查看已编译的文件夹和 erlang 的系统文件夹或 - lists:foreach(fun (E) -> io:fwr
对 Erlang 完全陌生。我正在尝试为函数组合定义一些函数,例如 compose , juxt和 pipe但是遇到这样一个事实,即 Erlang 没有(据我所知)可变参数,因此很难只编写适用于所有输
在 Erlang 中存储和管理高性能可变对象的最佳方法是什么?假设我想编写具有实时游戏玩法的非常简单的在线游戏服务器。不知何故,我需要在 Erlang 内存中表示玩家的状态。例如,它可能只是一个简单的
警告:前面的 erlang n00b。 我正在尝试掌握 erlang,只是尝试与牛仔一起使用基本的 hello world 应用程序。我正在模拟一个错误,基本上是在我的代码中的某处返回一个无效值,并试
当你向 shell 进程发送消息时,你可以通过调用: c:flush(). 来清除所有消息。 C:\Windows\System32>erl Eshell V5.9(使用 ^G 中止) 1> 自我()
这应该是一个简单的问题,但我不太了解文档,无法找到答案。 如果 OTP 管理器在崩溃后重新启动 gen_server,新子进程是否继承了崩溃进程的消息队列,或者消息是否在崩溃之前发送但尚未由旧子进程处
我将 net_ticktime 值设置为 600 秒。 net_kernel:set_net_ticktime(600) 在 net_ticktime = TickTime 的 Erlang 文档中:
我正在监视一个 Erlang 应用程序,我目前正在尝试确定特定 PID 已经运行了多长时间。绝对时间戳或持续时间对我有用,但我在 process_info 或通过 sys 模块看不到这些数据位中的任何
我想重新定义查找特定单词的元组的顺序 例如,我有一个像这样的元组列表: [{"a",["r001"]}, {"bi",["bidder"]}, {"bo",["an"]}] 但有时元组的顺序可能会
以下几行出现在 http://aosabook.org/en/riak.html 中,在该部分的第二段: 15.1. Erlang 简介 : "Calling the function with a
我认为 Erlang 节点之间的消息不应该很大。如果我想构建一个流服务器,通常每个连接都需要很大的带宽,Erlang 能做好吗?如果是,是否有任何开源代码可供我学习?我了解到 Erlang 很适合处理
下一个代码在结果中给了我 5.999999999999998,但正确答案是 6。 Alpha = math:acos((4*4 + 5*5 - 3*3) / (2*4*5)) Area = 1/2 *
注意:这是我的 previous question 的进化延续。关于类似的话题。 一段时间以来,我一直在寻找有关部署和更新 Erlang/OTP 版本(一组应用程序)的“最佳实践”,但我找不到任何直接
我试图在头文件中指定一个函数。 像这样: -spec update(pid(), tuple(tuple(), integer(), atom()), tuple(atom(), atom())) -
所以我在过去的八个小时里一直在使用 Erlang,我花了两个时间用我的头敲击键盘试图找出我的控制台不断返回的异常错误。 我正在编写一个骰子程序来学习erlang。我希望它能够通过 erlang 解释器
当我编译以下模块时: -module(x). -export([inp/0]). f(X) -> g(X). g(X) -> error(X). inp() -> f(123)
我目前正在开发一个实时媒体服务器,它将允许普通消费者向我们发送实时视频。在我们当前的环境中,我们已经看到发送给我们的广播持续了几天,因此能够在不断开用户连接的情况下修复错误(或添加功能)的想法非常引人
我是一名优秀的程序员,十分优秀!