Category: 小小草

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

  • When to use Magento layered navigation?

    Rcah module for Magento
    Rcah module for Magento

    Although I released a Magento module “Root Category as Homepage“, which enables replacing the default CMS page with the root category as homepage, thus the users can start layered navigation from the very top level of category, the usage of this module should be limited, for the sake of usability.

    In short, use Magento layered navigation only to narrow down the choice of products. Do not use it for the purpose of grouping products by some filter attributes. There are many other ways to group products together.

    I will explain in details when I have some more time.

  • Fixed NextGenGallery 0 images were uploaded error

    Nggallery 0 images were uploaded
    Nggallery 0 images were uploaded

    不知从何版本起,NextGenGallery 插件在我的 WordPress 上就不工作了,主要症状是:

    • 后台无法在 Gallery 里上传图片,显示 “Upload complete. 0 images were uploaded.”(WordPress 自身的 Media 上传正常)。
    • 后台无法批量导入图片,服务器的文件夹根本就不显示。
    • 已有的 Gallery 在前台只能显示第一张图,点下一张图就是 404 错误。

    这个问题困扰了我约有半年。期间发现把 Permalinks 改为 Default 模式能让 NextGenGallery 恢复正常,但我不可能为了 NextGenGallery 修改 Permalinks 啊,只好任由这个问题存在。所幸迄今为止只有 5 galleries,而且都不怎么重要,所以这个问题不突出。

    上个周末突然犟了一下,我觉得不该卡在这个问题无从下手啊,调用 google N 多次,终于在一个角落里给我找到一点端倪,再做了 N 多次试验,得出的结论是此问题在 PHP installed as an Apache module 时不存在,我恰用的是 Nginx,罪魁祸首是 fastcgi_param 没弄好。

    出现此类问题是小概率事件,即使是一个不完善的 fastcgi_param 配置,我的 Nginx 也让大部分 PHP 跑了多年没出其他问题。NextGenGallery 也有一定责任,使用了一种不推荐的环境变量,在 PHP installed as an Apache module 下不会激发这个 bug,但在 Ngnix + 不完善的 fastcgi_param 会。而我用的不完善的 fastcgi_param,我相信很多人都在用,所以有一定的普遍性。

    言归正传,怎么改?

    有人说把 NextGenGallery 的 class.router.php 的 function get_request_uri 的 if (isset($_SERVER[‘PATH_INFO’])) 改为 if (empty($_SERVER[‘PATH_INFO’])),确实能奏效,但我认为不理想。因为:

    • NextGenGallery 虽有错,但大错不在它,而在 Nginx 没配好。
    • 这个问题被反应到 NextGenGallery 开发者很久了,期间 NextGenGallery 升级了无数次,也没见他修正此 bug,可能他认为此 bug 非 bug。

    我认为解决问题的根本办法是在 fastcgi_param 文件里,把通常人用的

    fastcgi_param  PATH_INFO          $fastcgi_path_info;
    

    改为

    fastcgi_param  PATH_INFO          $fastcgi_path_info if_not_empty;
    
  • Newly installed BT Infinity keeps dropping

    Is BT Infinity stable
    Is BT Infinity stable

    BT Infinity 装了四天。前两天每天都会有一两次断线再续上,这离我心目中一个月都不断一次的设想有很大距离,但说实话,这并不影响使用。

    昨天下午开始,我注意到 BT Infinity 频繁断线,一个小时内会断好几次,这下我受不了了。我写了一个检测脚本,从凌晨2点多开始运行,收集到以下数据:

    ip up_time down_time
    86.163.4.231 2014-03-28 02:26:27 2014-03-28 02:31:34
    86.155.231.26 2014-03-28 02:34:02 2014-03-28 03:02:35
    86.163.218.228 2014-03-28 03:05:01 2014-03-28 03:34:01
    86.144.50.27 2014-03-28 03:37:01 2014-03-28 04:03:19
    86.155.228.111 2014-03-28 04:06:01 2014-03-28 04:34:01
    86.163.218.154 2014-03-28 04:37:01 2014-03-28 05:04:03
    86.164.192.9 2014-03-28 05:07:01 2014-03-28 05:36:01
    31.52.209.24 2014-03-28 05:38:01 2014-03-28 06:05:35
    86.144.50.126 2014-03-28 06:08:01 2014-03-28 06:36:02
    86.164.194.59 2014-03-28 06:39:01 2014-03-28 07:06:03
    86.164.194.91 2014-03-28 07:09:01 2014-03-28 07:38:01
    86.144.51.127 2014-03-28 07:40:01 2014-03-28 08:09:01
    86.155.228.111 2014-03-28 08:10:02 2014-03-28 08:31:02
    86.155.230.112 2014-03-28 08:41:01 2014-03-28 09:08:05
    86.149.254.255 2014-03-28 09:11:01 NULL

    我注意到从今天早上 9:11 开始,一直到现在下午 3:55,没有掉过线。我猜是 BT 在大部分人的非工作时间远程更新 Home Hub 5 的韧件,但我也并不喜欢 BT 来操控已经属于我的路由器,更不喜欢 BT 决定更新韧件的时间,是时候考虑买一个正宗的路由器,彻底堵住 BT 的后门。如果这次频繁掉线不是 BT 更新韧件引起的,那更糟糕,BT Infinity 竟然如此不稳定吗?我更换宽带,等了一个多月,等来的是如此结果?我暂不想下这个结论。不管怎样,我已经向 BT 反映了频繁掉线的问题,正等待它的反馈。

  • Publish on blog or social network?

    International social media icons
    International social media icons

    博客出现在 web 2.0 时代,社交网站算 web 后2.0 时代吧(web 3.0 概念不清,我不好拿来用)。

    博客和社交网站的界限模糊,有很多交集,比如博客发展到微博就归入了社交网站。但我这里说的博客,指的是用自主建站的方式,比如用 WordPress  搭建的博客,其他非博客类的 CMS,也可以归入博客范畴;而社交网站,指的是依托第三方的社交平台,通过开设帐号,发布消息。

    社交网站诞生多年,我的使用态度一直不积极。我相对较早使用 QQ ,但 QQ 空间至今没有开通;我也没有新浪微博、腾讯微博,更不要说什么人人网之类的;微信也是开通不足半年,还是被没有微信就活不下去的朋友逼着开通的;我也没有 Linkedin,因为它排不上前三;Facebook, Twitter 虽不缺账号,但也懒于维护;唯一用得比较多的 G+,那也是因为我是 Google 的粉丝,Google 想要在社交网站有所建树,我友情支持。

    我通常对新生事物都是积极尝新的,为什么不喜欢社交网站?我也不懂自己,勉强找了两点理由:

    1. 大部分人在社交网站发的贴没有深度,无非是“今天的大餐好好吃”、“我在公车上看到有人打架”,这些内容当时有人围观,过了一周、一月或一年,没人会关心你那时吃了什么、看了什么,连你自己也记不起来。
    2. 转贴太方便,个个都是新闻发言人,很多都是以讹传讹,即使是真实的也没有出处可循。转来转去,互联网信息急剧膨胀,原创比例急剧萎缩。

    但从商业角度看,不占领社交网站,就会失去和潜在用户联系的机会。怎么合理安排时间和精力维护这么多的社交网站?我草拟了一套方案:

    • 博客为主,社交网站为辅。就是说一定要有自己的博客,然后在时间和精力有盈余时,兼顾尽可能多的社交网站。
    • 内容只发布在博客上,社交网站只转其标题和链接。在内容有错别字或需要更新时,只要更新博客一处即可。虽然有很多工具可以自动同步多个社交网站的内容发布,但是我还没发现一款工具能做同步更新。如果要手动更新各个社交网站,工作量是很大的。而且是重复劳动,我最痛恨。把原创内容直接发布在社交网站上,从 SEO 角度看,是在给他人做嫁衣。
    • 博客要做一些社交网站做不到的事,比如说文章的分类整理、参数查询等等,方便用户记住你的博客,而不仅是你的社交网站的账号。当然你也可以放些广告,赚取额外收益,而在社交网站上这部分收益就不会归你了。
    • 博客要装有分享插件。服务端的分享插件在你发布新贴时,同步标题和链接到你的多个社交网站的账号;客户端的分享插件让用户在浏览帖子时,分享到他常用的社交网站的账号。WordPress 的社交插件有不少,但面面俱到、用起来得心应手的,我还没找到。你若有,别忘了分享给我。
    Chinese social media icons
    Chinese social media icons
  • Change PHP directives in Magento

    Today a Magento store owner asked me why he could not create a new attribute set based on an existing one. I took a look into his store and found out the existing attribute set has many custom attributes, which led to new attribute set creation would take more than 30 seconds. But 30 seconds is the default PHP max execution time, which is set in php.ini and has not been optimised for Magento backend operation.

    My immediate reaction was changing the default value of max_execution_time to 120. I added a line in /etc/php-fpm.d/www.conf, where is my preferential place to set server wide PHP directives rather than /etc/php.ini.

    
    php_admin_value[max_execution_time] = 120
    
    

    After a while, I had another thought. I do not like to extend PHP max execution time for most of other websites on the same server. Even for the Magento store, longer execution time is only needed for the backend operations. So how can I specify different PHP directives for different websites? Particularly, how can I specify longer execution time or larger memory limit for Magento admin users?

    My first idea was creating separate php-fpm (Yes, I am using php-fpm.) profiles for this purpose. However, I rejected this idea after 2 seconds, because:

    1. I do not like to create more PHP daemons into the valuable server memory.
    2. If Magento frontend and backend are on the same domain, I have no way to assign a corresponding daemon.

    So, can I implement changing run-time PHP directives using a Magento module? Of course. I had a Magento module called Msdk (Magento SDK). I just need to add this feature to Msdk.

    Firstly, I need to find a proper event to catch. The event should be dispatched only once per request, and earliest possible when it can distinguish frontend or adminhtml route. The earliest event is “controller_front_init_before” except some database events, which are not recommend to catch anyway. But “controller_front_init_before” can not distinguish frontend or adminhtml route, i.e. it can only be put into global section in config.xml. Following the event timeline, I find “frontend or adminhtml route” is the best event to catch.

    Secondly, I put one “controller_front_init_before” event catching into frontend section and another into adminhtml section in config.xml of Msdk module.

    Thirdly, write two observers in a Helper or a Model to apply PHP directives.

    Lastly, modify system.xml to allow users to set PHP directives in Magento System Configuration.

    It sounds complicated but actually not. I finished it in a couple of hours.

    BTW, Msdk is one of my free modules. But I am not going to launch it now with only one new feature. Watch the space for updated news.

  • Cure fail2ban on FreePBX

    不知从什么时候起,FreePBX 上的 fail2ban 不能启动了。amportal restart 时,其他项都是绿色的 OK,执行到最后是 fail2ban,两行:

    Stopping fail2ban [Failed]
    Starting fail2ban [Failed]

    两个红色的 Failed 触目惊心。

    看了看 /var/log/fail2ban.log,一头雾水。再说它不更新已经很久了,估计不能启动以后就没有更新。研究它的最后几行也不知对解决问题有没有帮助,总之我缺乏细看的耐心。问 Google 吧!有人说,

    yum remove fail2ban
    yum install fail2ban
    

    就能重新工作了,就这么简单。一试,果然!

    问题虽然解决,但我对 FreePBX 软件质量的印象分有所降低——“不明原因、重装解决问题”似乎是 Windows 的特症,怎么 CentOS 下的 FreePBX 也染上了?!

  • Sftp chroot howto

    我之前在服务器上应用 Ftp chroot,那设置起来相对简单。但 Ftp service 不是服务器预装的,通常我会装 proftpd 或 vsftpd。

    这次我想为什么不用服务器预装的 Sftp service?我有点钻了牛角尖—— Sftp 比 Ftp 好在哪?更安全?似乎这增加的安全性对我来说毫无意义。少占点硬盘空间?空余字节多着呢。总之,我想到了就想把它用起来。

    首先新建一个用户组,sftponly,只要是这个组的用户 Sftp 登录后都会被 chroot。

    
    groupadd sftponly
    
    

    然后把需要 chroot 的用户都加到 sftponly 组

    
    usermod -a -G sftponly user1
    
    

    如果是新用户,则在创建的时候直接参组。

    
    useradd -U -G sftponly -s /sbin/nologin -d /path/to/user1_home user1
    
    

    然后要保证 /path/to/user1_home 这个目录及所有各级父目录的属主是 root,属性 755。user1 在他的 home directory 下是没有写权限的,不能由他自己创建文件或文件夹。这也容易理解,因为他被 chroot 以后,他的 home directory 看上去是系统根目录,普通用户当然不能在根目录这一级有写权限。这时需要 root 事先为 user1 创建好若干文件夹,如 /path/to/user1_home/documents、/path/to/user1_home/pictures,并将 documents、pictures 的属主指定为 user1。

    然后我按网上的指点依样画瓢,在 /etc/ssh/sshd_config 里添加了这几行:

    
    Match Group sftponly
        ForceCommand internal-sftp
        ChrootDirectory %h
    

    然后重启 sshd service

    
    service sshd restart
    
    

    理论上这时 user1 已经可以在 Sftp 登录是被 chroot,限定在他的 home directory。但是 user1 怎么都登录不了,碰到的错误是:

    Connection closed by server with exitcode 1

    原来,在我的 /etc/ssh/sshd_config 里有这么一行

    
    Subsystem       sftp    /usr/libexec/openssh/sftp-server
    
    

    这是服务器预装时的配置,可能不是所有的服务器都这样,但有一定的普遍性。

    这说明,Sftp 子系统是由 /usr/libexec/openssh/sftp-server 支持的。而在被 chroot 的 user1 看来,是没有 /usr/libexec/openssh/sftp-server 这个文件的。怎么办?两个办法:

    办法一:将那一行改为

    
    Subsystem     sftp    internal-sftp
    
    

    办法二:在 user1 的 home directory 下建一个副本 %h/usr/libexec/openssh/sftp-server,只是简单的文件拷贝。

     

  • 5V2A adapter for IAD

    前不久在淘宝上淘了一个华为 U-SYS IAD101H,准备用作 MGCP 语音网关。才 28 元人民币,运费 6 元,真的很便宜。

    Huawei U-SYS IAD101H
    Huawei U-SYS IAD101H

    卖家说明自配变压器,是 5V2A 的电源。我加钱求卖家帮我配好变压器,但卖家不帮忙。因为语音网关还未转寄到我手上,所以我也没急着寻购 5V2A 变压器。今天无意中在我家电视机柜边上翻出一个孤零零的变压器,一看正好是 5V2A。我想了半天没想出它是哪个设备元配的变压器,先拿来用了再说。

    5V2A adapter
    5V2A adapter
  • Newbie’s experience in setting up an IPPBX

    I classify myself as a newbie as I have been diving into Asterisk / FreePBX for only 3 months. I am not familiar with 95% parameters of my IPPBX, and I try to avoid touching those parameters. However I can proudly say I have gained enough experience in setting up an IPPBX for a commercial environment, and I want to share it with you.

    Before I start, I have to make it clear what my goals are, so you know if my experience suits you.

    Firstly, I do not have massive users, say less than 100. We did not use any PBX, but once we launch IPPBX, it must be working very stably.

    Secondly, users should be able to pick up the calls in the office, at home or on the move. Myself is a typical user, who answer 1/3 calls in the office, 1/3 at home, 1/3 on the move.

    Thirdly, I want to save every pence possible on this first IPPBX. There are many IPPBX with Asterisk preinstalled and probably optimised on the market, whose prices start from £150. However I think at £150 it is an entry level product and geared for a SOHO enviroment. If I hunt for a proper commercial Asterisk IPPBX, I should look for something above £300.  I am a fanatical DIYer and I believe business can take advantage of open source. Free open source allows business to do the same things other highly priced product can do, and sometimes does better. Of course the price of open source is the learning time. I spent £100 on the hardware (Bought from China directly. I evaluate it as £190 for similar hardware on the UK market), and 3 months in learning. A commercial Asterisk IPPBX with the equivalent capacity should be priced at £500 or so.

    My 3 months’ learning only saved £400 which is a loss. Nevertheless, back to the topic – my gained experience in setting up an IPPBX.

    I do not need to connect IPPBX to a physical analogue (POTS) or digital (ISDN) telephone line. If you do, and the more lines to connect, the more worthwhile to buy a commercial IPPBX with FXO or BRI ports built in. None of analogue/digital cards or ATA or ISDN gateways are cheap.

    At the time of choosing a DIY IPPBX other than a commercial IPPBX, I was quite worrying about the stability. Now I can say software stability can be achieved by a newbie like me. But to make the whole system work reliably, I have to buy a decent hardware to run it on, and most importantly, a reliable network. My current ISP is horrible and due to be switched away in next month. It wasted me a lot of time debugging – barking at the wrong tree. I would not say “horrible” if I was only using their network browsing Internet. It looks like it can not afford VOIP traffic when it comes to host an IPPBX.

    I set port forwarding on the NAT router where IPPBX is. I forwarded SIP bind port and RTP ports. I did not do everything at client side router. The SIP client should traverse a router not in my control.

    I put NAT in Settings >> Asterisk SIP Settings to “route”, which instantly solved a lot of audio silence between various devices, i.e. high end SIP phone, entry level SIP phone, and several soft SIP phones installed on several Android based mobiles. I still can not understand the exact logical behavior of “yes”, “no”, “never”, “router” for NAT choice, but to me, “router” is the best choice.

    I totally understand many people says SIP behind NAT is a nightmare. My IPPBX is behind a NAT router in the office, and if I am at home, my extension is behind another NAT router. This is the worst scenario. With FreePBX Distro and the above simple configuration, but without help of any third party modules, proxy, stun server, SER, the most difficult problem I encountered is one way audio on some devices / soft phones. It is always the caller can not hear voice from the callee, but the callee can.

    Then I find enabling stun server on SIP client does not do anything good. Actually I find enabling Rport for signaling and media helps eliminating one way audio symptom if this choice is available. If your device does not have such a choice, but you have two devices at hand, you can dial out using one of them and transfer the call to the other one. This method makes both ends callees. So tricky. Do we really to do that? No. I have better way later on.

    Missing codecs may cause audio silence, but it has nothing to do with one way audio. If a required codec is missing, both ends will be silent. I have a weird SIP trunk provider supplying 2 lines. Both lines have an external number (connecting PSTN) and an internal number (extension number on his SIP server). It turned out he enables different codecs for these 2 lines. And even on the same line, he enables different codecs for external number and internal number. It took me a long time before I realised it was a codec problem.

    Although Android mobiles are widely available, it is worth buying SIP phones for office and home.  SIP phones can stay online much more stable than any of soft SIP phones on Android mobile. It may not be a fault of soft phones. They are restricted by Android power management. The advantage of Android devices is you can choose SIP apps to install. To get the best of both worlds, the best buy is an SIP desktop phone with Android OS.

    Among SIP apps, I recommend Zoiper (most stable, and support IAX2), CSipSimple (support video calls with CSipSimple video plugin), Samsung Galaxy built in SIP client (may be best choice in power saving), in turn.

    It is time to summarise how to tackle one way audio. I mentioned IAX2. Yes, for soft phone, use it as the first choice over SIP. (Sadly as a hardware, VOIP phone with IAX protocol are not widely available.) I am using Zoiper on the move. In the office, as it in the same subnet, SIP traversing is not a problem, so any SIP phones will do the job. At home, use a SIP phone which can enable Rport, or use Zoiper.

    I tried to achieve a stable IPPBX without having to periodically reboot it, but I could not. The IPPBX runs into a hanging state every a few days. For example, all trunks / extensions are disconnected. Even “amportal restart” can not solve the problem. A daily reboot is a must. Just choose a quietest time and use crontab to reboot. My IPPBX reboots in 34 seconds, which means the uptime is 99.96%. Normally the IPPBX will not hang within a day. But I set a monitoring script anyway to monitor if all trunks / extensions lose connection, reboot the IPPBX immediately. It never happened so far.

    I also find IPPBX daily rebooting is a usual practice. I have monitored two of my SIP trunk providers are rebooting their servers daily. I am going to test it on a third one. Besides, I will be very glad to see a future version of FreePBX can run without rebooting for years as Nginx, etc.

  • SIP requires very reliable network

    我的 SIP 服务器 FreePBX 暂时还放在一个非常不可靠网络环境下,这在前文《FreePBX working with an unstable router》有提及,一有 SIP 不正常的风吹草动,我就成了惊弓之鸟。

    今天早上我在家,发现 SIP 分机又出现单向语音的症状,测了多次,十次有九次是单向语音,主要是主叫方听不到对方声音。我在服务器上看来看去看不出原因,不管三七二十一,又重启了一次,仍没解决问题。

    单向语音是 SIP 很常见的问题,在用 FreePBX 之初,我曾花大力气去解决,找到一套行之有效的办法。怎么今天又出现了老问题了?我一阵头疼。

    我家的网络宽带路由器确实不太好,但一开始我没意识到是它的原因,因为浏览网页是正常的,再说 SIP 能注册,也能接通。我排查了很久,无意中将手机 Wi-Fi 连接关闭,用 3G 连接网络,手机的 SIP 客户端立刻就能双向语音,一切正常。我这才想到是网络宽带路由器的原因,把它重启了一遍,SIP 通话就正常了。

    看来 SIP 对网络的要求非常高,而且是服务端、客户端双方的要求都很高。