强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Erlang/OTP 完全指南 / 02 - 环境搭建

第 02 章:环境搭建

工欲善其事,必先利其器。本章介绍 Erlang/OTP、rebar3 构建工具及 IDE 的安装与配置。


2.1 安装 Erlang/OTP

2.1.1 各平台安装方式总览

平台 推荐方式 命令
Ubuntu/Debian apt apt install erlang
CentOS/RHEL yum / dnf dnf install erlang
macOS Homebrew brew install erlang
Windows 官方安装包 下载 .exe 安装
通用 asdf 版本管理 asdf install erlang 27.0
通用 kerl 源码编译安装

2.1.2 Ubuntu / Debian

# 方式一:系统包(版本可能较旧)
sudo apt update
sudo apt install erlang

# 方式二:Erlang Solutions 官方仓库(推荐)
wget https://binaries2.erlang-solutions.com/ubuntu/pool/contrib/e/esl-erlang/esl-erlang_27.0-1~ubuntu~jammy_amd64.deb
sudo dpkg -i esl-erlang_27.0-1~ubuntu~jammy_amd64.deb

# 验证安装
erl -version
erl -eval 'erlang:display(erlang:system_info(otp_release)), halt().' -noshell

2.1.3 macOS (Homebrew)

# 安装
brew install erlang

# 安装特定版本(使用 kerl 或 asdf)
brew install kerl

# 验证
erl -version
which erl

2.1.4 Windows

  1. 访问 Erlang 官网下载页
  2. 下载 Windows 64-bit 安装包(OTP_win64_27.0.exe)
  3. 运行安装程序,按默认选项安装
  4. C:\Program Files\erl-27.0\bin 添加到 PATH
# PowerShell 验证
erl -version

2.1.5 使用 asdf 版本管理(推荐)

asdf 可以管理多个 Erlang 版本,非常适合需要切换版本的场景:

# 安装 asdf(如果尚未安装)
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
echo '. "$HOME/.asdf/asdf.sh"' >> ~/.bashrc

# 添加 Erlang 插件
asdf plugin add erlang https://github.com/asdf-vm/asdf-erlang.git

# 查看可用版本
asdf list all erlang

# 安装指定版本
asdf install erlang 27.0
asdf global erlang 27.0

# 验证
erl -version

2.1.6 使用 kerl 源码编译

# 下载 kerl
curl -O https://raw.githubusercontent.com/kerl/kerl/master/kerl
chmod +x kerl
sudo mv kerl /usr/local/bin/

# 列出可用版本
kerl list releases

# 构建并安装
kerl build 27.0 27.0
kerl install 27.0 ~/erlang/27.0

# 激活
. ~/erlang/27.0/activate

# 验证
erl -version

💡 注意:源码编译需要先安装依赖:

# Ubuntu/Debian
sudo apt install build-essential autoconf libncurses5-dev \
    libssl-dev flex libwxgtk3.0-gtk3-dev libgl1-mesa-dev \
    libglu1-mesa-dev libpng-dev

# CentOS/RHEL
sudo dnf install gcc make autoconf ncurses-devel openssl-devel \
    flex wxGTK3-devel mesa-libGL-devel mesa-libGLU-devel libpng-devel

2.2 安装 rebar3

rebar3 是 Erlang 生态中最主流的构建工具(类似 Java 的 Maven、Node.js 的 npm)。

2.2.1 安装方式

# 方式一:官方脚本(推荐)
wget https://s3.amazonaws.com/rebar3/rebar3
chmod +x rebar3
sudo mv rebar3 /usr/local/bin/

# 方式二:从源码构建
git clone https://github.com/erlang/rebar3.git
cd rebar3
./bootstrap
sudo cp rebar3 /usr/local/bin/

# 方式三:Homebrew (macOS)
brew install rebar3

# 验证
rebar3 version

2.2.2 rebar3 核心命令

命令 作用
rebar3 new app <name> 创建新的 OTP 应用
rebar3 new lib <name> 创建纯库项目
rebar3 new release <name> 创建带 release 的项目
rebar3 compile 编译项目
rebar3 eunit 运行 EUnit 测试
rebar3 ct 运行 Common Test
rebar3 dialyzer 静态类型分析
rebar3 shell 启动交互式 Shell(含依赖)
rebar3 release 构建发布包
rebar3 tar 打包发布包
rebar3 hex publish 发布到 Hex.pm
rebar3 deps 获取依赖

2.2.3 创建第一个项目

# 创建 OTP 应用
rebar3 new app myapp
cd myapp

# 查看项目结构
tree .
# myapp
# ├── README.md
# ├── rebar.config
# ├── src
# │   ├── myapp.app.src
# │   ├── myapp_app.erl
# │   └── myapp_sup.erl
# └── test
#     └── (测试文件)

# 编译
rebar3 compile

# 运行
rebar3 shell

2.2.4 rebar.config 配置示例

%% rebar.config

{erl_opts, [
    debug_info,           %% 包含调试信息
    warnings_as_errors,   %% 警告视为错误
    {parse_transform, lager_transform}  %% lager 日志转换
]}.

{deps, [
    {cowboy, "2.12.0"},             %% HTTP 服务器
    {jsx, "3.1.0"},                 %% JSON 库
    {gun, "2.1.0"},                 %% HTTP 客户端
    {jiffy, "1.1.1"}                %% JSON (NIF 实现)
]}.

{relx, [
    {release, {myapp, "0.1.0"}, [myapp, sasl]},
    {dev_mode, true},
    {include_erts, false},
    {sys_config, "config/sys.config"},
    {vm_args, "config/vm.args"}
]}.

{profiles, [
    {prod, [
        {relx, [
            {dev_mode, false},
            {include_erts, true}
        ]}
    ]},
    {test, [
        {deps, [
            {meck, "0.9.2"},
            {proper, "1.4.0"}
        ]}
    ]}
]}.

{dialyzer, [
    {warnings, [
        error_handling,
        underspecs,
        unmatched_returns
    ]},
    {plt_extra_apps, [mnesia]}
]}.

2.3 IDE 与编辑器配置

2.3.1 编辑器对比

编辑器/IDE Erlang 支持 推荐度 特点
VS Code 插件支持 ⭐⭐⭐⭐⭐ 最流行,erlang-ls 集成
IntelliJ IDEA Erlang 插件 ⭐⭐⭐⭐ 重构能力强
Vim/Neovim erlang-ls ⭐⭐⭐⭐ 高效,需配置
Emacs erlang-mode ⭐⭐⭐⭐ 原生支持好
Sublime Text 插件 ⭐⭐⭐ 轻量

2.3.2 VS Code 配置(推荐)

安装步骤:

  1. 安装 VS Code
  2. 安装 erlang-ls 扩展(Erlang Language Server)
  3. 可选:安装 Erlang/OTP 语法高亮扩展
// .vscode/settings.json
{
    "erlang.erlangPath": "/usr/local/bin",
    "erlang.rebar3Path": "/usr/local/bin/rebar3",
    "erlang.linting": true,
    "editor.tabSize": 4,
    "editor.insertSpaces": false,
    "files.associations": {
        "*.erl": "erlang",
        "*.hrl": "erlang",
        "*.app.src": "erlang"
    }
}

erlang-ls 安装:

# 安装 erlang-ls(语言服务器)
git clone https://github.com/erlang-ls/erlang_ls.git
cd erlang_ls
rebar3 compile
rebar3 escriptize
cp _build/default/bin/erlang_ls /usr/local/bin/

# 或者使用 Erlang LS 预编译版本
# 从 GitHub Releases 下载

工作区配置(erlang_ls.config):

# erlang_ls.config(放在项目根目录)
apps_dirs:
  - "lib/*"
deps_dirs:
  - "_build/default/lib/*"
  - "_checkouts/*"
include_dirs:
  - "include"
  - "_build/default/lib/*/include"
diagnostics:
  - dialyzer
  - elvis
  - compiler

2.3.3 Vim / Neovim 配置

使用 nvim-lspconfig + erlang_ls

-- init.lua (Neovim)
require('lspconfig').erlang_ls.setup{
    cmd = { "erlang_ls" },
    filetypes = { "erlang" },
    root_dir = require('lspconfig').util.root_pattern("rebar.config", ".git"),
    settings = {
        erlang_ls = {
            dialyzerEnabled = true,
            elvisEnabled = true
        }
    }
}

2.3.4 Emacs 配置

;; .emacs 或 init.el
;; Erlang 官方模式(通常随 Erlang 安装)
(setq load-path (cons "/usr/local/lib/erlang/lib/tools-3.5/emacs" load-path))
(require 'erlang-start)

;; 自动加载
(add-to-list 'auto-mode-alist '("\\.erl\\'" . erlang-mode))
(add-to-list 'auto-mode-alist '("\\.hrl\\'" . erlang-mode))

;; 缩进设置
(setq erlang-indent-level 4)

;; Erlang LS 集成
(require 'lsp-mode)
(add-hook 'erlang-mode-hook #'lsp)

2.4 Erlang Shell (REPL)

2.4.1 基础使用

%% 启动 Shell
$ erl
Erlang/OTP 27 [erts-14.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1]

Eshell V14.0  (abort with ^G)
1> 1 + 1.
2
2> "Hello, Erlang!".
"Hello, Erlang!"
3> halt().

2.4.2 Shell 常用快捷键

快捷键 功能
Ctrl+C 中断当前操作 / 进入 BREAK 菜单
Ctrl+G JCL 模式(切换 Shell)
Ctrl+D 退出 Shell
Tab 自动补全
Up/Down 历史命令
Ctrl+A 行首
Ctrl+E 行尾

2.4.3 Shell 特殊命令

%% 查看历史
1> h().

%% 使用历史结果
2> 1 + 1.
2
3> v(2).     %% 引用第 2 行的结果
2

%% 编译并加载模块
4> c(my_module).

%% 查看模块导出函数
5> m(io).

%% 查看进程信息
6> i().

%% 退出
7> q().

2.4.4 Shell 限制

⚠️ 注意:Shell 中有些语法与源文件不同

%% Shell 中定义函数需要这样写:
1> Double = fun(X) -> X * 2 end.
#Fun<erl_eval.44.123456789>
2> Double(5).
10

%% Shell 中不能直接使用 -module, -export 等属性
%% 这些只能在 .erl 源文件中使用

2.5 项目结构详解

2.5.1 标准 OTP 项目结构

myapp/
├── rebar.config              # 构建配置
├── config/
│   ├── sys.config            # 应用配置
│   └── vm.args               # VM 启动参数
├── src/
│   ├── myapp.app.src         # 应用描述文件
│   ├── myapp_app.erl         # Application 回调模块
│   ├── myapp_sup.erl         # Supervisor 模块
│   └── myapp_server.erl      # 业务模块
├── include/
│   └── myapp.hrl             # 头文件
├── test/
│   ├── myapp_SUITE.erl       # Common Test
│   └── myapp_server_tests.erl # EUnit 测试
├── priv/
│   └── static/               # 静态资源
└── _build/                   # 构建输出(自动生成)
    ├── default/
    │   └── lib/
    └── default/
        └── rel/

2.5.2 应用描述文件

%% src/myapp.app.src
{application, myapp, [
    {description, "My Erlang Application"},
    {vsn, "0.1.0"},
    {registered, [myapp_server]},
    {mod, {myapp_app, []}},     %% 启动模块
    {applications, [
        kernel,
        stdlib,
        cowboy    %% 依赖
    ]},
    {env, [
        {port, 8080},           %% 配置项
        {pool_size, 10}
    ]},
    {modules, []},              %% rebar3 自动填充
    {licenses, ["Apache-2.0"]},
    {links, []}
]}.

2.5.3 VM 启动参数

%% config/vm.args
## 节点名称
-name myapp@127.0.0.1

## Cookie(集群认证)
-setcookie myapp_cookie

## 调度器数量(默认等于 CPU 核心数)
## +S 8:8 表示 8  CPU 调度器 + 8  IO 调度器

## 最大进程数
+P 1048576

## 最大 ETS 表数量
+e 65536

## 异步线程池大小
+A 128

## 垃圾回收参数
+MBas aobf
+MBacul 0

2.6 Dialyzer 配置

Dialyzer 是 Erlang 的静态类型分析工具,可以在编译期发现类型错误。

2.6.1 类型规范(Type Spec)

-module(math_utils).
-export([add/2, divide/2]).

%% 类型规范:接受两个 integer,返回 integer
-spec add(integer(), integer()) -> integer().
add(A, B) ->
    A + B.

%% 可能返回错误的情况
-spec divide(number(), number()) -> {ok, float()} | {error, string()}.
divide(_A, 0) ->
    {error, "division by zero"};
divide(A, B) ->
    {ok, A / B}.

2.6.2 运行 Dialyzer

# 构建 PLT(持久查找表,首次运行较慢)
rebar3 dialyzer

# 或手动构建 PLT
dialyzer --build_plt --apps erts kernel stdlib crypto

# 分析单个文件
dialyzer my_module.erl

# 分析项目
dialyzer _build/default/lib/myapp/ebin/

2.7 Observer 可视化工具

Observer 是 Erlang 内置的图形化监控工具:

%% 在 Shell 中启动
1> observer:start().

%% 或从菜单启动
%% 应用程序 → observer

Observer 提供:

  • System:系统概览(CPU、内存、进程数)
  • Processes:进程列表和详情
  • Ports:端口信息
  • ETS:ETS 表浏览器
  • Applications:应用监控树
  • Graphs:实时性能图表

2.8 注意事项

⚠️ 版本兼容性

问题 说明
OTP 版本 不同版本之间 API 可能有变化,注意文档版本
rebar3 版本 保持 rebar3 更新到最新稳定版
系统包版本 apt/yum 的 Erlang 版本通常较旧,建议用 asdf/kerl
NIF 兼容 使用 NIF 时注意 OTP 版本匹配

💡 最佳实践

  1. 使用 asdfkerl 管理 Erlang 版本,避免系统包
  2. 每个项目固定 Erlang 版本(.tool-versions 文件)
  3. 新项目优先使用 rebar3 new release 模板
  4. 安装完后立即运行 rebar3 dialyzer 建立 PLT
# .tool-versions(asdf 版本固定文件)
erlang 27.0

2.9 扩展阅读


上一章:01 - Erlang 简介 下一章:03 - Hello World