IEx 与 REPL 实战
不要只把 REPL 当计算器:用 IEx 读代码、查进程、调试监督树和验证数据库查询。
iex -S mix 进入项目,检查模块、调用函数、观察进程,安全地验证一个修改,而不是每次都先写脚本或重启服务。一、启动方式
# 普通 Elixir REPL
iex
# 加载 Mix 项目、依赖和应用代码
iex -S mix
# 指定环境
MIX_ENV=test iex -S mix
# 启动项目但不自动启动应用
iex -S mix run --no-start
iex -S mix 会编译项目并加载依赖。是否启动应用取决于 Mix 和 Application 配置;连接真实数据库或外部服务前,先确认当前环境。
二、最常用的探索命令
h Enum.map/2 # 查看帮助
h Pipeline.Llm # 查看模块文档
i value # 查看值的类型和大小
v() # 查看上一条结果
v(2) # 查看历史第 2 条结果
c "tmp/demo.ex" # 编译文件
r Pipeline.Dag # 重新编译模块
exports Pipeline.Dag # 列出导出函数
flush() # 取出当前进程邮箱里的消息
h用来读文档,i用来确认数据形状。v()可以避免重复执行有副作用的调用。r Module适合开发环境;生产环境不要随意热编译模块。
三、用 IEx 检查真实数据
iex> text = "a\nb\n"
iex> String.split(text, "\n", trim: true)
["a", "b"]
iex> Pipeline.Dag.nodes()
[%{id: "news_pull", upstream: []}, ...]
iex> Pipeline.Repo.all(from e in Pipeline.PipelineExecution,
...> order_by: [desc: e.id], limit: 3)
[%Pipeline.PipelineExecution{}, ...]
复杂表达式建议拆成多个绑定,先看中间结果,再继续管道。这样比把十步逻辑写成一行更容易定位数据在哪一步变形。
四、观察 BEAM 进程
Process.list() |> length()
Process.whereis(Pipeline.Repo)
Process.info(Process.whereis(Pipeline.Repo), [:status, :memory, :message_queue_len])
:observer.start() # 图形化观察器
:erlang.system_info(:schedulers_online)
Process.registered()
重点关注 :message_queue_len。邮箱持续增长通常意味着消费者处理太慢、消息格式不匹配,或者某个进程已经无法及时处理消息。
五、IEx 中的调试边界
# 纯函数可以直接验证
Pipeline.FeishuParser.parse("...")
# 查看异常,但不要吞掉根因
try do
risky_call()
rescue
error -> IO.inspect(error, label: "error")
end
# 追踪一个进程收到的消息
:sys.trace(pid, true)
:sys.trace(pid, false)
:sys.trace/2 只适合短时间、开发或受控诊断。生产环境优先使用 Logger、Telemetry 和监控,不要把所有消息长期打印出来。
六、用 IEx 验证配置与模块
Application.get_env(:pipeline, :start_oban)
Application.get_env(:pipeline, :llm)
Application.fetch_env!(:pipeline, :schema_prefix)
Code.ensure_loaded?(Pipeline.Jobs.NewsDigest)
function_exported?(Pipeline.Jobs.NewsDigest, :perform, 1)
Application.started_applications()
配置问题经常不是代码逻辑错误,而是环境变量、编译期配置和运行时配置混在一起。先在 IEx 里确认实际值,再决定改哪一个配置文件。
七、数据库查询的安全练习
import Ecto.Query
query = from e in Pipeline.PipelineExecution,
where: e.status == ^"done",
order_by: [desc: e.id],
limit: 5
Pipeline.Repo.all(query)
Pipeline.Repo.to_sql(:all, query)
先用只读查询验证条件,再执行写操作。不要在生产 IEx 里直接复制未经检查的 delete_all 或裸 SQL。
八、把临时探索变成可复现代码
IEx 适合探索,不适合保存关键业务逻辑。验证出正确行为后,应把它变成:
- 纯函数测试或 ExUnit 回归测试。
- 可审查的 Mix Task。
- 明确的 migration 或维护脚本。
- 带日志、权限和幂等控制的后台 Job。
九、测验
加载 Mix 项目并进入 REPL 的命令是?
IEx 中查看模块或函数帮助使用?
i value 主要用于?
IEx 中查看上一条表达式结果使用?
Process.whereis(Pipeline.Repo) 返回什么?
进程的 message_queue_len 持续增长通常说明?
Pipeline.Repo.to_sql(:all, query) 的用途是?
生产环境长期追踪所有 GenServer 消息的做法?
IEx 探索出正确行为后,最好的下一步是?
MIX_ENV=test iex -S mix 的作用是?
**下一步:**用 IEx 验证一个真实查询,再把它写成 ExUnit 测试,形成可复现反馈回路。