Category: 小小草

IT 技术领域学海无涯。其实任何领域都学海无涯,无非 IT 发展太快了,让我有更多嘘唏。希望我掌握的技术有如小小草,虽然渺小,却有旺盛的生命力。

  • 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

  • What is the maximum RAM can Lenovo T410 upgrade to?

    According Lenovo official website, T410 “supports up to 8GB maximum memory”.

    From the forum of Lenovo, someone said

    I have exactly the same computer. Here is what I have tried:

    – 2x 8GB = didn’t work
    – 1x 4GB + 1x 8GB = didn’t work
    – 1x 2GB + 1x 8GB = didn’t work
    – 1x 8GB = didn’t work
    – 2x 4GB = WORKS….

    So maximum is 8GB (2x 4GB)

    However, they are both incorrect. I just tried 12GB (4GB under the keyboard + 8GB on the underside of the computer). It boots Fedora 22 workstation without any problems. Although it hangs on Windows 7 booting stage, I think it may boot Windows 7 or 8 from new installation. Whatsoever the fact reflects Fedora is more robust than Windows.

    I will try if T410 supports 16GB if I can find a way how to install RAM under the keyboard.

    UPDATE: I have tried 16GB (8GB under the keyboard + 8GB on the underside of the computer). Fedora boots all right (Windows still hangs). So the final answer to the maximum RAM can Lenovo T410 upgrade to is 16GB! Here is the screenshot as a proof of my experiment.Lenovo T410 with 16GB RAM running Fedora

  • 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——这个并没有给我带来实际利益的程序也花了我一天去熟悉。

  • NIC is a critical point

    一个网络设备好不好,就拿大文件去测试它。

    LinkSys WRT54GL 路由器就有这样的问题:从 WAN 端口下载若干GB 大小的文件,中途就会断开,路由器也不工作了,它的 web 管理界面也访问不了,非得重启才能恢复。

    今天发现我的网络硬盘 WD MyBookWorld 2TB 也有此类问题:在拷贝两个20多GB大小的文件过程中,中途也被断开,再也访问不了 MyBookWorld,重启后恢复。

    以前我以为这些家用级的网络设备在大流量压力下会死机(CPU 超载),今天的结论是 CPU 或许还有余力,但网卡超载了。因为,在访问不了 MyBookWorld 时,我拔出了一个 USB 设备(我用 MyBookWorld 的USB 口在给手机充电),触发了 USB device unplug 的事件。通常我会收到一个邮件通知,但这次因为网卡停止响应,CPU 仍在工作,记录下了这个事件,延迟到重启后网卡恢复正常才发出邮件。

    网卡很关键,以后得多关注这方面的指标。我现在热衷于选用商业级的设备,即使是为家用。

  • Change FreePBX default MySQL connection

    我可能吹毛求疵了:我感觉如果要修改 FreePBX 里默认的 MySQL 的连接位置好麻烦。

    我修改成 MySQL socket 方式连接,而且也修改了 socket file 的位置,然后要修改 FreePBX 好多个文件才能让 FreePBX 对接 MySQL。大部分文件属于 FreePBX 配置文件,还好办,象填表格一样填就是。但 /var/www/html/admin/modules/userman/DB_Helper.class.php 根本没为 MySQL socket 连接方式考虑,DSN 只兼容 host 连接,所以要大改 262 行(以FreePBX 2.11.0.39为例)。

    要改成多行:

    
    if (preg_match('/^unix\((.+)\)$/', $amp_conf['AMPDBHOST'], $matches) === 1) {
    	$ampdbsocket = $matches[1];
    	$dsn = "mysql:unix_socket=".$ampdbsocket.";dbname=".$amp_conf['AMPDBNAME'];
    }
    else {
    	$dsn = "mysql:host=".$amp_conf['AMPDBHOST'].";dbname=".$amp_conf['AMPDBNAME'];
    }
    
    

    直接修改程序是我最不愿意的。FreePBX 似乎也没提供安全升级的办法,所以 User Management 模块一升级,上述修改就作废,FreePBX web portal 就出错。

  • Allow specific “anonymous” inbound SIP calls

    之前所有的 SIP 服务商都是提供 SIP 注册的帐号和密码。最近碰上一个新的 SIP 服务商,购买了一个电话号码,它只让我设置 Forward to SIP Server 或 Forward to SIP URI(当然也可以转发到普通电话号码,但那是要额外收费的,不在我考虑范围之内)。

    于是,碰到了新命题:我必须在 FreePBX 的 SIP Settings 里同时启用 Allow SIP Guests 和 Allow Anonymous Inbound SIP Calls 才能收到转发过来的 SIP calls。这两项都是我不愿意启用的设置,因为存在被 SIP hackers spamming 的风险。尽管单独启用 Allow SIP Guests 据说没有太大风险,但还是接不到电话,呼叫方会收到 FreePBX 给出的语音提示:The number you have dialed is not in service. Please check the number and dial again.

    怎样才能让来自 SIP 服务商的 anonymous calls 通过,而把其他的阻挡在外?我甚至想到了启用 Allow SIP Guests 和 Allow Anonymous Inbound SIP Calls ,但用防火墙规则只允许来自特定 host / IP 的流量。这个方法我自我评价是非常 dirty,我希望是 FreePBX 的问题在 FreePBX 内部解决。

    我几乎不带希望,搞了个试验,创建了一个 SIP trunk。它跟之前注册型的 SIP trunk 的区别就是省略了 PEER Details 项里的 username, password 和 Register String。然后,同时禁用 Allow SIP Guests 和 Allow Anonymous Inbound SIP Calls,这时 Forward to SIP URI 已经能工作;再添加一条 Inbound Route,Forward to SIP Server 也能工作了。

    这个事实推翻了我对 trunk 的原有理解—— trunk 只是一条进或出的通路。现在我知道 trunk 还能“命名”符合特定条件的“匿名”来电,起到过滤的作用。

    此外,我猜想,转发型的 SIP 服务比注册型的 SIP 服务更可靠,因为转发型的 SIP 只在有来电时把数据包转发到我的 FreePBX;而注册型的 SIP 则要不时地重注册保持连接,有时连接已经断开,而 FreePBX 不知道,要等到下个周期才重注册,于是会错过来电。不知我猜想对否?请教过路的 VOIP 专家。

     

  • WP Social Login back to working

    WP Social Login 这个插件在芳草苑上好长时间工作不正常了。无法通过 Google 帐号登录,显示的出错信息是:Oops! We ran into an issue. Request failed. Either you have cancelled the authentication or Google refused the connection.

    Google authentication failed
    Google authentication failed

    今天终于找到原因,其实也不是插件的错,而是在 Google 开发者项目设置里没有开启 Google+ API。默认是禁用,启用就行了。

    Enable Google+ API
    Enable Google+ API

    我隐约记得有消息说 Google+ API 发布以后,WP Social Login 从 Google API 转向了 Google+ API。但当时也没留意看,现在也搞不清楚 Google API 和 Google+ API 有什么区别。IT 技术发展太快了,很多概念只能浮于表面,能用足用好已经不错了。

  • Use long established business for your hosting

    前段时间用了一个名不见经传的公司的 VPS 产品。当时看它性能不错才切换过去,但是它操作极不规范,到期前不催续费,我想主动续费都没有链接可以让我续。突然有一天,它意识到有未收账款,也不通知我付款,就停了我的帐号。然后我付款,重新开通服务。中间中断了大约半天的服务,让我损失惨重——那天以后来自 Google 和 Facebook 的流量突然就下降了。这也让我百思不得其解:

    1. 我知道一个网站的 uptime 是很重要的指标,但是,好像影响过头了?以致我怀疑流量下降不是 uptime 的问题,但转折点就在宕机的那一天,是巧合吗?
    2. Google 和 Facebook 使用同样的算法?

    总之,不正规的公司是绝对不敢用了。离开之前,我自己清空数据,以下一行命令删除 MySQL 里所有的数据库,抄来的,很方便。

    mysql -uroot -pPASS -e "show databases" | grep -v Database | grep -v mysql| grep -v information_schema| grep -v test | gawk '{print "drop database " $1 ";"}' | mysql -uroot -pPASS