asterisk 使用脚本——Dialplan 基础

引言:

Dialplan 是 Asterisk 的核心。它定义了一个呼叫怎么进入以及怎么离开 Asterisk 系统。

Dialplan 是一种脚本语言,它包含着 Asterisk 响应外部触发的各种指令。不同于传统电话系统,Asterisk 的 dialplan 是可以完全由用户修改的。

这句话重点关注的是Diaplan这个英文单词的含义是拨号,说白了一个人要与另外一个人通话一定要做的就是拨号,而拨号有各种各样的方式,比如说你要打110和你要打你爸爸的电话,所输入的号码是不一样的,但是你所输入的号码是怎么转发到对应的话机上的呢,这其实就是拨号脚本的作用。我们想让即使你输入110但是电话却打到你爸爸的手机上,也是可以的,这就多亏了拨号脚本的作用,用户可以直接修改这个脚本控制你电话的走向。

Diaplan语法

Asterisk 的 dialplan 定义在名为 extensions.conf 的配置文件中。
其实这个extensions.conf 顾名思义,其实就是一个分机配置文件。

extensions.conf 文件一般安装在 /etc/asterisk/directory 目录下,但是它的
位置也可能会变化,这取决于你是如何安装 Asterisk 的。这个文件的一些
其它常见安装目录还包括 /usr/local/etc/asterisk/ 和 /opt/etc/asterisk/
这段话其实不重要

Dialplan 由四个基本概念组成:上下文(contexts),分机(extensions),优先级(priorities),应用(applications)。在解释完上述每个要素的作用之后,我们会帮助你创建一个基本但可以工作的 dialplan。
这四个基本概念相当重要,后续会详细讨论,分机决定了你的通话终端,优先级决定了你的通话顺序,另外两者后面会讲述。

1.上下文(Contexts)

Dialplan 是由一个个称为 Contexts 的部分组成的。Context 保持了 dialplan 中不同部分作用的相互独立。在一个 Context 中定义的 extension 和在另外一个 Context 中定义的 extension是完全独立的,除非我们特别允许它们可以互相作用。(我们将在本章末讨论如何允许context 中的相互作用)

这里要清楚一点,Contexts是相互独立的,他们就像一台分机一样,简单理解分机就是一台电话,每一台电话之间是相互独立的。除非我们特别允许他相互作用,否则每个context之间是毫无关联的。

举一个简单的例子,让我们想像一下有两家公司共享一个 Asterisk 服务器的情况。如果我们把每个公司的应答流程放在它们各自的 Context 中,这两个公司就完全无关了。这就允许我们分别定义诸如按下“0”时会发生什么:当在 A 公司的语音菜单中按下 0 时,会转接给 A 公司的前台秘书;当在 B 公司的语音菜单中按下 0 时,会转接给 B 公司的前台秘书。(当然,这需要我们此前已经定义了按 0 会转给前台秘书注 1)。
嘿兄弟们,明白了吧,实际上每台context的流程就是不一样的,一个公司的拨号流程使用一种context。

Contexts 的定义通过在方括弧([])中定义一个名字来实现。这个名字可以包含字母 A到 Z,数字 0 到 9,以及连字符和下划线注 2。一个为来电定义的 context 看起来可能是这样的:Context 名字最长为 79 个字符(80 个字符,减去最后的 NULL 结束符)

这里我们必须要抓住重点,Contexts的定义通过在[]中定义一个名词来实现,记住这句话,记住这句话,记住这句话,重要的话我说三遍,Contexts的定义通过在[]中定义一个名词来实现。这个名字的范围也很重要,最长为79个字符,特别注意,最后还有一个NULL结束符。

所有跟在一个 context 定义之后的部分都是这个 context 的一部分,直到遇到下一个context 定义。(这句话很总要,两个context的距离是一个中括号,只要没有遇到中括号,无论字符有多长,中间的空格有多长,都是一个context。)

在 dialplan 的开头,有两个特殊的context 命名为 [general] 和 [globals]。[general]上下文包含一系列 dialplan 的一般配置(你可能永远不需要理会这些配置),我们会在“全局变量”一节讨论[globals]上下文。现在,只要记住[general]和[globals]不是一般的context 就可以了。请一定避免使用[general],[default],[globals]作为 context 名字,除此而外,你可以使用任何你喜欢的名字。
这里就记住,[general],[default],[globals]三种context有其特殊的用法,不能当作分机使用。

当我们定义 channel 时(channel 并不是定义在 extensions.conf 中,而是定义在诸如
sip.conf,iax.conf,chan_dahdi.conf 等文件中), 对每一个 channel 都有一个必须的参数是context。这个 context 参数定义了一个指向 dialplan 入口点的指针,它定义了这个 channel是如何插入dialplan的。Fugure6‐1表示了channel配置文件和diaplan中context之间的关系。

这里要记住,每一个通道函数channel都要有一个必须的参数是context,为什么要这样呢,大家也没有想过,其实原因也很简单,你建立通道是为了什么,还不是为了打电话吗,打电话是不是需要分机,那在拨号脚本之中是用什么定义分机呢,还不是context,所以通道函数必须要一个context作为参数是不是很好理解了。另一个重点的问题是,我们必须明白,为什么通道不建立在extensions.conf中而是建立在pjsip.conf这种提供通话协议的文件中,这就像废话一样,只有真正在通话的时候我们才需要建立通道,闲着没事干你建通道干什么?
在这里插入图片描述
这是我们处理 channels 和 dialplans 时需要理解的一个非常重要的概念。
一旦你理解了channel配置文件中定义的context参数和dialplan的context
的匹配关系,你就会发现给 Asterisk 的呼叫流程排错是非常轻松的工作。

Contexts 的一个非常重要的作用(也许是最重要的作用)是提供安全性。通过正确的使用 contexts,你可以为某些用户提供一些其它用户不可使用的功能(例如长途呼叫)。而当你没有仔细的设计好你的 dialplan 时,你可能会无意允许他人欺诈性的使用你的系统。当你构建你的 Asterisk 系统时请牢牢记住,Internet 上有许多专门编写的机器人程序,它们专门寻找和破解没有很好配置安全性的 Asterisk 系统.
这里不用管,说白了就是,账号密码要写好。

2.分机

在通讯的世界里,术语 extension 一般指一个数字号码,当这个号码被拨叫时,将使一个电话(或语音信箱,队列等系统资源)振铃。这句话虽然简单,但是你必须要多理解几遍,extension其实就是一个数字号码,就好像110,你爸爸的手机号或者是10086,当你拨打这个数字号码时对端才会响铃。

在 Asterisk 中,extension 的概念要强大的多,因为它定义了一个步骤序列(每个步骤又都包含一个应用),Asterisk 通过这个步骤序列来处理一个呼叫。在每个 context 中,根据需要,我们可以定义很多(或几个)extensions。这里你必须注意,context不等于分机,我再重申一遍一个context不等于一个分机,他可以包含很多种分机的呼入方式,比如说你打10086,110,你爸爸的电话,都是有可能进入这个context的,然后再在这个context中匹配到你所需要的那个extension!

当一个特定的extension 被触发后(被一个来电触发,或者被某个 Channel 上的拨号触发),Asterisk 将执行这个 extension 中已经定义好的步骤。如你打10086自动转接到人工客服,因为你是VIP。

Extension 定义了当一个呼叫通过 dialplan 时会发生什么。尽管 extension 可以(它当然可以)被用于类似传统 PBX 的场景来指定一个分机号码(例
如,呼叫 extension 153 会导致 John 的桌面 SIP 电话振铃),在 Asterisk 的 dialplan 中,它还有更多的用途。
无论他有多少用途,我们都必须明白,extension并不仅仅单纯代表一个分机,而是代表当外部拨打这个分机后,所进行的一系列规则!!!!

extension 的语法是 exten,然后紧跟一个等于大于符号,如下面所示:
exten =>
再然后跟着的是这个 extension 的名字(或者数字号码)。当我们用传统电话系统拨号时,我们一般把 extensions 理解为你拨叫并使该分机振铃的号码。在 Asterisk 中,它有更多的含义,例如,extension 名字可以是任何数字和字母的组合。在本章和下一章的课程中,我们将使到数字和字母两种 extensions为 extension 指定名字看似来似乎是个革命性的概念,但当你认识到许多VoIP 应用都支持(甚至鼓励)用名字或 email 地址,而不是用数字号码来呼叫对方,这就非常浅显易见了。这是使得 Asterisk 如此灵活和强大的特性之一。
这句话意思就是,你打电话不一定只能打数字了,你打个人民都能通。

Extension 中的每一个步骤都由三个部分组成:
 extension 的名字(或号码)
 优先级(priority),每个 extension 可以包含多个步骤,每个步骤的编号称为优先级
 应用(application),或称命令(command),它们将在该步骤被执行时执行;
这三个部分被逗号分开,如下例所示:

exten => name,priority,application()
下面是一个真实 extension 的实例:
exten => 123,1,Answer()
在这个例子中,extension 名是 123,priority 是 1,application 是 Answer()。
//extensions是分机的名字,priority是优先级,具体的操作应用是answer

3 优先级(Priority)

每个 extension 都可以有多个步骤,称为 priorities。Priorities 是一个数字序列,从 1 开始,
并且每次执行一个指定的 application。举个例子,下面的 extension 将应答一个呼叫(priority
为 1),然后再挂断它(priority 为 2):
在这里插入图片描述

在 Asterisk 发行的老版本中,数字编号的 priorities 带来了很多问题。想像一下一个 15
个 priorities 的 extension,现在要在第二步增加一些东西:所有后续的 priorities 都需要手工
重编号。Asterisk 不会执行未编号或错误的编号的步骤,调试这种错误是毫无意义及令人沮
丧的。
从 Asterisk 1.2 版本开始,Asterisk 解决了这个问题:它引入了一种 n priority 的机制,n
的意思是下一个(”next”)。每当 Asterisk 遇到 priority 是 n 的语句时,会自动转换为前一个
priority 再加 1。这使得修改你的 dialplan 变得非常容易,因为你不再需要手工重新编号所有
的步骤。例如,你的 dialplan 可能看起来像下面这样:
在这里插入图片描述
Asterisk 会在每次遇到 priority 为 n 时计算实际的 priority。注 3 需要记住的是,你必须指定
priority 1。如果你不小心把上面例子中第一行的 1 用 n 来代替(一个常见的错误),你会发
现当你重新加载 dialplan 后,这个 extension 不存在。
总结上面:你可以用n来代替,优先级,它默认向下+1,但是优先级1你必须自己定义

‘same =>’操作符

在永无止境的简化编码的努力下,一个新的语法被创造出来,它可以使 extension 的创
建和管理更加容易。当 extensions 中保留有相同的部分时,与其不得不在每一行输入相同的
内容,你也可以简单的输入 same => ,然后跟着输入 priority 和 application:
在这里插入图片描述
缩进格式不是必须的,但它会提高可读性。这种风格的 dialplan 会使从一个 extension 到另一个 extension 拷贝代码更加容易。我们非常欣赏这种代码风格,并强烈推荐。
same就是拷贝前面重复的部分。

Priority labels

Priority labels 允许你在一个 extension 中给 priority 指定一个名字。这使得你除了利用 priority编号(这个编号有时是不知道的,比如你采用 unnumbered priorities 时)外还可以利用 label来指代这个 priority。我们需要能够寻址到一个特定 extension 中的特定 priority 的原因是,你可能经常会用到需要将一个呼叫从 dialplan 的一个部分跳转到一个特定 extension 的特定
priority。一会我们将对此做更多的讨论。为了给 priority 指定一个文字 label,只要简单的在priority 之后的括弧中增加一个 label 就可以了,如下例:
在这里插入图片描述
后面我们还会讨论如何在 dialplan 的不同 priorities 之间跳转的内容。你会看到更多的 priority labels,并且你会在你的 dialplan 中经常使用它们。

这里就是高端操作了,你给优先级打上一个label,后面可以直接跳转到这个label。

一个常见的书写 labels 的错误是在 n 和 ( 之间错误的插入了一个逗号,
例如:
exten => 123,n,(label),application(); <‐‐ THIS IS NOT GOING TO WORK
这个错误会打断你的 dialplan,而且你会得到一个错误导致 application 无
法被找到

4.应用(Applications)

Applications 是 dialplan 中的驮马(workhorse,实际干活的部分的意思)。每个 application都会在当前 channel 上执行一个特定的操作,例如播放一段声音,接受一个音频输入,在数据库中查询,拨叫某个 channel,挂机,等等。在前面的例子中,我们介绍了两个简单的
applications:Answer()和 Hangup()。你现在会学习更多关于它们是如何工作的知识。
一些 Applications,包括 Answer() 和 Hangup(),不需要其它的信息就能完成操作。然而,大部分 applications,需要一些额外的信息。这些额外的信息称为参数(arguments),被传递给 application 以指示如何执行操作。为了把 arguments 传递给 application,需要把它们放在 application 名字之后的括弧中,参数间用逗号分隔。

偶尔,你也可能看到用竖线(|)字符来隔开参数,而不是用逗号。从 Asterisk
1.6.0 开始,用竖线作为分隔符的作法被废弃了。

5.The Answer(), Playback(), 和 Hangup() Applications

Answer() 用于应答一个呼叫。它对收到来电的 channel 执行初始配置操作。如同我们早先提到的那样,Answer()不需要参数。Answer()并不是必须的(实际上,在某些情况下它根本就不适合使用),但它是一个有效的办法来确保 channel 在执行进一步操作前已经被连接上。

在这里插入图片描述
Playback()用于在某个 channel 上播放一个预先记录下来的声音文件。在 Playback()操作过程
中,用户的输入将被忽略,这就意味着你不能用 Playback()实现语音自动应答,除非你不希
望接受任何信息。

Asterisk 中有许多专业的声音记录文件,你可以在默认的声音文件目录(通
常在/var/lib/asterisk/sounds/)中找到它们。当你编译 Asterisk 时,你可以
选择安装用不同语言和不同格式录制的声音样本文件。我们将在许多例子
中用到这些声音文件。有几个我们例子中用到的声音文件来自于 Extra
Sound Package,所以,请花点时间安装这个包(参见第 3 章)。你也可以
通过访问 http://www.theivrvoice.com 来获得与现有声音提示文件一样的
你自己的声音提示文件。在本书的后续章节,我们也将讨论更多关于如何
利用你的电话和 dialplan 来创建和管理你的系统录音的话题。

为了使用 Playback(),需要指定一个文件名(不要扩展名)作为参数。例如,Playback(filename)
会播放一个名为 filename.wav 的声音文件,假如这个文件在默认声音文件安装目录下存在的
话。注意,如果需要的话,你也可以包含完整的文件目录作为参数,例如:
在这里插入图片描述
这样,/home/john/sounds/目录下的 filename.wav 文件会被播放。
你也可以在参数中使用相对路径,例如:
在这里插入图片描述
这样,默认声音文件安装目录下的 /custom 目录下的 filename.wav (比如
/var/lib/asterisk/sounds/custom/filename)会被播放。注意,如果在指定目录下有多个文件名
相同而扩展名不同的文件,Asterisk 会自动选择最适合的文件。

Hangup()的作用与其名字所暗示的完全一样:它挂断一个活动的 channel。你可以在 context的最后使用这个 application 来结束当前的呼叫,从而确保通话双方都无法在 dialplan 中以你未预料到的方式继续进行操作。Hangup()不需要任何参数,但是如果你需要的话,也可以利用它返回一个 ISDN 的原因代码(例如,hangup(16))。

6.一个简单的 Dialplan 例子

按照许多技术书籍的典型的作法(尤其是计算机编程类书籍),我们的第一个例子称为
“Hello World!” 在 extension 中的第一步,我们应答了这个呼叫。在第二步,我们播放了一个名为
hello‐world 的声音文件。然后第三步,我们挂断了这个呼叫。在这个例子中,对应的代码就
是:
在这里插入图片描述
如果你已经完成了第 5 章的例子,那么你应该已经配置好了两个 IP 电话机,同时你也
已经有了一个包含上述代码的 dialplan。如果你还没有实现第 5 章的例子,那么你需要将下
述代码输入到 /etc/asterisk/ 目录下的 extensions.conf 文件中
在这里插入图片描述
如果你还没有配置任何 channels,那么现在是做这件事的时候了。当你从
头开始创建了一个 Asterisk 的 dialplan 并且利用它打通第一个电话时,满
足感会油然而生。当人们意识到他刚刚创建了一个电话系统时,都会觉得
非常有趣而开怀大笑。这些快乐当然也属于你,所以,请首先让这个最简
单的 dialplan 工作起来。如果你遇到问题,那么请返回第 5 章并完成那里
的例子。
如果你刚刚添加了这些 dialplan 代码,你需要通过 Asterisk CLI 相关命令重新加载这个 dialplan:在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

举世无双勇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值