停止 Erlang VM 的 10 种方法

您是否有一个不再需要的 Erlang VM 并且您不知道如何处理它?不用担心,我的朋友,这只是给你的清单!系好你的安全带,进入你的旧冰箱……我们会撞坏东西的

好的方法

有几种方法可以很好地关闭 Erlang VM……

1. q/0, c:q/0, init:stop/0

正如文档所说,最简单和最干净的方法是使用q/0或c:q/0(实际上是同一件事)……

此函数是 init:stop() 的简写,即它使节点以受控方式停止。

而且init:stop/0是……

与 stop(0) 相同。

所以,基本上你最终会运行init:stop(0).要了解该命令的作用,让我们再次检查文档:

所有应用程序都被顺利关闭,所有代码都被卸载,并且在系统通过调用halt(Status)终止之前关闭所有端口。如果指定了命令行标志-heart,则heart程序在 Erlang 节点终止之前终止。有关详细信息,请参阅heart(3)。 为了限制关闭时间,init允许关闭应用程序的时间,使用命令行标志-shutdown_time。

所以,这可能是最干净的关机形式。但你也可以跳过所有干净的部分,直接跳到……

2. erlang:halt/0

正如您在文档中看到的那样,erlang:halt()与erlang:halt(0, [])。除去下面与erlang:halt/1,2相关的更多内容,现在erlang:halt()只是关闭虚拟机,并没有正确地终止应用程序和正确地关闭端口。

3. JCL模式

以前的方法依赖于你能够在 shell 中运行命令(或者远程shell,如果你使用分布式 Erlang的话)。如果你不能这样做,例如,你阻止了你的shell或其他什么?好吧,如果您在要关闭的节点的shell中,即使它没有接收到输入,您仍然可以按Ctrl-g(这会将您带到JCL 模式)。在那里,您可以使用命令q退出 Erlang shell。

这与效果类似erlang:halt(0).

顺便说一句,这是在不停止原始节点的情况下停止remsh节点的最佳方法。

4. BREAK模式

您可以按Ctrl-c而不是 Ctrl-g 。这将带您进入BREAK 模式,如下所示:

BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
       (v)ersion (k)ill (D)b-tables (d)istribution

您可以做两件事来关闭那里的节点:

  • 再次按Ctrl-c。
  • 按a然后返回。

他们两个都会表现得像erlang:halt(0).

坏的方法

也许您确实想以一种不太好的方式退出系统并生成某种错误报告。这些是您的一些选择,然后……

5. erlang:halt/1,2

正如您在文档中看到的那样,有一些选项可以erlang:halt/1,2在输出时产生错误。您可以阅读文档上的选项,但关键部分是:

  • 如果您想要一个具有正确退出状态的干净关闭,您可以使用一个整数。
  • 如果要生成 erl_crash.dump,请使用字符串作为标语。
  • 如果要生成核心转储,请使用原子 abort。

当然,无论您的选择如何,都不会正确终止任何应用程序,也不会正确关闭任何端口等。

6. 直接杀死进程

当然,Erlang VM 最终只是你操作系统中的一个进程。而且,如果您的操作系统类似于 UNIX,您可以通过向它们发送信号来终止进程。不同的信号对 Erlang VM 有不同的影响。通常的信号按预期工作:kill -SIGTERM会表现得像init:stop().并且kill -SIGKILL会表现得像erlang:halt(137).(谢谢Tristan Sloughter澄清kill -SIGTERM)。

但是您可以使用另外一个信号 kill -SIGUSR1,在这种情况下生成一个 erl_crash.dump:。在生成的故障转储中,停止原因将是Received SIGUSR1.

丑陋的方法

嗯……关闭虚拟机的乐趣在哪里?因为它们应该被关闭?让我们把它们烧掉,而不是……

7. 不要让它开始

当你启动一个 Erlang VM 时,你可以通过在命令行中指定它们在 shell 启动之前运行命令(例如$ erl -s your_app,即在启动 shell 之前运行your_app:start())。但是,如果这些命令错误或损坏,会发生什么?💥 VM 崩溃并生成 erl_crash.dump。例如…

$ erl -s something_that_doesnt_exist
Erlang/OTP 20 [erts-9.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [kernel-poll:false]
init terminating in do_boot ({undef,[{something_that_doesnt_exist,start,[],[]},{init,start_em,1,[]},{init,do_boot,3,[]}]})
Crash dump is being written to: erl_crash.dump...done

8. Kill the Kernel

不管 Erlang 传奇的Let It Crash哲学(又名The Zen of Erlang)如何,Erlang VM 中有一个进程是不允许崩溃的:the application controller。所以,如果你杀了它……

$ erl
Erlang/OTP 20 [erts-9.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [kernel-poll:false]
1> exit(whereis(application_controller), kill).
true
*** ERROR: Shell process terminated! ***
*** ERROR: Shell process terminated! ***
*** ERROR: Shell process terminated! ***
*** ERROR: Shell process terminated! ***
*** ERROR: Shell process terminated! ***
*** ERROR: Shell process terminated! ***
*** ERROR: Shell process terminated! ***
*** ERROR: Shell process terminated! ***
*** ERROR: Shell process terminated! ***
*** ERROR: Shell process terminated! ***
{"Kernel pid terminated",application_controller,killed}
Kernel pid terminated (application_controller) (killed)
Crash dump is being written to: erl_crash.dump...done

9. 耗尽原子表

Erlang VM 中允许的原子数量巨大且可配置,但仍然有限。使用erlang:system_info/1我们可以确定该限制,当然,利用耗尽原子表您可以轻松生成的很大的 erl_crash.dump 之一(警告:生成 erl_crash.dump 可能需要很长时间):

$ erl
Erlang/OTP 20 [erts-9.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [kernel-poll:false]
1> [list_to_atom(integer_to_list(I)) || I <- lists:seq(erlang:system_info(atom_count), erlang:system_info(atom_limit))].
no more index entries in atom_tab (max=1048576)
Crash dump is being written to: erl_crash.dump...done

10. 直接关掉你的电脑(哈哈哈)

呵呵,不是这样啦。耗尽进程列表将是我的第 10 种方法,但是当我在 Erlang/OTP 20.1 安装上尝试此方法时,我发现它并没有崩溃。发生了不一样的事情……

原子表并不是 Erlang VM 中唯一受限的东西。另一个是进程数(可+P在命令行上配置)。使用与上面类似的方法,您可以尝试通过创建过多的 Erlang VM 来使它们崩溃,但您会在那里发现一个惊喜……

$ erl +P 1024
Erlang/OTP 20 [erts-9.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [kernel-poll:false]
1> [spawn(timer, sleep, [60000]) || I <- lists:seq(erlang:system_info(process_count), erlang:system_info(process_limit))].

这不会使虚拟机崩溃,而是会产生无穷无尽的…

=ERROR REPORT==== 29-Apr-2018::01:25:51 ===
Error in process <0.52.52> with exit value:
{system_limit,[{erlang,spawn_link,
                       [erlang,apply,[#Fun<shell.1.98304428>,[]]],
                       []},
               {erlang,spawn_link,1,[]},
               {shell,get_command,5,[{file,"shell.erl"},{line,300}]},
               {shell,server_loop,7,[{file,"shell.erl"},{line,230}]}]}
Eshell V9.0  (abort with ^G)
*** ERROR: Shell process terminated! ***
=ERROR REPORT==== 29-Apr-2018::01:25:51 ===
Too many processes

机器没有崩溃,但是 shell 进程确实崩溃了,当它尝试重新启动时,嗯……它一次又一次地崩溃。但其他一切都在继续运行。

我希望你喜欢这份清单。如果您认为我错过了其他一些使 Erlang VM 崩溃的方法,请在下面的评论中告诉我!: )

Related Posts

2021 年你需要知道的关于 Erlang 的一切

今天,我们将看一个相当古老且有些古怪的东西。 你们大多数人可能没有注意到的语言。 虽然 Erlang 不像某些现代编程语言那样流行,但它安静地运行着 WhatsApp 和微信等每天为大量用户提供服务的应用程序。 在这篇文章中,我将告诉你关于这门语言的更多事情、它的历史,以及你是否应该考虑自己学习它。 ## 什么是 Erlang,它在哪里使用? Erl

Read More

Erlang JIT中基于类型的优化

这篇文章探讨了 Erlang/OTP 25 中基于类型的新优化,其中编译器将类型信息嵌入到 BEAM 文件中,以帮助JIT(即时编译器)生成更好的代码。 ## 两全其美 OTP 22 中引入的基于SSA的编译器处理步骤进行了复杂的类型分析,允许进行更多优化和更好的生成代码。然而,Erlang 编译器可以做什么样的优化是有限制的,因为 BEAM 文件必须

Read More

Erlang JIT之路

自从Erlang 存在,就一直有让它更快的需求和野心。这篇博文是一堂历史课,概述了主要的 Erlang 实现以及如何尝试提高 Erlang 的性能。 ## Prolog 解释器 Erlang 的第一个版本是在 1986 年在 Prolog 中实现的。那个版本的 Erlang 对于创建真正的应用程序来说太慢了,但它对于找出Erlang语言的哪些功能有用,哪

Read More