天天看点

【原创】Erlang 之 entop 使用问题

   工欲善其事,必先利其器。排查 erlang 系统问题时,肯定希望能有一个像 unix top 一样的工具,entop 就是这么个东东。 

---------- 我是三月份发版本天天加班的分隔线 ----------- 

(以下内容翻译自 entop 的 readme.md 文件) 

entop 

如同 unix 中 top 一样的 erlang 节点信息查看工具。 

简介 

      entop 是用来展示远端 erlang 节点运行信息的工具,其信息显示的方式类似于 unix 中的 top 命令。

      若要保证 entop 的正常运行,在 pre-r15 环境下,需要使用 cecho 0.3.0 版本;在 r15 或更高版本的环境下需要 cecho 0.4.0 版本。

编译 

清理和编译可以分别运行如下命令 

注意:如果你遇到和 cecho 依赖相关的问题,可以手动创建符号链接到 deps/ 下的 cecho (如果你的 cecho 放在其他目录也可以进行类似操作),或者运行 ./rebar get-deps 以下载最新版本。当通过 rebar 获取到最新版本后,不要忘记重新编译整个应用。 

用法 

      若想成功运行 entop ,首先要确保 erlang 已经安装到你的系统之中,并且 cecho 库所在路径被 erlang code path 所包含。 项目中默认提供的启动脚本(entop)假定了其在 entop 应用根目录下被执行,如果这与你的实际情况不符,请自行调整脚本的相应路径,或者直接确保 entop 的 ebin/ 目录包含在 erlang code path 之中。详情请参考启动脚本具体内容。 

entop 的运行示例 

用户接口 

entop 的接口允许用户定制化,所以本节描述的接口均为“内置”接口。 

表头信息 

第一行 主要展示了节点的静态信息,例如节点名、操作系统类型、指定的 erl flag 、当前所运行的 erlang 版本信息。 

第二行 展示了(目标节点所在机器的)本地时间、目标节点已持续运行的时间(格式为 days:hours:minutes:seconds)、运行 entop 的节点与目标节点之间的网络延迟情况(即 net_adm:ping() 成功交互所需花费的时间) 

第三行 展示了系统中每个进程的具体信息、进程的总数、运行队列中的进程数量(由调度器进行调度的待运行进程数量)、reductions per interval (rpi) 值(自从上一次 called the node 后系统已经 reduction 的次数)、以及每个进程占用的内存量。 

第四行 展示了系统内存使用量、atom 内存占用量(当前使用量/总体分配量)、binary 内存占用量、code 内存占用量,以及 ets 内存占用量。 

第五行 为空白,目前作为预留。 

第六行 为和行内容展示相关的信息,例如信息获取时间间隔、信息展示排序方式,以及获取相关信息所耗费的时间。 

在 entop 运行状态下可以使用的控制命令: 

[1-n]: 根据指定列编号进行输出内容排序。第一列编号为 1 ,其他列按顺序增加。 

r: 在升序排序和降序排序之间进行切换。 

q: 从 entop 中退出返回 shell 命令行。 

ctrl-c: 等价于 'q' 命令。 

'<' 和 '>': 将当前排序列左移或者右移(注意:次数为小于和大于号,非箭头) 

      按照 readme.md 中的说明 “entop 的正常运行在 pre-r15 情况下需要 cecho 0.3.0 的支持,在 r15 或更高版本的情况下需要 cecho 0.4.0 的支持” 做了如下配置变更。 

通过 entop 连接到 rabbitmq 进程进行查看 

通过挂起回到前台,查看 entop 相关进程运行情况,并强杀 

可以看到,按照上面的操作,我们失败了,排查错误的原因,我 查看了 cecho 的代码。 

在 cecho_srv.erl 中 

查看手册,针对 erl_ddll/load/2 有如下说明 

---------- 我是三月份发版本天天加班的分隔线 -----------

(以下内容翻译自 kernel-2.15.2)

load(path, name) -> ok | {error, errordesc}

types: 

path = path() 

name = driver() 

errordesc = term()

加载并链接名为 name 的动态 driver 。path 为包含该 driver 的目录。name 指定的对象必须为共享对象或动态链接库。 

若两个 driver 具有不同的 path 参数(即在不同路径下),则无法通过相同的 name 进行加载。 

name 的值对应 path 目录下的动态加载对象文件,但是去除了扩展名(例如,移除了 .so 后缀)。 

在 driver 初始化函数中指定的 driver 名字方式,在很大程度上,与指定对应了 .beam 文件的 erlang 模块名一样。 

如果对 driver 执行了卸载动作,但由于 port 仍旧处于 open 状态,故此 driver 实际上仍旧存在,此时若调用 load/2 ,则会停止针对 driver 的卸载行为,使得该 driver 得以保留(只要 path 没有发生过变更),并会返回 ok 。 

如果确实打算重新加载对象代码(driver),则可以使用 reload/2 或者底层的接口 try_load/3 进行操作。 

针对不同的场景下的加载/卸载行为描述请参考具体说明。 

如果超过一个进程想要使用相同的 path 加载一个已经加载过的 driver ,或者如果相同的进程想要加载同一个 driver 多次,该函数调用都会返回 ok 。 

模拟器会跟踪 load/2 被调用的次数,以便在相同数量的 unload/2 被调用后才真正卸载该 driver 。 

如此,才能保证一个应用安全的加载一个 driver ,无论该 driver 是在多 erlang 进程间共享,还是在多 erlang 应用间共享。同样能保证 driver 的安全卸载,而不会对系统的其他部分产生影响。 

以相同的 name 但不同的 path 加载多个 driver 是不允许的; 

注意: 

需要注意的是,path 参数的值是按字面量解析的,所以针对统一 driver 的多次加载都需要指定具有相同字面量的 path 字符串,即使不同的路径表达均指向相同的文件系统目录也不行(比如使用相对路径或链接的情况)。 

函数执行成功后返回 ok ;函数执行失败后返回 {error, errordesc} ,其中 errordesc 为 opaque term ,可以通过 format_error/1 翻译成人可读的格式。 

若希望对错误处理有更多控制,则需要使用 try_load/3 接口。 

该函数会在入口参数不符合要求的情况下,抛出 badarg 异常。 

根据上述信息,查看源码目录 priv 下,会在编译 cecho 后生成的 cecho.so 文件 

我擦,果然其中没有定义 scrollok 符号……erlang 果不欺我~~~ 

ok ,变回原始配置再再做一次挑战... 

整个过程下来,没发现有啥具体区别啊!!如何破?! 

      在没有其他思路的请款下,就让我们简单粗暴一点吧,直接拉下来 master 和 0.4.0 两个版本的代码进行比较~~ 

【原创】Erlang 之 entop 使用问题
【原创】Erlang 之 entop 使用问题
【原创】Erlang 之 entop 使用问题

结果很明显,只有 rebar.config 中的不同才是问题关键。 

这条配置信息从字面上就可以理解,ldflags 是用来设置 link 选项的,所以上面是指定了对 ncurses 库的链接依赖。 

回头再看依赖 cecho.so 的库依赖关系(之前少看了该信息,5555...) 

而在引用 0.4.0 版本的 cecho 时,信息如下 

果然存在差别!这也就解释了为何 scrollok 符号在两次结果中虽然都是 u 状态,但基于 master 的编译却可用的原因,因为 scrollok 符号在 libncurses.so.5 中~~ 

手动在 0.4.0 版本的 cecho 的 rebar.config 文件中添加 {port_envs, [{"ldflags", "$ldflags -lncurses"}]}. 后,重新编译运行,一切正常~~ 

上一篇: div滚动条
下一篇: sql 常用函数