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

Lost network after update VPS from CentOS 7.0 to 7.1

昨天我把 VPS 用 yum update 了以后,重启,就发现怎么也登录不了 VPS 了。幸好还有 serial console 可用,登进去一一检查,一开始以为服务没有启动,接着又查防火墙、SELinux 的设置是否被改动,甚至查到了 runlevel,最后才发现 venet0 无法获得 IP 地址。难怪什么都访问不了了——谁会想到升级之后出这种毛病。

我见 VPS 控制面板里有 “Reconfigure Network” 按钮,看来就是针对网络失联的,可是点了好多次,也重启了好多次,仍然没有 IP 地址。我想是不是 /etc/sysconfig/network-scripts/ 目录下原有的 ifcfg-lo、ifcfg-venet0 和 ifcfg-venet0:0 三个文件无法被重置造成的?我就想把它们删除然后再按 “Reconfigure Network” 按钮。不幸的是,这三个文件被删之后,VPS 控制面板所有按钮都失效了,同时 serial console 也无法登录了。看来 serial console 仍是依赖于网络访问的——这跟我事先估计的不一样。

如果是台普通电脑,遇到网卡无法获得 IP 地址的情况,我肯定是插拔网卡,或者重装驱动程序。可这是一台 VPS 啊?我一度绝望了,以为只有重装系统了。大概过了十几分钟,我意外地发现 VPS 控制面板的按钮又可用了,serial console 也恢复了。大概是我删除这三个文件后,CentOS 自动检测到了新硬件,并安装了驱动。我用 serial console 登录后查看,果然 ifcfg-venet0 和 ifcfg-venet0:0 已经在那里,但 ifcfg-lo 没有自动恢复。这下我不敢乱来了,赶紧把 ifcfg-lo 从备份中拷贝过来。

但是,最关键的——venet0 仍没有 IP 地址。两个多小时过去了,我仍不知道该怎么办,只是不死心地 Google 着不同的关键字,终于被我找到一篇大神的文章。它教我编辑 /etc/sysconfig/network-scripts/ifup-aliases 文件,找到一行:
if ! /sbin/arping -q -c 2 -w ${ARPING_WAIT:-3} -D -I ${parent_device} ${IPADDR} ; then

把它删了,改成两行:
/sbin/arping -q -c 2 -w ${ARPING_WAIT:-3} -D -I ${parent_device} ${IPADDR}
if [ $? = 1 ]; then

保存退出,重启网络服务。Wow!真是见证奇迹的时刻,一切都正常了。

Install CentOS 7 on Fujitsu Server

我买了一个 Fujitsu TX2540 M1 服务器,可以说是一个错误的选择。因为它的安装逻辑异常复杂,花了好长时间才把 CentOS 7 安装成功。

期间多次以为它不支持 CentOS 7,只有在 Fujitsu Support 网站上找到一份文件说 CentOS 7 is “Tested”,才支撑我频频破碎的信念一直到成功。因为 Fujitsu 注明 CentOS 7 仅是 “Tested”,而非 “Supported”,意味着 Fujitsu 不提供官方支持。期间我尝试着按网上找到的方式,电邮联系 Fujitsu,问能不能告诉我我买的服务器 Megaraid 是什么型号。Fujitsu 回信说它不提供电邮支持(那你公布电邮干吗?)信里说可以使用他们的在线提问系统,于是我重填了一遍问题,然后得到回复说,要我打电话寻求支持。我彻底服了,不过我也没打电话,因为当时我也差不多摸索出来了。

言归正传。CentOS 7 安装时碰到的问题是识别不了 Megaraid,要我禁用阵列卡做单个硬盘使用,我又心有不甘。试了好些其他主流操作系统也是如此。后来我用 ServerView Installation DVD 启动,它是“预安装”盘。预安装界面里是找不到 CentOS 7 的,好在 CentOS 7 和 RedHat Enterprise Linux 7 的极其相似性,我选了RedHat Enterprise Linux 7 让预安装执行完毕,之后选择安装源千万不能选从 DVD 读取。我是指定了 CentOS NetInstall 的 URI 才顺利让机器重启后进入了 CentOS 的安装界面。这时安装目标盘已被预置为阵列卡(这时千万不要点进去,一旦进去后哪怕不做任何修改,返回安装过程又成识别不了阵列卡的状态),之后就是正常的安装步骤了。

最后吐槽一下 ServerView Installation DVD,它的操作系统竟然是 Windows,看得出 Fujitsu 已经落伍了。

Back to MySQL

不知从什么时候开始,Fedora 和 CentOS 里的 MySQL 都给换成了 MariaDB。我一直搞不懂好端端的 MySQL 为什么还要分出一个 MariaDB,更搞不懂 MariaDB 的优越性在哪里,反正 MySQL 对我来说够用了,倒是 MariaDB 安装和启动时使用了不同于 MySQL 的名称,让我很不习惯。比如

yum install mysql-server

换成了

yum install mariadb
service mysqld start

换成了

service mariadb start

幸好,除此之外,一切照旧,用到 MySQL 的 PHP 程序都能继续在 MariaDB 使用,所以我就一直用着 MariaDB。直到今天使用 Magento2,要求 MySQL 5.6 以上版本,而 CentOS 下把 MariaDB 用 yum update 到最新版本,仍是 5.5.40。

于是我被逼着去下载 MySQL 5.6。不用不知道,一用发现 CentOS 下安装 MySQL 超级方便,只要安装好 RPM 包——http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm,就可以恢复使用

yum install mysql-server

执行安装。

早知如此,我真不该碰 MariaDB——这个并没有给我带来实际利益的程序也花了我一天去熟悉。

Hands on GeoIP for Nginx on Fedora and CentOS

最近研究了一下如何根据用户的 IP 获得他的地理位置(我只关心 country 级,不关心 city 级),区别性地在 Ngnix 层面做一些限制性访问。这里用到 GeoIP 软件包和 MaxMind 的数据库。

在 Fedora 20 下,Nginx (目前 1.4.7) 依赖于 GeoIP。等于说,装好 Nginx,ngx_http_geoip_module 自然就启用了,只要在两个配置文件略作修改。

Fedora nginx -V output
Fedora nginx -V output

1. 在/etc/nginx/nginx.conf 里添加


http {

...

geoip_country /usr/share/GeoIP/GeoIP.dat;

...

}

2. 在 /etc/nginx/fastcgi_params 里添加


fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code;
 fastcgi_param GEOIP_COUNTRY_NAME $geoip_country_name;

还有其他参数可用,请自行查手册。重启 Nginx 就可以使用 GeoIP 的信息了。

在 CentOS 6.5 下,事情要复杂一些。网上说 CentOS 下的 Nginx 同样依赖于 GeoIP,可在我这里事实并非如此。同样是最新的 1.4.7 版,Nginx for CentOS 是不带 ngx_http_geoip_module 编译的。即使我用 yum install GeoIP 安装了 GeoIP 软件包,但 Nginx 不从源码编译就不能启用 geoip 模块。

CentOS nginx -V output
CentOS nginx -V output

着重提一下,我说的 CentOS 6.5 是 VPS 版,Nginx 和 GeoIP 无依赖是不是这个版本特有的?不得而知。我不想为之专门装一次 CentOS 来探究。我也不想从源码编译 Nginx,因为我太喜欢 yum,就为一个 ngx_http_geoip_module 搞砸了其他功能就不值得了。

退而求其次,CentOS 下不妨用 php 调用 GeoIP,只是感觉同样功能用 php 实现会消耗更多资源。另外,Nginx 能进行全面的限制,而 php 无法利用 GeoIP 信息限制对静态文件的访问。但是,Nginx 的全面限制也只能阻止低级用户,不可能阻止稍有点 IT 知识、一心要绕开地理位置限制来访问的用户,所以 php 对动态文件的限制其实也起到了相同的效果。

CentOS 下,安装 GeoIP for php,首先要装有 GeoIP,前面已经说了,要单独装:


yum install GeoIP

然后,安装  php-pecl-geoip:


yum install php-pecl-geoip

哈哈,都是我喜欢的yum。然后重启一下 php-fpm,即可在 php 下获得 geoip 信息。函数有很多,geoip_country_code_by_name()、geoip_country_name_by_name() 等等,请自行查手册。

顺便提一下,CentOS 6.5 VPS 版安装 GeoIP 后,带来的 country 数据库(GeoIP.dat, 6 Sep, 2011)有 1,183,408 字节,而 Fedora 20 的 GeoIP country(GeoLiteCountry.dat, 18 Jun, 2013) 数据库只有 581,110 字节,从 MaxMind 网站上下载最新的 GeoLite Country 数据库(GeoIP.dat, 每月第一个周二更新)也只有668,134 字节。考虑到 MaxMind 的数据库是分免费和收费的,那么,CentOS GeoIP.dat 这么大,是不是更接近于收费版?我不知道收费版是啥样的,因此无从考证。

Remove php-eaccelerator before updating php 5.3 to 5.4

今天用 yum update 升级基于 CentOS 的服务器碰到一系列的 errors。

Yum update errors
Yum update errors

我用了 –skip-broken 这个开关,不能解决问题。

因为 errors 太多,我实在没兴致仔细看,曾经想重装 OS 得了。但终究有一条 error 引起我的注意:

Error: Package: 1:php-eaccelerator-0.9.6.1-17.el6.remi.x86_64 (@remi)
Requires: php-common(x86-64) = 5.3.16

我尝试着卸载了 php-eaccelerator:


yum remove php-eaccelerator

然后再升级:


yum update

竟然错误没有了。升级成功!

那就再把 php-eaccelerator 装回去吧。


yum install php-eaccelerator

装不上。可能是 remi 的 php 和 epel 的 php-eaccelerator 不兼容吧。

1and1 server London zoneinfo is invalid

I can not believe it! One of the files come with 1and1 CentOS server installation is invalid. I do not know whether other types of servers from 1and1 have the same situation, but I am using 1and1 cloud server 64bit. The damaged file is /usr/share/zoneinfo/Europe/London. Every method I tried to set timezone to London (for now it is BST: British Summer Time), the system resets it to EDT: Eastern Daylight Time.

Normally I know how to set timezone on server, but cloud server is new to me. So when I see my methods do not work, my first reaction is looking for some secret method that works on cloud server. I have tried different ways to set timezone before I ever think about the London zoneinfo file is invalid. In a total hopelessness, I upload my PC’s /usr/share/zoneinfo/Europe/London from Fedora to CentOS, and it works.

Other zoneinfo files are OK as I observed.

Ftp user chroot setting on CentOS

在 CentOS 上,怎么把 linux user ftp 登录后限制在它的 home directory?很久以前我设置过一次,知道是很简单的一个设置,今天需要同样的事情再做一次,竟然怎么也想不起来。要命的是,google 了好几个小时都不得要领。

可以说半天时间是浪费掉的。最后当然是重新找到了办法,赶紧记下来:

Edit /etc/proftpd.conf, add

DefaultRoot ~

当然前提预装有 proftpd。如果还预装 plesk,则更简单,/etc/proftpd.conf 已含有

DefaultRoot ~ psacln

只要把新建的用户归入 secondary group psacln 即可。

Connect to mdb under Linux

虽然没有实际意义,只想挑战一下自己,在 centos 下尝试连接 Access 数据库。装好了 unixodbc (原先就在 centos 里,可能是默认被安装的) 和 mdbtools、mdbtools-odbc,搞定了一切设置,可就是出不来。

我是用 php odbc_connect 去连接 ActinicCatalog.mdb,页面一片空白,连个错误提示也没有,刚开始我还以为 web server 出问题。折腾了好久,最后,自己新建了一个很简单的 mdb 文件,终于在页面上显示出来了。

总结经验,centos 连接 mdb 需要关闭 selinux,然后,如果页面空白(连跟数据库无关的内容也不显示)不要怪自己,要么怪 mdb 里的结构太复杂,要么怪 mdbtools 能力太弱,读不出来。

大概只有微软自己知道怎么连接 mdb,第三方是不可能完全读懂它的了。

Fix Postfix in Virtualmin

今天在安装 Virtualmin for Webmin 时碰到一个问题:启用 Postfix 时出错,出错信息为:

A problem was found with your Postfix virtual maps : No map sources were found in the Postfix configuration

解决方法是: edit the /etc/postfix/main.cf file and add:

virtual_alias_maps = hash:/etc/postfix/virtual