ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Erlang/OTP 嵌入式系统守护利器:run_erl 命令完全指南

Erlang/OTP 嵌入式系统守护利器:run_erl 命令完全指南 编程语言语言运行时标准库编译器并发编程【免费下载链接】otpErlang/OTP项目地址https://gitcode.com/gh_mirrors/ot/otp点击查看免费下载导读run_erl是 Erlang/OTP 运行时系统ERTS中面向 Unix 系统的核心工具负责将 Erlang 模拟器的标准输入输出流重定向为可持久化的日志并通过命名管道FIFO与终端会话解耦使无头headless嵌入式系统可以被远程监控和调试。读完本文你将掌握run_erl的完整命令行语法、日志轮转机制、全部环境变量调优手段以及它与start、start_erl、to_erl协同构建嵌入式 OTP 系统的完整链路。概述run_erl 解决什么问题在传统的交互式 Unix 环境中Erlang 模拟器直接挂接在用户终端上运行一旦终端断开输出就会丢失进程也可能收到 SIGHUP 而终止。而对于部署在嵌入式设备、服务器后台的 OTP 系统通常不存在交互式 shell且要求所有输出可追溯、进程可与启动它的终端完全脱离。run_erl正是为解决这一矛盾而生。它在 Unix 上做了两件关键的事见 run_erl.c 头部注释中的架构说明重定向并记录所有 I/O将标准输入、标准输出重定向到日志文件实现输出全量落盘提供远程接入通道通过一对命名管道FIFO开放接入点让to_erl程序可以随时挂接到 Erlang console从而在远程监控和调试嵌入式系统。官方对它的定位在 run_erl_cmd.md 中描述得很清楚该程序专属于 Unix 系统更多使用背景可参考 Embedded System Users Guide嵌入式系统用户指南。命令语法与参数详解run_erl的命令行形式如下run_erl [-daemon] pipe_dir/ log_dir exec command arg1 arg2 ...-daemon后台守护模式强烈推荐该选项使run_erl完全在后台运行彻底脱离任何控制终端命令随即返回调用者。没有它你必须借助 shell 中的若干技巧如重定向、等才能把run_erl与启动它的终端彻底分离。关键约束-daemon必须是命令行上的第一个参数。pipe_dir命名管道目录命名管道存放的目录通常为/tmp/。该参数必须以/斜杠结尾即应写成/tmp/epipes/而非/tmp/epipes。to_erl默认也使用/tmp/作为管道目录二者必须一致才能连接成功。实际的管道文件命名为erlang.pipe.N见 run_erl.c 中的PIPE_STUBNAME erlang.pipe宏定义。log_dir日志目录run_erl在此目录下维护两类日志run_erl.log记录run_erl程序自身的运行进度与警告源码中对应STATUSFILENAME /run_erl.log见 run_erl.cerlang.log.N最多 5 个、每个最大 100 KB 的日志文件内容为命令的标准流输出。文件数量与单文件大小均可通过环境变量调整见下文 环境变量。当日志写满后run_erl会删除并复用最旧的日志文件实现循环轮转。exec command arg1 arg2 ...要执行的命令一个以空格分隔的字符串指定要执行的程序。第二个字段通常是命令名典型用法是erl。注意它用exec前缀引导表示用该命令替换当前进程映像。生产环境中的真实调用示例Erlang/OTP 自带的start启动脚本start.src中实际的调用形态为$ROOTDIR/bin/run_erl -daemon /tmp/ $LOGDIR exec $ROOTDIR/bin/start_erl $ROOTDIR $RELDIR $START_ERL_DATA该脚本会根据权限自动选择日志目录优先/var/log否则$HOME/.local/state/erlang或$XDG_STATE_HOME/erlang并调用run_erl后台启动start_erl最终拉起 Erlang 模拟器。这是-daemon选项在真实嵌入式部署中的标准用法。工作原理FIFO 与 pty 的数据通路从源码角度看run_erl的本质是一个读写中继进程。在 run_erl.c 头部有一幅清晰的 ASCII 架构图将其翻译如下________ _________ | |---- pipe.r (fifo1) ----| | | to_erl | | run_erl | (parent) |________|---- pipe.w (fifo2) ----|_________| ^ master pty | | slave pty ____V____ | | | erl | (child) |_________|数据流为to_erl操作员终端↔ 两条 FIFOpipe.r / pipe.w↔run_erl父进程↔ pty 主从设备 ↔erl子进程即 Erlang 模拟器。run_erl打开两条 FIFO一条用于读、一条用于写它通过open_pty_master/open_pty_slave创建伪终端pty让子进程erl挂接在 pty 从设备上从而即使没有真实终端也能正常运行从读 FIFO 收到的输入转发给 pty从 pty 读到的输出同时写入 stdout 与写 FIFO——而写 FIFO 的另一端正是to_erl通过这种设计Erlang 输出原样uninterpreted落入日志文件且所有与 shell 的交互都被完整记录。此外run_erl.h 中定义了to_erl与run_erl之间的握手协议版本RUN_ERL_HI_VER 1/RUN_ERL_LO_VER 0自 R12B-3 起加入版本握手与窗口尺寸控制保证不同版本的工具之间可以安全通信。日志文件机制详解文件命名与循环轮转运行期间run_erl将全部输出原样写入名为erlang.log.N的文件其中N为整数代generation。当日志满时默认 100 KB转入erlang.log.(N1)继续写直到N达到上限默认 5此时N重新从 1 开始最旧的文件开始被覆盖。embedded.md 中给出了日志目录随时间演变的完整序列erlang.log.1 erlang.log.1, erlang.log.2 erlang.log.1, erlang.log.2, erlang.log.3 erlang.log.1, erlang.log.2, erlang.log.3, erlang.log.4 erlang.log.2, erlang.log.3, erlang.log.4, erlang.log.5 erlang.log.3, erlang.log.4, erlang.log.5, erlang.log.1 ...每一行中最右侧的文件是最新的。也就是说最新文件通常是编号最高的但当已有四个文件时最新的是跳跃缺口前的那个。这正是循环轮转的自然结果为了标明最新文件run_erl会删除最旧的文件在文件序列中保持一个空洞hole。例如目录中同时存在 #1、#2、#4、#5则意味着 #2 最新、#4 最旧。一个值得注意的推论实际存在的日志文件数量最多比RUN_ERL_LOG_GENERATIONS设定值少一个。时间戳与 ALIVE 消息为避免日志中长时间无声导致的困惑run_erl引入了两类时间戳ALIVE 消息当 Erlang shell 无任何输出、但模拟器看起来仍然存活时默认在15 分钟静默后写入一条ALIVE消息其格式为 ALIVE date-time-string活动时间戳当有 Erlang 输出被记录但距上次输出已超过5 分钟默认时在日志中插入一个纯时间戳 date-time-stringdate-time-string为消息写入时刻的时间默认使用本地时间可改为 UTC由 ANSI-C 函数strftime按格式串%a %b %e %T %Z %Y格式化例如 ALIVE Thu May 15 10:13:36 MEST 2003该格式可通过RUN_ERL_LOG_ALIVE_FORMAT环境变量修改。环境变量详解以下环境变量被run_erl识别用于调整日志行为。这些变量的解析与默认值均可直接在 run_erl.c 的源码中找到对应实现getenv调用与DEFAULT_LOG_*宏定义。环境变量作用默认值取值范围/说明RUN_ERL_LOG_ALIVE_MINUTES静默多久后写入ALIVE消息15最小 1分钟RUN_ERL_LOG_ACTIVITY_MINUTESErlang 不活跃多久后输出前加时间戳ALIVE_MINUTES div 3即 5最小 1分钟RUN_ERL_LOG_ALIVE_FORMAT传给strftime的时间格式串%a %b %e %T %Z %Y最大 256 字符ALIVE_BUFFSIZRUN_ERL_LOG_ALIVE_IN_UTC时间显示是否使用 UTC未设置本地时间设为非0的值即启用 UTCRUN_ERL_LOG_GENERATIONS轮转前保留的日志文件数量5最小 2最大 1000RUN_ERL_LOG_MAXSIZE单个日志文件切换前的字节数100000约 100 KB最小 1000最大约 2^30RUN_ERL_DISABLE_FLOWCNTRL禁用 pty 的输入输出流控未定义只要被定义即生效RUN_ERL_LOG_ALIVE_MINUTES控制写入ALIVE消息前的等待时间分钟。默认 15最小 1。源码中对应DEFAULT_LOG_ALIVE_MINUTES 15宏run_erl.c并在解析时校验小于 1 的值并报错。RUN_ERL_LOG_ACTIVITY_MINUTESErlang 需要保持不活跃多久输出才会被前置时间戳。默认值为RUN_ERL_LOG_ALIVE_MINUTES div 3即 15 ÷ 3 5最小为 1。源码常量DEFAULT_LOG_ACTIVITY_MINUTES 5与之对应。RUN_ERL_LOG_ALIVE_FORMAT指定传给 C 库函数strftime的另一种格式串。例如设为%e-%b-%Y, %T %Z时间戳将变成15-May-2003, 10:23:04 MET默认值为%a %b %e %T %Z %Y。源码以ALIVE_BUFFSIZ 256为缓冲区上限格式串超过 256 字符会被拒绝并报错。RUN_ERL_LOG_ALIVE_IN_UTC设置为任何非0的值时run_erl显示的所有时间改用 UTCGMT、CET、MET 等无夏令时而非本地时间。注意这不影响来自 Erlang 的数据只影响run_erl自己直接输出的日志。若要同步调整 SASL 应用可将 Erlang 应用变量utc_log设为true。RUN_ERL_LOG_GENERATIONS控制旧文件被复用前保留的日志文件数量。默认 5最小 2最大 1000。源码中的约束宏为LOG_MIN_GENERATIONS 2与LOG_MAX_GENERATIONS 1000。如前文所述由于空洞机制实际可见文件数会少一个。RUN_ERL_LOG_MAXSIZE单个日志文件在切换到新文件前的字节数。默认 100000最小 1000最大约 2^30。源码常量DEFAULT_LOG_MAXSIZE 100000与LOG_MIN_MAXSIZE 1000与之对应。RUN_ERL_DISABLE_FLOWCNTRL若被定义则禁用run_erl所开 pty 的输入输出流控。这用于消除误按Ctrl-S而非用于分离的Ctrl-D意外阻塞流控的风险——一旦流控被阻塞整个 Beam 进程都会被卡住当使用heart作为监督者时heart 进程在向终端写日志消息时同样会被阻塞从而无法执行其监督工作。源码中该分支通过tcgetattr/tcsetattr清除终端标志位IXOFF与IXON实现run_erl.c。在嵌入式系统中与 start、start_erl、to_erl 协同run_erl并非孤立工作它处于嵌入式 OTP 系统启动链路的中间环节。整个启动流程为详见 embedded.md机器启动时调用start程序start调用run_erl搭建操作员可接入的环境run_erl执行start_erl后者依据start_erl.data中的版本信息调用对应 ERTS 版本目录下的erlexec并附上正确的-boot与-config文件最终启动 Erlang 模拟器。嵌入式指南中给出的start脚本默认行为如下#!/bin/sh # Usage: start [DataFile] # ROOTDIR/usr/local/otp if [ -z $RELDIR ] then RELDIR$ROOTDIR/releases fi START_ERL_DATA${1:-$RELDIR/start_erl.data} $ROOTDIR/bin/run_erl /tmp/ $ROOTDIR/log exec $ROOTDIR/bin/start_erl \ $ROOTDIR $RELDIR $START_ERL_DATA /dev/null 21 若要为节点命名并启用 heart 看门狗可改造为#!/bin/sh # Usage: start [DataFile] # HEART_COMMAND/usr/sbin/reboot TERMdumb export HEART_COMMAND TERM ROOTDIR/usr/local/otp if [ -z $RELDIR ] then RELDIR$ROOTDIR/releases fi START_ERL_DATA${1:-$RELDIR/start_erl.data} $ROOTDIR/bin/run_erl /tmp/ $ROOTDIR/log exec $ROOTDIR/bin/start_erl \ $ROOTDIR $RELDIR $START_ERL_DATA -heart -sname cp1 /dev/null 21 接入控制台to_erl当run_erl将模拟器启动为后台进程后操作员通过to_erl接入Usage: to_erl [pipe_name | pipe_dir]pipe_name默认为/tmp/erlang.pipe.N接入后即连接到 Erlang shell可执行普通 Erlang 命令且所有交互都会被记录到日志目录断开连接但不退出 Erlang 系统键入Ctrl-D即可Ctrl-S是流控暂停使用RUN_ERL_DISABLE_FLOWCNTRL可消除其误触风险。实践建议与注意事项始终使用-daemon否则需要复杂的 shell 技巧才能实现完全脱离终端的后台运行且必须以第一个参数位置传入。pipe_dir末尾斜杠不可省略/tmp/epipes/与/tmp/epipes会被区别对待to_erl默认查找/tmp/下的管道路径不一致将导致无法连接。日志目录与权限run_erl自身的状态日志写为run_erl.log权限为0600业务日志erlang.log.N权限为0664源码宏PERM与LOG_PERM见 run_erl.c。生产环境应确保运行用户对日志目录有写权限。轮转参数按需调优默认 5 代 × 100 KB 的容量上限约 500 KB长时间运行的系统应根据输出量调大RUN_ERL_LOG_GENERATIONS与RUN_ERL_LOG_MAXSIZE。时间统一跨时区运维时可启用RUN_ERL_LOG_ALIVE_IN_UTC并同步将 SASL 的utc_log设为true保证日志时间基准一致。流控风险若担心操作员误按Ctrl-S导致整机阻塞尤其在 heart 监督场景应定义RUN_ERL_DISABLE_FLOWCNTRL。参见start(1) 与 start_erl(1)嵌入式启动链路中的上下游命令手册Embedded System Users Guide嵌入式 OTP 系统的完整部署指南含自动开机启动脚本、磁盘无盘客户端等扩展主题实现源码run_erl.c、to_erl.c、run_erl.h 以及真实启动脚本 start.src。赞分享编程语言语言运行时标准库编译器并发编程【免费下载链接】otpErlang/OTP项目地址https://gitcode.com/gh_mirrors/ot/otp点击查看免费下载相关推荐Erlang/OTP 中的 werlWindows 平台 Erlang 模拟器命令行指南Erlang/OTP 中的 werlWindows 平台 Erlang 模拟器命令行指南 werl 是 Erlang/OTP 在 Windows 平台上用于交编程语言语言运行时标准库编译器并发编程Erlang/OTP epmd 端口映射守护进程完全指南命令行选项、协议原理与集群配置Erlang/OTP epmd 端口映射守护进程完全指南命令行选项、协议原理与集群配置 epmd Erlang Port Mapper DaemonErl编程语言语言运行时标准库编译器并发编程Erlang/OTP erl_call 命令完全指南从 Shell 脚本远程调用与启动分布式 Erlang 节点Erlang/OTP erl_call 命令完全指南从 Shell 脚本远程调用与启动分布式 Erlang 节点 erl_call 是 Erlang/OTP编程语言语言运行时标准库编译器并发编程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表