如何在实时应用程序中检查 DETS?

Posted

技术标签:

【中文标题】如何在实时应用程序中检查 DETS?【英文标题】:How to examine DETS on a live application? 【发布时间】:2018-06-23 22:07:42 【问题描述】:

我是 Erlang 的新手,但我想知道是否有可能以某种方式附加到一个工作应用程序并检查它正在使用的 ETS 或 DETS。如果是,您愿意举一个小例子吗?

谢谢!

【问题讨论】:

【参考方案1】:

如果您有权访问,您可以使用 Observer 查看 ETS 表。在 erlang shell 中,只需键入 observer:start(). 即可打开 GUI。

要连接到正在运行的命名节点,您可以使用 Erlang Shell 中的连接到远程节点选项。

启动一个命名节点

$erl -name application@hostname

从不同的机器或终端启动一个新的 erlang shell

$erl -name temp@hostname

从您的临时 erlang shell 连接到应用程序,按 Ctrl+g,然后按 h? 以获取选项列表。选项r 连接到远程节点,c 连接到新作业。

>r 'application@hostname'
>c

之后,您可以调用任何命令,就像您在该机器上的位置一样,调用任何模块:函数,并访问 ETS 表。

如果你在同一台机器上,没有别的,如果你在不同的机器上,你必须设置 cookie 以便它们匹配,否则你将无法连接。

断开连接时要小心,必须切换到本地节点才能退出,或者杀死临时应用程序,不要杀死真正的应用程序。

Rebar3

现在很多人使用 Rebar3 来创建和运行 Erlang 项目,如果你不这样做,我强烈推荐使用它。

使用 Rebar3,您可以使用 start 命令启动应用程序,并使用 attach 命令附加到正在运行的应用程序。您必须使用 Rebar3 发布才能使用这些命令。 More info here.

样本:

rel/my_app/bin/my_app start
rel/my_app/bin/my_app attach

然后按照上述方法访问 ETS 或使用erlang man pages 中列出的任何 ets 命令。

使用 ctrl+D 分离。

混搭 您可以使用常规的erl -name temp@hostname shell 连接到以 rebar3 开头的项目。只要 cookie 匹配并且您知道节点名称,您就不必使用 Rebar3 附加到正在运行的应用程序。

【讨论】:

【参考方案2】:

有两种方法可以做到这一点,根据 Erlang 节点的启动方式,这两种方法都可能有效,也可能无效:

使用to_erl 通过 Erlang 分发打开远程 shell (erl -remsh)

无论哪种方式,您最终都会得到一个 Erlang shell,您可以在其中检查您的表。


run_erl 和 to_erl

如果 Erlang 节点是使用 run_erl 包装器启动的,那么您可以使用 to_erl 连接到正在运行的节点。运行可以看到run_erl使用的命令:

ps -C run_erl -fww

例如,如果 Erlang 节点是使用以下命令启动的:

run_erl -daemon /my/erlang/node/tmp/ /my/erlang/node/log/ /my/erlang/node/start

那么命令中的三个路径对应:

    保存命名管道的目录 记录标准输出的目录 实际启动 Erlang 节点的命令

你想要to_erl的第一个,所以命令是:

to_erl /my/erlang/node/tmp/

注意尾部的斜线! to_erl 如果丢失,会感到困惑。

要退出,请输入Ctrl-D


使用 Erlang 分发连接

如果 Erlang 节点作为分布式节点运行,并且您知道秘密“cookie”,则可以启动另一个节点并打开远程 shell。

哪个节点名?长还是短?

您需要知道正在运行的节点的节点名称,以及它是以“长”还是“短”节点名称运行的。

在“长”节点名中,主机部分是完全限定的域名或 IP 地址,但在“短”节点名中,主机部分只是主机名,没有点。如果 Erlang 节点以 -name 选项启动,它使用长节点名称,如果它以 -sname 选项启动,它使用短节点名称。如果两个选项都没有使用,则它不是分布式节点,并且无法连接到它。1

并且主机名在命令中可能是显式或隐式的。如果命令看起来像其中之一,则您已经知道确切的节点名称:

erl -name myerlangnode@mymachine.example.com
erl -sname myerlangnode@mymachine

但如果 -name-sname 选项仅指定“裸”节点名称,您需要弄清楚它选择以哪个主机名开头:

erl -name myerlangnode    # node name is actually myerlangnode@mymachine.example.com
erl -sname myerlangnode   # node name is actually myerlangnode@mymachine

什么是cookie?

当一个 Erlang 节点连接到另一个节点时,两个节点需要配置相同的“cookie”,否则握手会失败。 cookie 可以从运行 Erlang 节点的用户的主目录中的文件.erlang.cookie 中读取,也可以在启动节点时使用-setcookie 命令显式设置。

让我们联系吧!

所以现在我们知道了:

运行节点使用的确切节点名称 节点是否以-name-sname 启动(即长或短节点名称) cookie 是从用户的主目录读取的还是用-setcookie 设置的

现在我们可以连接了!我们需要启动一个临时的 Erlang 节点:

使用-name-sname,取决于运行节点的启动方式 使用唯一的节点名称 要么使用与运行节点相同的-setcookie 选项,要么以相同用户身份运行以访问相同的.erlang.cookie 文件 使用-remsh(“远程shell”)连接到正在运行的节点。 使用 -hidden 避免被视为 Erlang 集群的一部分

所以是这样的:

erl -hidden -name mytmpnode -setcookie secret -remsh myerlangnode@mymachine.example.com
erl -hidden -sname mytmpnode -setcookie secret -remsh myerlangnode@mymachine

这应该会在正在运行的节点上打开一个 shell。您可以通过查看提示来判断,它应该告诉您节点名称:

(myerlangnode@mymachine)1>

如果它没有显示正确的节点名称,请参阅问题Erlang remote shell not working。

要退出,请输入Ctrl-g,然后输入q


检查 ETS 或 DETS 表

一旦你有了 Erlang shell,你就可以检查表了。使用ets:all()dets:all() 列出现有表。对于 ETS,您可以使用 ets:tab2list,它将所有条目显示在一个表格中:

ets:tab2list(my_table).

对于 DETS,您可以将 dets:match_object'_' 通配符模式一起使用:

dets:match_object(my_table, '_').

1 除非该节点作为非分布式节点启动,后来变为具有net_kernel:start 的分布式节点。

【讨论】:

非常感谢您的详细回答!

以上是关于如何在实时应用程序中检查 DETS?的主要内容,如果未能解决你的问题,请参考以下文章

如何在iOS中构建实时用户的状态更新

如何在 Android 上接收实时 API 数据更新?

如何实时检查文本字段输入?

如何检查python函数是否更改(在实时代码中)?

Django 实时作业

在 Android Studio 上使用 Java 检查实时数据库上的重复数据