☰
CentOS 7.9 源码编译安装 FreeSWITCH 全流程与避坑指南
2026/10/10 6:49:00 网站建设 项目流程

最近在一台 CentOS 7.9 的旧服务器上重新部署 FreeSWITCH,从拉源码到编译再到服务化,又实打实走了一遍全流程。网上讲 CentOS 7.9 安装 FreeSWITCH 的教程不算少,但很多直接给个 RPM 仓库地址,或者默认你已经有一台配置很好的新机器,真正能照着跑完、不中途踩坑的反而少。这篇就把我在 centos7.9 上安装 freeswitch 的完整经过写清楚,适合要在存量机房或公司内网里自建软交换、呼叫中心实验环境、SIP 接入层的人,也适合刚接触 VoIP 想跑一套真实系统练手的同学。我会从系统初始化、依赖安装、源码编译讲到 systemd 托管、防火墙放行,最后附上我实际遇到的编译坑和运行期隐患。

1. 为什么 CentOS 7.9 + FreeSWITCH 的组合仍然值得认真对待

1.1 存量机器的真实生态

说实话,CentOS 7 的生命周期已经进入末期,生产环境里它的占比在下降,但很多通信机房、政企内网、IDC 托管设备里,依旧跑着一大批 CentOS 7 系列系统。我见过不少客户机房的语音网关、SIP 线路对接机,都还是 CentOS 7.9 的最低环境,上面跑着 FreeSWITCH 或者老版本 Asterisk,业务稳定不出事,谁也不想轻易动系统。另外很多内网环境出于合规考虑,不允许随意换操作系统,这种情况下 CentOS 7.9 就是现实选项。

还有一个客观原因:FreeSWITCH 对系统没有特别激进的要求,CentOS 7 的 glibc、openssl、内核版本完全能满足 1.10.x 的编译和运行。只要不开一些非常新、依赖过高版本系统库的功能,在 CentOS 7.9 上跑 FreeSWITCH 完全可以做到稳定。我并不建议你在生产上为了“追新”而把一个运行了多年的 CentOS 7.9 直接升级到大版本,反而更推荐在新版本系统上新建一套环境做灰度验证。可现实里,存量服务器上能把 FreeSWITCH 顺利装起来,仍然是很多同学要面对的第一步。

1.2 版本选型:为什么我挑 1.10.x

如果你去翻 GitHub,会看到 FreeSWITCH 有多个分支,老的 1.6、1.8 已经停止维护,1.10 是目前还在持续维护的稳定分支。以我这次在 CentOS 7.9 上部署的经验来说,1.10 对新的编解码库、TLS 支持、WebRTC 相关模块都要友好得多。1.8 年代编译时常常会遇到 openssl 版本太新导致头文件不兼容的问题,1.10 在这块已经收敛了很多。

我这次直接用 v1.10 分支,没有去碰 master 上的新特性代码。原因很简单:通信系统要的是稳,不是天天追新功能。master 分支可能有一些还处于开发中的功能,模块依赖变化也快,不是短时间能摸透的。对于大多数业务场景,1.10 分支上的稳定版本足够支撑 SIP 注册、呼叫路由、媒体转发、录音、TTS/ASR 对接等常规需求。如果你是为了学习,那也建议先把 1.10 分支跑熟,再看新分支的新特性,这样遇到问题时你能更好地区分是配置问题还是代码问题。

2. 编译前按我的顺序装依赖,没那么多幺蛾子

2.1 先决定一件事:源码编译还是 RPM 安装

FreeSWITCH 官方文档里提供了 SignalWire 维护的 RPM 仓库方式,理论上yum install freeswitch一行就能搞定。但我在 CentOS 7.9 上踩过一次坑:官方 RPM 仓库对 CentOS 7 的支持已经不像前几年那么积极,经常遇到依赖库版本不对、GPG 密钥过期、仓库里软件包版本落后的问题。而且 RPM 方式安装出来的目录结构、模块组合不是你完全可控的,出了问题想排查就得先搞清楚它把配置放在了哪里。

所以我坚持源码编译。花点时间,但换来的好处很实在:安装目录固定,模块你可以自由裁剪,编译参数可以自己控制,升级时也能通过 git 切 tag 来精确管理版本。编译一次大约需要几十分钟,这时间相比后面生产运行一年的稳定期来说,完全值得。

2.2 最小化系统环境与软件包安装命令

如果你的 CentOS 7.9 还没有装好,建议选择最小化安装模式,镜像去国内常见镜像站下载就行,版本串注意选 7.9.2009。最小化安装能减少很多不必要的系统服务干扰,后面跑 FreeSWITCH 也更干净。

装完系统第一件事,把基础工具和 YUM 源准备好:

# 更新现有软件包 yum update -y # 启用 EPEL 源,后面很多依赖包都靠它 yum install -y epel-release # 编译工具链 yum install -y gcc gcc-c++ make automake autoconf libtool

然后是 FreeSWITCH 编译需要的具体开发库,这些缺一个,后面 configure 阶段或 make 阶段就会报一个错,让你来回折腾:

yum install -y libuuid-devel zlib-devel openssl-devel \ libjpeg-turbo-devel sqlite-devel libcurl-devel pcre-devel \ speex-devel ldns-devel libedit-devel libxml2-devel yasm \ nasm wget git

如果后面要启用特定模块,比如 WebRTC 或录音格式转换,还会用到这些:

yum install -y opus-devel libvpx-devel libsndfile-devel \ lua-devel ncurses-devel

libedit-devel是 fs_cli 命令行工具需要的依赖,如果没有它,装完你连控制台都用不起来。sqlite-devel对应 FreeSWITCH 内部数据库支持,很多注册信息、通话记录都存在 SQLite 里,这个库不能少。speex、opus这类是编码库,虽然运行时也可以动态加载,但编译期就带上会更省事。

提示:如果某些包在默认源里提示找不到,多半是因为没有装 EPEL,或者 EPEL 源拉取失败。先确认/etc/yum.repos.d/epel.repo存在并且能访问,再重新执行安装。

3. 源码编译全流程:configure、make、install 的分段处理

3.1 拉取源码和分支选择

最稳妥的源码获取方式是直接克隆官方仓库的 v1.10 分支:

mkdir -p /usr/local/src cd /usr/local/src git clone -b v1.10 https://github.com/signalwire/freeswitch.git freeswitch

如果你在拉取 GitHub 时速度长时间卡住,也可以找国内开源镜像站上的 FreeSWITCH 镜像仓库,效果一样。拉取完成后先看一下源码目录里有没有configure文件,如果没有,需要先执行./bootstrap.sh或者build/bootstrap.sh来生成 configure 脚本。1.10 分支下通常 bootstrap 脚本会自动完成 autoreconf。

cd /usr/local/src/freeswitch ./bootstrap.sh

这一步会跑一段时间,主要是生成 configure、Makefile 等构建文件。看到提示成功后再继续。

3.2 configure 阶段:依赖检查与常见失败

默认安装路径是/usr/local/freeswitch,这个路径我觉得清晰好记,所有二进制、配置、日志都集中在一个目录下,后面做备份迁移都方便。执行:

cd /usr/local/src/freeswitch ./configure --prefix=/usr/local/freeswitch

configure 脚本会检查上一节里安装的各类库和头文件。如果缺依赖,它会明确告诉你缺什么,比如提示缺少某个 lib。这时候不要急着瞎装,先看报错信息里的关键关键字,很多时候是某个*-devel包没装。我自己遇到过缺libedit和uuid头文件的情况,执行完 2.2 的命令后就没再出现问题。

一个实用技巧:源码目录下有个modules.conf文件,里面按行列出了所有要编译的模块。如果你机器资源有限,或者明确知道用不到某些模块,就把它们注释掉。比如不打算做 TTS/ASR 对接的,可以注释掉相关 module;不需要某些小众协议支持的,也先关掉。这样能显著缩短编译时间,也减少后续运行时的维护面。

3.3 make 阶段:并行度、OOM 与模块裁剪

依赖都通过后,接下来是编译。我建议不要一上来就make -j$(nproc),尤其当你的服务器只有 2GB 或者 4GB 内存的时候。FreeSWITCH 编译过程中会同时跑很多编译任务,并行度太高容易把内存直接吃满,最终表现为 make 进程无端消失,系统出现“Killed”,实际上是内存不足被系统干掉了。

我的经验是 4GB 内存机器用make -j2或make -j4,2GB 内存机器老老实实make -j1。虽然耗时会长一些,但至少不会反复中断。执行:

cd /usr/local/src/freeswitch make -j4

如果编译过程中某个模块失败,不要整个重来。看一下终端上失败的模块名称,然后回到modules.conf把对应的模块注释掉,重新执行./configure && make -j4。FreeSWITCH 的 make 是增量式的,已经编译过的不会重来,所以你不用太担心时间浪费。

3.4 make install 与语音包

编译完成后安装:

make install

这一步会把二进制、默认配置、脚本拷贝到/usr/local/freeswitch下。装完后建议安装内置语音包和音乐包,不然拨测时没有提示音可用:

make cd-sounds-install cd-moh-install

这步会从官方源下载声音文件,如果因为网络原因下载失败,不会影响主程序运行,可以等网络好的时候重新执行一次。声音文件会放到/usr/local/freeswitch/sounds和/usr/local/freeswitch/moh目录下。下载的是默认的 en-us-callie 语音包,基本够测试用了。

安装完成看一下目录结构:

ls /usr/local/freeswitch/ ls /usr/local/freeswitch/bin/

正常情况下能看到freeswitch、fs_cli这两个核心可执行文件,conf、db、log、recordings、sounds等目录也都会存在。

4. 装完不等于能用:服务化、SELinux 与端口放行

4.1 创建服务用户和目录权限

用 root 跑 FreeSWITCH 不是不行,但风险太高。万一某个接口被攻击,整个系统权限都丢了。我自己部署一定创建一个专用用户:

useradd --system --home-dir /usr/local/freeswitch --shell /sbin/nologin freeswitch chown -R freeswitch:freeswitch /usr/local/freeswitch chmod -R 750 /usr/local/freeswitch

这个用户不能登录系统,只用来跑 FreeSWITCH 进程,所有配置、日志、数据库都归它管。后续你会发现,很多启动失败的问题其实都是目录权限不对,提前把权限设好能少踩一堆坑。

4.2 一份开箱即用的 systemd unit

CentOS 7 使用 systemd 管理服务,我选择手动写一个 unit 文件而不是用官方自带的启动脚本。原因是官方脚本在一些环境下对环境变量处理得不理想,而自定义 unit 非常简单直接:

[Unit] Description=FreeSWITCH After=network.target [Service] User=freeswitch Group=freeswitch WorkingDirectory=/usr/local/freeswitch ExecStart=/usr/local/freeswitch/bin/freeswitch -nc -nf ExecReload=/usr/local/freeswitch/bin/fs_cli -x "reloadxml" Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target

把上述内容保存到/etc/systemd/system/freeswitch.service,然后:

systemctl daemon-reload systemctl enable freeswitch systemctl start freeswitch

这里需要注意-nc表示不进入控制台模式,-nf表示不 fork 到后台,systemd 要求服务进程在前台运行,这两个参数配合正合适。LimitNOFILE设置大一点是为了防止高并发下文件描述符不够用,这个值在通信软件里很重要。

如果修改过 event socket 密码,ExecReload里的fs_cli -x命令也要对应加上-p 新密码,不然重载会失败。这个细节很容易忽略。

4.3 SELinux 与 firewalld 放行

CentOS 7 默认是 SELinux enforcing 状态,对自定义编译的软件影响特别大。FreeSWITCH 启动后会有很多动态库加载、端口绑定、文件读写动作,都可能被 SELinux 拦截。如果启动失败,先看日志再查 SELinux:

grep freeswitch /var/log/audit/audit.log | tail -20

如果你确认这台机器就是专用通信服务器,可以临时把 SELinux 设为 permissive 来排查:

setenforce 0

如果验证下来就是 SELinux 导致的,生产环境请按公司安全基线处理,要么正确配置策略放行,要么在必要且允许的前提下调整 SELinux 模式。硬顶着 SELinux 跑不是不行,但你会不断遇到莫名其妙的权限问题。

防火墙也一样,CentOS 7 的 firewalld 默认不让你出 SIP 端口。需要放行以下端口:

firewall-cmd --permanent --add-port=5060/udp firewall-cmd --permanent --add-port=5080/udp firewall-cmd --permanent --add-port=5060/tcp firewall-cmd --permanent --add-port=5080/tcp firewall-cmd --permanent --add-port=16384-32768/udp firewall-cmd --reload

5060 是 internal profile 默认监听的 SIP 端口,5080 是 external profile 的端口,16384-32768 是 RTP 媒体流端口范围。很多人只放行了 5060,结果分机注册上了但电话打不通,一查才发现 RTP 端口没放,这种问题很难排查,提前放好最省心。

4.4 启动前必须改掉的默认配置

FreeSWITCH 安装后默认配置里有几个非常“危险”的默认值,如果你打算把它暴露到非可信网络,必须先改。最典型的是默认密码:

  • 分机密码默认是1234,定义在/usr/local/freeswitch/conf/vars.xml里的default_password
  • 管理接口 event socket 的默认密码是ClueCon,定义在/usr/local/freeswitch/conf/autoload_configs/event_socket.conf.xml

修改方式很简单,把 vars.xml 里对应的密码替换成强密码,然后把 event_socket 的密码也换掉。修改后执行:

/usr/local/freeswitch/bin/fs_cli -x "reloadxml" systemctl restart freeswitch

另外检查一下 external profile 里的公网 IP 配置,如果这台机器要对接外网 SIP 线路,把ext-sip-ip和ext-rtp-ip改成你的公网 IP,或者设置成auto-nat模式。默认的$${local_ip_v4}在 NAT 环境下会导致信令和媒体地址错误,这是一个非常隐蔽的问题。

5. 验证安装成果:推荐一套从命令行到真实呼叫的检查清单

5.1 进程、端口、模块三连查

装完别急着配业务,先用三条命令确认基础运行状态:

# 看版本 /usr/local/freeswitch/bin/freeswitch -version # 看运行状态 /usr/local/freeswitch/bin/fs_cli -x "status" # 看监听端口 ss -lntup | grep -E '5060|5080|8021'

fs_cli是 FreeSWITCH 自带的管理客户端,默认通过本地 8021 端口的 event socket 和主进程通信。如果执行fs_cli -x "status"提示 connection refused,先确认主进程有没有起来:

systemctl status freeswitch tail -f /usr/local/freeswitch/log/freeswitch.log

日志是排障的第一现场,日志目录/usr/local/freeswitch/log/下不仅有freeswitch.log,还有按天轮转的老日志。能看到Freeswitch version ... starting就说明主进程启动成功了。

再深入一点检查 SIP 模块加载情况:

/usr/local/freeswitch/bin/fs_cli -x "sofia status"

这个命令会列出 internal 和 external 两个 profile 的运行状态、监听地址。如果某个 profile 没起来,大概率是对应 XML 配置有问题,或者端口被别的程序占用。

5.2 用软电话完成首次真实呼叫

命令行终归是间接验证,最直观的成果是拿一个真实 SIP 电话终端注册上来,完成一次通话。我自己习惯用 MicroSIP 或者 Zoiper,都是免费的,配置也很简单:

  • 服务器地址填 CentOS 7.9 机器的 IP
  • 端口填 5060
  • 账号填默认分机号,比如 1000
  • 密码填修改后的分机密码

分机号 1000 到 1019 在默认配置里就已经存在,对应的文件在/usr/local/freeswitch/conf/directory/default/下。注册成功后,在 fs_cli 里执行:

/usr/local/freeswitch/bin/fs_cli originate user/1000 &echo

软电话会响铃,接听后你就能从耳机里听到自己的回声。这一步通过,说明从 SIP 注册到媒体协商、RTP 传输整条链路都通了。如果注册不上,先看 softphone 上有没有显示 SIP 403 或 404,403 多数是密码错误,404 多半是分机号不存在或者 dialplan 没加载。再不行就抓包看一下 SIP 信令。

提示:拨测时最好把软电话和 CentOS 7.9 放在同一个网段,或者确认两端 UDP 端口没有防火墙拦截,否则很容易出现“注册成功但通话没声音”的情况。

6. 实测中的编译坑与运行期隐患

6.1 编译链路踩坑实录

第一类坑是 configure 阶段报缺库。报错关键字通常是cannot find、no such file or directory、checking for ... not found。比如提示找不到uuid.h,那就是缺libuuid-devel;找不到ssl.h,就是缺openssl-devel。按第 2.2 节的命令列表装完后,绝大部分问题都能解决。如果提示缺一些不常用的库,我的做法是先看它是哪个模块要用,不重要的直接把 modules.conf 里对应模块注释掉,不折腾。

第二类坑是 make 阶段机器被“Killed”。这在我第一次部署时出现过,当时看到终端突然断掉,还以为代码有问题,后来查dmesg才发现是 OOM。小内存机器一定控制并行度,make -j1虽然慢但稳。编译期间最好别同时跑其他吃内存的服务,比如 MySQL、Redis。

第三类坑是编译某个模块失败,常见于 mod_vpx、mod_openh264 这类依赖外部代码库的模块。遇到这种情况,回到 modules.conf 注释掉它,再重新 configure、make。对于测试环境,音视频编码先依赖系统内置的 codec 就够了。

6.2 运行期的坑和排查建议

FreeSWITCH 编译成功后,运行期我也踩过几个印象深刻的坑。最烦的是启动后进程秒退,查日志发现是db目录无法写入,原因是用户权限没对。这不算稀奇,但每次换新机器都容易忘,所以我习惯装完立刻用ls -l /usr/local/freeswitch/检查目录 owner。

第二个是 IP 地址被 NAT 时导致注册失败或单通。FreeSWITCH 明确区分了 internal profile 和 external profile,内网注册用 internal,公网或跨网络通信要考虑 external 的 NAT 配置。如果你的系统放在内网后面带公网映射,记得在 external 配置里把外网地址写清楚,否则对端看到的 SIP Contact 是内网地址,回包根本到不了。

第三个是 fs_cli 连接不上的问题。如果fs_cli一直提示 connection refused,大概率是 event socket 没有监听,或者只监听了 127.0.0.1 而你从远程执行 fs_cli。默认 event socket 监听 127.0.0.1,这是安全设计,远程管理应该先 SSH 到服务器再执行,而不是把 8021 端口直接暴露出去。

6.3 升级替换:别忘了备份配置文件

最后说一个看似简单但经常出事的点:升级。FreeSWITCH 升级时,很多人直接make install覆盖旧版本,结果新版本启动后分机全部掉线、配置失效。原因往往是旧版本里你改过的配置文件被新版本默认配置覆盖了,或者数据库目录结构不兼容。

我的习惯是升级前完整备份这几个目录:

cp -a /usr/local/freeswitch/conf /backup/freeswitch-conf-YYYYMMDD cp -a /usr/local/freeswitch/db /backup/freeswitch-db-YYYYMMDD cp -a /usr/local/freeswitch/store /backup/freeswitch-store-YYYYMMDD

然后去源码目录切到新版本 tag,重新 configure、make、make install。装完先不急着启动,把备份的 conf 目录覆盖回去,重点对比一下freeswitch.xml和vars.xml有没有新增必填项。升级后先跑一轮注册和呼叫测试,再切真实业务流量。这样就算新版本有问题,也能随时把旧进程拉起来回滚,至少业务不会长时间中断。

编译安装 FreeSWITCH 这件事,说难其实也不难,最难的部分往往不是编译本身,而是你对系统环境和版本选择的把握。按这篇的顺序走下来,CentOS 7.9 上跑起来一套可用的 FreeSWITCH 基本不会出大问题。等到你把它稳定跑起来之后,再去折腾拨号计划、外呼线路、媒体转码这些高阶功能,心里就有底了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询