Call to undefined function music_list()

今天在 FreePBX 里试图编辑一个分机,点了编辑结果出现一个错误:Call to undefined function music_list()。

好端端怎么有了这么个错误?后来发现是没有安装 Music On Hold 模块的缘故,安装并启用这个模块,错误就消失了。

可是我不需要 Music On Hold 模块啊,记得之前也是为了应付一个错误安装了不需要的 Call Recording 模块。这样下去,模块越装越多,直到某一天 FreePBX 崩溃……

POP3 error resolved

一年多以前,我的 Gmail 邮箱就无法再从另一个中国方的邮箱 POP 收取邮件了。当时我以为是中国方的邮箱不再允许 Gmail 服务器连接到它的服务器去收取邮件,我就不再去管它,一是因为我管不了,二是这个中国方邮箱我已基本不用。但每次 Gmail 尝试 POP 失败,主界面里都有一个弹窗提示,很烦人。

就这样被烦了一年多,最近得知这样 POP 错误,是因为邮箱有某封信,把它删了就好了。于是我清空了收件箱,果然,Gmail 就成功 POP 收取了两封新邮件。

原来不是中国方邮箱不喜欢 Gmail 而设置的障碍,我想多了。

POP3 error history
POP3 error history

Zoiper cannot stay online on mobile phones

Zoiper 是我青睐的一个 VOIP 客户端,最大好处是它同时支持 SIP 和 IAX2 协议,最大坏处是它太想捞钱,竟然把视频通话功能归入收费版本。

言归正传,我在使用 Zoiper 过程中,发现 Zoiper 里的 SIP 或 IAX2 帐号在手机上不能稳定在线,通常是在手机屏幕熄灭 5 秒钟进入锁屏状态(默认设置)后,Zoiper 就掉线了;如果锁屏前 Zoiper 是当前窗口,则在锁屏后存活的几率大大提高,但仍免不了掉线。

另外有几个发现:

  • 如果在平板上使用 Zoiper,则非常稳定。
  • 在 Huawei P8 手机上使用 Zoiper,也非常稳定,真是个奇迹。性能更好的 Mate 7, Mate 8 在这方面都不如 P8。
  • 在绝大部分手机上使用 Zoiper,一旦掉线,Zoiper 不会(或看上去不会)自动重试上线。
  • 手机在充电时使用 Zoiper,则比不充电时要略稳定。

如果 Zoiper 不稳,那我就无法把重要来电转接到 VOIP。所以我花了点时间一一对比了 P8 和其他手机上 Zoiper 的设置。虽然我仍未发现 P8 上 Zoiper 能站稳的原因,但我发现,在电源省电管理里,给 Zoiper 选中“锁屏后保护进程”对其稳定在线是有好处的。默认未选中,P8 上的默认也是未选中,但 Zoiper 就是稳,所以我不理解。

不管怎样,“锁屏后保护进程”让 Zoiper 在 Mate 7 和 Mate 8 上稳定了好多,但又来了新问题——大大增加了另一种掉线的概率,错误信息:“503 Transport failure: no transports left to try”。我搜了一下,不知所云。

不过,我发现这个错误只针对 SIP 帐号。IAX2 帐号在选中“锁屏后保护进程”的手机上能稳定在线,期间经历 Wi-Fi / 4G / 3G 的来回切换,Zoiper 都能网络恢复后自动上线。幸好 IPPBX 的控制权也在我,那以后就在手机上用 IAX2 帐号吧。

Huawei mobile phone China release VS international release

我用手头的 Mate 7, Mate 8, P8 总结了几点华为国内版和国际版的区别。

1、谷歌被阉割。这个折腾一下是可以续上,但整个系统感觉不是浑然天成。

再谈下几个硬伤:

2、电话拨号程序里没有内置 Internet call,显然官方仍视 VOIP 如洪水猛兽。

3、电话拨号程序里多了阻止响一声的骚扰电话,IP 固定拨号,黄页号簿,都是跟国内用户需求有关,出了国就是鸡肋。

4、Browser(系统提供的浏览器)提供四个搜索提供商:搜索大全,百度,谷歌,淘宝,如果设定为谷歌,则为中国的谷歌,搜索时询问是否跳转到香港谷歌,非常烦人,而且无法添加新的搜索提供商,这几乎废掉了 Browser。

5、华为穿戴一定要输入华为帐号才能使用,而我之前用过华为穿戴就没有这种限制,我就特别气愤这种中外歧视(特指给外国人的优惠不给国人),就丢开华为穿戴不用。后来发现只要把区域改为英国,Huawei Wear 就不再询问华为帐号。

最后谈谈国内版的好处:

6、Calendar 系统应用里的 Calendars to be displayed 有一个 Other 组,可以选中显示农历,这个选择不随区域的修改而失效。我就是看它知道今年春节是 2 月 8 日。

7、Video 系统应用并不仅是视频播放器,而更像一个类似 Youtube 的视频内容提供商。我在里面可以找到很多中国的节目,其中少儿内容也很多,弥补了 Youtube 的不足。速度还可以。

Why my phone only ring once?

因为刚换了华为新手机,这两天摆弄手机比较多。

今天无意发现,我拿另一台旧手机打给它,只响一声就被挂断,我一度怀疑是因为手机开启了防骚扰功能(中国特色,英国暂时还没有这种困惑)。可是关闭防骚扰功能以后,仍然只能铃响一声。

我开始怀疑华为的智能来电识别(也算是防骚扰的一部分)仍在起作用。是不是旧手机号码对应的联系人信息有某种关键词符合骚扰特征?于是我删除了该号码对应的联系人,号码裸奔了,可仍然只能响一声。

我开始怀疑旧手机 07585 开头的号码在中国视为无效区号,于是把新手机语言和区域改为英国,可是还是只响一声。无语了。这时又发现反过来用新手机打给旧手机也是只响一声。于是我怀疑是手机死机了。

于是把新旧手机都重启了一下。手机重启的时候,我戴着的华为 B2 手环振了一下,这是手环的蓝牙连接断开的提示。这个振动提示提醒了我,B2 手环同时连接新旧两个手机,正是一个手机蓝牙的去电被另一个手机蓝牙的来电掐断,就这么简单。我关闭其中一个手机的蓝牙测试了一下,铃响正常了。

OpenVPN cannot resolve the host

Bhost 介绍了一款 OpenVPN 安装神器,它使得建立和维护 OpenVPN 服务器的工作量大大减少。我在一台服务器试用后,觉得很满意,又把它装在另一台服务器上。可是没多久,其中一台的 OpenVPN 不工作了,具体症状是:能建立 OpenVPN 连接,但客户端无法解析域名,也就无法访问 Internet。虽然可以在客户端手动添加路由就可以让客户端联网,但我总想找到是什么原因让好端端的 OpenVPN 坏掉——印象中我没有修改 OpenVPN 任何设置,它就莫名其妙坏了。

可我找不出原因,只好把 OpenVPN 删除,又重新装了一遍,这下 OpenVPN 恢复正常。可是另一台的 OpenVPN 立马又坏了,症状相同。

我就纳闷了,难道两台服务器有关联,只能有一台正常工作?!躺上床把当天的操作过程细想了一下,突然想到我在安装一台服务器的 OpenVPN 时,会习惯性地清理一遍另一台服务器的 OpenVPN 失效用户,用的也是 OpenVPN 安装神奇内置的 Revoke existing user cert 选单。难道是 Revoke existing user cert 有问题造成了 OpenVPN 不工作?我专门就此测试了一下,似乎又不是这个原因。但严格地说,我也不是完全没有改动过 OpenVPN 服务器配置,尽管用的都是 OpenVPN 安装神器来维护,可能是 OpenVPN 安装神器的脚本有 bug。

【2016 年 1 月 18 日更新】之前将 OpenVPN 突然不能解析的原因归咎于 openvpn_install.sh 进行了一些添加删除用户的操作,今天看来不是很恰当。今天在 Windows 8.1 客户端与两台不同地域的 OpenVPN 服务器进行了多次连接测试,结果如下:

  • Windows 标准用户,利用 OpenVPN GUI 调用存放在 config 目录下的 ovpn 配置文件,连接任何一台服务器都有问题:能完成连接,但无法解析域名。
  • Windows 标准用户,右击 ovpn 文件,选单 Start OpenVPN on this config file,连接一台服务器无问题,连接另一台有问题:能完成连接,但无法解析域名。
  • Windows 管理员,利用 OpenVPN GUI 调用存放在 config 目录下的 ovpn 配置文件,连接任何一台服务器都无问题。虽然连接过程中有很多行显示“write UDPv4: No Route to Host (WSAEHOSTUNREACH) (code=10065) ”,但不影响最终成功连接。
  • Windows 管理员,右击 ovpn 文件,选单 Start OpenVPN on this config file,连接任何一台服务器都有问题:连接后能解析域名,但 IP 仍为原 IP——连了跟没连一样。

上述四种情况下都会有“write UDPv4: No Route to Host (WSAEHOSTUNREACH) (code=10065) ”出现。我曾尝试以此为线索解决无法解析域名的问题,有人说“changing the MTU value of the bridge interface to 1492”,可以在 Linux 下解决解析问题,但在 Windows 下仍无法解析。我觉得即使在 Linux 下能行,也是瞎猫碰到了死老鼠,真正原因未必是 MTU。

不管怎么说,Windows 下,即使你用管理员权限把 ovpn 放入了 config,OpenVPN 连接仍需要管理员权限。如果你不小心用普通用户连接成功,那是运气,换一台机子未必能复制这种运气。OpenVPN 对管理员权限的严重依赖也是我不喜欢的,在这种状况不改善之前,我不想过多使用 OpenVPN。

Huawei Mate 8 and Google

自从知道华为应用市场里有谷歌框架安装神器,我就不再等华为 Mate 8 国际版的上市,买了一个行货全网通尝鲜。

Mate 8 的谷歌框架很顺利,但是我碰到了两个非常规的问题:

一是 Google Contacts 没有被同步到手机电话簿。后来发现还需要在华为应用市场上找“联系人同步服务”来安装,安装以后还要在权限管理里赋予“Google 联系人同步”这个应用所有的通讯录权限,之前是“提示”,要改为“允许”。最后重启才正常。

二是只能添加一个 Google 帐号。后来发现可以在某些 Google 应用的 GUI 里添加第二个帐号,我在 Maps 里添加里第二个 Google 帐号,通过这种“曲线救国”的方式,达到在设置里添加第二个 Google 帐号同样的效果。

虽然 Mate 8 终于连上了 Google 服务,但行货手机的一些细节方面用起来实在别扭,总的来说,如果有后悔药,我选择等待 Mate 8 国际版的上市。

Huawei app store has gapps

一直以来我都以为要在 Android 上安装 Google 框架只能求助一些开发者网站,比如 XDA Developers。但我一怕病毒,二怕麻烦,总希望原装设备上开机就带有 Google 框架,所以智能时代我从不买中国的行货手机,因为它们没有 Google 框架。

但最近华为 Mate 8 挺热门,我也关注了很久,可惜迟迟没有国际版,直到今天才听说华为两天前发布了 Mate 8 国际版,但要在世面上看到它,恐怕还得几个月。

正嗟叹中,朋友告诉我,华为应用商店里就有 Google 框架下载,安装好就能像国际版一样用 Google 服务了。有这等好事?我想起之前 Grandstream 也是如此迂回战术,但没想到华为也会。我赶紧上华为应用商店看,还真有一个叫”谷歌框架安装神器”的应用。我拿老妈的一个国行手机试了试,很顺利地装上了 Google 框架。我又拿它来给 Fanvil D900 Android IP Phone 安装 Google 框架,也很顺利安装成功(安装之前要 root D900)。D900 买了两年,一直觉得是鸡肋,就是因为它无法用 Google 服务,当时我频繁联系了 Fanvil 技术支持,他们给我发了好几个 firmware 去更新,都没有成功装上 Google 框架,后来我自行放弃。如今被华为的”谷歌框架安装神器”一举解决,我怎能不兴奋。(不过今天后来我在 Fanvil 官网上下了最新的 D900 firmware,更新后发现此次的 firmware 已带有 Google 框架,只是 Google Play 未安装,但在根目录下存了一个 Google Play 的 apk,安装一下就好了,也无需 root。)

总之,华为能提供 Google 框架,让我对入手国行华为手机再无顾虑。顺便我看了看小米应用商店,没有提供 Google 框架,那就多劝人不要买小米呗。

FreePBX 13 does not work on php 7.0.1

前几天安装 Magento 2,竟然说要 php 5.5 以上版本。本不追新的我,想到反正要用到 remi repo,那就装个最新的 php 7.0.1。结果 Magento 2 倒是能运行,但 FreePBX 13 的 web UI 出不来了,显示成空白页。我估计是 FreePBX 所用的 php 语法不够规范,简单排查了一下,根本没看出是哪里的毛病。我估计对 php 7.0.1 来说,FreePBX 到处是毛病。虽然此时 asterisk 仍正常运行,但我不能让 web UI 长期瘫痪啊,赶紧找了个时间拆了 php 7.0.1,换上了 php 5.6。这是目前兼容性最好的版本,FreePBX 和 Magento 2 均能运行,证明对 php 环境不能过于追新。

Install Freepbx 13 on CentOS 7

FreePBX Wiki 有一篇关于如何在 CentOS 7 上安装 FreePBX 13 详细的指导。我不想重复具体的步骤,只想说说如何解决在安装后出现的问题。

我在 OpenVZ VPS 的 CentOS 7.0 minimal 环境下依次执行了 FreePBX 13 安装指导的各项命令,期间并没有发现问题,下载、编译都很顺利。安装完成以后,发现虽能访问 FreePBX web UI,但对 FreePBX 进行的第一项测试——添加一个分机,就卡住了——注册不了。这时 VPS 还未重启过,虽然指导上没有让重启,那就重启一下看看呗。重启之后,更糟,首先发现 FreePBX web UI 访问不了,然后发现 ssh 也登录不了,最后发现连 ping 也不响应。只好用 serial console 登录后排查,发现 network 服务没启动,手动重启 network 服务也失败。

我只好把安装步骤分解,首先定位到是 yum groupinstall core 群组件造成 network 服务启动失败,然后再分解,发现是其中的 selinux* 和 NetworkManager 两个软件包的问题。定位这两个软件包花了我很长时间,这里按下不表。幸好这两个软件包也不是 FreePBX 所需要的,所以把它们卸载之后,network 服务就能正常启动了。FreePBX 安装指导提到需要将 SELinux 关闭,SELinux 也确实处于关闭状态,但它由 core 群组件安装后还是对 network 造成了困扰,卸载当然是最好的选择;NetworkManager 跟 network 冲突,似乎很久以前也碰到过,只是这次没有在第一时间想到是 NetworkManager 的问题,是地毯式排查中发现的。

网络正常后,就能访问到 FreePBX web UI,但 dashboard 上提示无法连接到 asterisk 服务。我再回头看安装命令,其中一项是 chkconfig asterisk off。我其实挺不理解的,为什么特意不让 asterisk 自启动,当时以为安装过程中暂时将它关闭,会在后期的脚本里配置好,让 asterisk 自启动。可事实上是 asterisk 没有自启,因此我认为 chkconfig asterisk off 是原作者笔误,应该是 chkconfig asterisk on。

另外,安装过程中特意执行了

firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --reload

这是开放 80 端口。我就纳闷了——作为一个 VoIP server,仅开放 80 端口有什么用?!之后发现,5060 端口也是开放的,因此 SIP 分机注册没有问题。我没见哪条指令将它打开,估计是在某个脚本里了。但是,还有好些端口,比如 RTP 默认端口 10000-20000,不打开这些端口听筒里就没有声音。我试了一下,果然没有声音。FreePBX 安装指导没有提及更多的 firewall 的设置,这需要在安装完成后自行设置。

执行到此,似乎就可以了,我添加了分机,并注册、互呼成功。但运行了大约半小时左右,再次添加一个分机,Apply Config 时,出现以下错误:

Reload failed because retrieve_conf encountered an error: 1

exit: 1
Unable to connect to remote asterisk (does /var/run/asterisk/asterisk.ctl exist?)
Exception: Unable to connect to Asterisk through the CLI in file /var/lib/asterisk/bin/retrieve_conf on line 24
Stack trace:
1. Exception->() /var/lib/asterisk/bin/retrieve_conf:24
1 error(s) occurred, you should view the notification log on the dashboard or main screen to check for more details.

这是因为 /var/run/asterisk/asterisk.ctl 在 asterisk 重启之后,属主、属组被修改为 root:root,而正常的应该是 asterisk:asterisk。为什么一开始的时候还能 Apply Config,一定时间后才出现问题?这个机理我搞不懂了。

Updated 20/12/2015:这个机理我猜想是 asterisk 有一个守护进程,在异常时会重启 asterisk,用户通常不会觉察到 asterisk 已重启,但这时 Apply Config 就被拒绝。解决办法是在 /etc/asterisk/asterisk.conf 增加以下内容,可以让 /var/run/asterisk/asterisk.ctl 保持属主、属组都为 asterisk。

[files]
astctlpermissions = 0660
astctlowner = asterisk
astctlgroup = pbx
astctl = asterisk.ctl