首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >分享 Kamailio 预处理指令使用经验

分享 Kamailio 预处理指令使用经验

作者头像
杜金房
发布2026-07-11 08:33:55
发布2026-07-11 08:33:55
60
举报

直接查阅官方手册往往令人困惑,不知如何正确使用 Kamailio 的预处理指令,这是正常现象。根据笔者的经验,多动手测试并积累实践案例是关键。

文件包含指令:include_file 与 import_file

include_file 会在解析配置前将指定文件内容嵌入当前位置。如果被引用的文件不存在,将会报错。

示例:

代码语言:javascript
复制
#!include_file "kamailio-local.cfg"
代码语言:javascript
复制
import_file 功能与 include_file 相同,但允许引用的文件不存在,不会因此报错。

一个典型的 kamailio.cfg 可以按以下方式组织:

代码语言:javascript
复制
#!include_file "defines.cfg"   # 宏定义(如 IP 地址、端口、DBURL 等)
#!import_file "aliases.cfg"    # 别名列表
#!include_file "modules.cfg"   # 加载模块及模块参数
#!include_file "request.cfg"   # 主路由逻辑
#!include_file "utils.cfg"     # 分支路由、应答路由等
代码语言:javascript
复制
条件加载与宏定义:define

define 采用类似 C 语言的风格,控制配置文件中哪些部分生效。未定义区域内的内容不会被加载。

  • 示例一:条件加载模块
代码语言:javascript
复制
#!define WITH_NAT
...
#!ifdef WITH_NAT
loadmodule "nathelper.so"
#!endif
代码语言:javascript
复制
示例二:定义并引用公共参数
代码语言:javascript
复制
#!define DBURL "postgres://kamailio:kamailiorw@127.0.0.1/kamailio"
...
loadmodule "permissions.so"
loadmodule "usrloc.so"
# DBURL 只需定义一次,即可多处引用
modparam("usrloc", "db_url", DBURL)
modparam("permissions", "db_url", DBURL)
代码语言:javascript
复制
启动 Kamailio 后,执行 kamcmd core.ppdefines_full 可以查看已定义的宏(输出经过简化):
代码语言:javascript
复制
{
    {
        name: DBURL
        value: "postgres://kamailio:kamailiorw@127.0.0.1/kamailio"
    },
    {
        name: KAMAILIO_6      # 版本标识
        value: none
    },
    {
        name: MOD_usrloc      # 已加载的模块
        value: none
    },
    {
        name: MOD_permissions # 已加载的模块
        value: none
    }
}

基于上述特性,可以编写如下配置以确保模块加载:

代码语言:javascript
复制
#!ifdef WITH_HTABLE
loadmodule "htable.so"
#!endif
...
# 无论 WITH_HTABLE 是否定义,下面配置都能保证 htable 模块被加载
#!ifndef MOD_htable
loadmodule "htable.so"
#!endif
代码语言:javascript
复制
字符串替换:subst 与 substdef

subst 用于在配置文件内部进行字符串替换。

语法:

  • #!subst "/正则表达式/替换内容/标志位"
  • #!subst "!正则表达式!替换内容!标志位"

标志位说明:

  • i:忽略大小写
  • g:全局替换

示例:

代码语言:javascript
复制
#!subst "!DBURL!postgres://kamailio:kamailiorw@127.0.0.1/kamailio!g"
modparam("usrloc", "db_url", "DBURL")
modparam("permissions", "db_url", "DBURL")
代码语言:javascript
复制
重要区别:
  • 使用 #!define DBURL "..." 时,引用方式为 modparam(..., DBURL)(不加引号)。
  • 使用 #!subst "!DBURL!...!g" 时,引用方式为 modparam(..., "DBURL")(需加引号)。

substdef 在功能上与 subst 一致,但会同时创建对应的宏定义(可通过 kamcmd core.ppdefines_full 验证),而 subst 仅进行替换,不创建宏。

  • 解决密码中含特殊字符的问题

使用 #!define DBURL "..." 时,若数据库密码包含 @ 等字符,会导致解析错误。此时可借助 substdef 分层定义:

代码语言:javascript
复制
#!substdef "!DB_USERNAME!kamailio!g"
#!substdef "!DB_PASSWORD!1234@XXXX!g"
#!substdef "!DB_HOST!127.0.0.1!g"
#!substdef "!DB_PORT!5432!g"
#!substdef "!DB_NAME!kamailio!g"

#!define DBURL "postgres://DB_USERNAME:DB_PASSWORD@DB_HOST:DB_PORT/DB_NAME"

modparam("usrloc", "db_url", DBURL)
modparam("permissions", "db_url", DBURL)
代码语言:javascript
复制
补充说明:
substdefs 与 substdef 功能相同,区别在于其宏值会自动包裹双引号,适用于需要字符串常量的场景。
代码语言:javascript
复制
使用环境变量:defenv

可将数据库用户名、密码等敏感信息存入环境变量,在配置中通过 defenv 引用。

  • 设置环境变量
代码语言:javascript
复制
export DB_USERNAME="kamailio"
export DB_PASSWORD="1234@XXXX"
export DB_HOST="127.0.0.1"
export DB_PORT="5432"
export DB_NAME="kamailio"
代码语言:javascript
复制
 Kamailio 配置方式一
代码语言:javascript
复制
#!defenv DB_USERNAME
#!defenv DB_PASSWORD
#!defenv DB_HOST
#!defenv DB_PORT
#!defenv DB_NAME

#!substdef "!DBURL!postgres://$def(DB_USERNAME):$def(DB_PASSWORD)@$def(DB_HOST):$def(DB_PORT)/$def(DB_NAME)!g"

modparam("usrloc", "db_url", "DBURL")
modparam("permissions", "db_url", "DBURL")
代码语言:javascript
复制
Kamailio 配置方式二(使用共享变量)
代码语言:javascript
复制
#!defenv DB_USERNAME
#!defenv DB_PASSWORD
#!defenv DB_HOST
#!defenv DB_PORT
#!defenv DB_NAME
modparamx("pv",
    "shvset",
    "dburl=postgres://$def(DB_USERNAME):$def(DB_PASSWORD)@$def(DB_HOST):$def(DB_PORT)/$def(DB_NAME)"
)
modparamx("usrloc", "db_url", "$shv(dburl)")
modparamx("permissions", "db_url", "$shv(dburl)")
代码语言:javascript
复制
通过合理组合这些预处理指令,可以使 Kamailio 配置文件更加模块化、可维护,并安全地管理敏感信息。

上面用的是 modparamx 而没有用 modparam,是因为前者支持对参数中的变量进行求值运算。

另外上面用到了 $def(DB_USERNAME),这是伪变量,马上就要发布(预计 2026-02-18)的 v6.1.0 支持下面的伪变量:

  • $def(name), 返回已定义的值
  • $defs(name), 返回已定义的字符串。如果已定义的值被单引号或双引号包裹,则原样返回该值。
  • $defn(name), 将已定义的值以有符号整数形式返回。
  • $defv(name), 返回去除引号的已定义值。对单引号和双引号均有效。如果已定义的值未被引号包裹,则原样返回该值。

下面是例子:

代码语言:javascript
复制
#!defenvs DB_USERNAME  # 有双引号
$var(s) = $defv(DB_USERNAME);  # 双引号已删除
代码语言:javascript
复制
下面是 LUA 代码:
代码语言:javascript
复制
local db_username = KSR.pv.get("$defv(DB_USERNAME)")
KSR.xinfo("db_username = " .. db_username .. "\n")
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-07-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FreeSWITCH中文社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 直接查阅官方手册往往令人困惑,不知如何正确使用 Kamailio 的预处理指令,这是正常现象。根据笔者的经验,多动手测试并积累实践案例是关键。
  • 文件包含指令:include_file 与 import_file
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档