更换服务器对lnmp、eac、xc和mc的折腾记录

以前在HelloHost的凤凰城的空间访问速度越来越不理想了,跑个Discuz都卡掉渣的。空间也略神奇,发邮件时不时要抽一下两下的。偶尔可以sendmail,有时候只能smtp。UC也时不时要抽一下,不过总体来说还是物有所值的,对速度要求不高的,或者有CDN的可以买来试试看。不过我既没有CDN,也没法忍受那样的速度于是就想着换个地方来的。和ivmm(via 米饭维谷)交流了一阵子。后来他推荐给我LocVPS(via LocVPS|无推介链接)家的VPS,说是洛杉矶机房,和大陆线路是直连的。于是回来以后就买下了LocVPS的Xen 512M方案,使用军哥的LNMP自动脚本(via LNMP一键安装包)搭建的LNMP环境。

环境搭建起来以后要考虑的主要还是安全问题。默认的php.ini禁止了一些函数,比如fsocksopen之类的,我给解开了;然后有一些函数没有禁用,比如popen(进程管理,容易被webshell利用执行命令)等,我给禁用了。我的php.ini中的disable\_functions大概是这个样子的(为了看清楚,做了换行处理):

disable\_functions = passthru,exec,system,chroot,chgrp,chown,
shell\_exec,proc\_open,proc\_get\_status,ini\_alter,ini\_set,
ini\_restore,dl,openlog,syslog,readlink,symlink,popepassthru,
stream\_socket\_server,passthru,popen

而另外一些“公认”比较危险的函数,比如opendir,scandir之类的函数,由于有一些特殊需要,就没有禁止了。这样设定起来的参数相对而言比较宽松。

然后就是跨站的问题了。在前一篇文章中提到的LNMP防跨站方法(via LNMP下防跨站、跨目录安全设置,仅支持PHP 5.3.3以上版本)是相当有用的,尤其是在enable_dl=Off和dl被加入disable_functions的时候,要攻破的几率就不很大了。

我对上面文章的一些设定做了一些小小的改动。默认情况下php.ini里是没有限定open_base_dir的。按照上面的方法设定的话,有可能会有某些极端情况(手动编辑vhost让docroot改到其它目录下)导致对目录的open_base_dir限定无效,还在php.ini的[PHP]节加入了这样的设定使它应用到默认的情况下:

open\_basedir = ./:/tmp/

这样在添加了虚拟主机或者修改了路径以后,不会带来潜在的安全隐患。这样处理了以后安全性应该是比原来好一些了。上传了一个phpspy做测试,还算符合要求。

最后要考虑的还有效率问题。说道效率问题就想到了eaccelerator,xcache和memcache(当然还有APC等)。我的习惯是安装eac和mc。但是经过ivmm介绍后,我决定把eac抛弃转而使用xc作为编译缓存,数据缓存保留xcache和memcache两种方式(有的程序只支持其一)。可是不管我怎么折腾,eac,xc,mc还有pdo\_mysql都一直没有办法安装成功。正在无可奈何之际留意到php-fpm重启时的提示消息:

Starting php-fpm Zend Optimizer requires Zend Engine API version 220060519.
The Zend Engine API version 220090626 which is installed, is newer.
Contact Zend Technologies at http://www.zend.com/ for a later version of Zend Optimizer.

本来一直以为这是和php -v一样输出的一些版本号,没有在意。仔细一看才发现这是一条报错消息。到php.ini里查看,才发现因为从php5.2升级php5.3.21后恢复了备份的php.ini,导致Zend Optimizer所加载的还是老版本的ZendOptimizer.so,而不是php5.3.x应该加载的ZendGuardLoader.so(在php5.3之后,Zend Optimizer升级改名为了Zend Guard Loader并且不完全向下兼容)。找到问题根源以后就好办了,把php.ini中的Zend改为正确的名字,重新加入mc和xc的配置文件,重启php-fpm,打开phpinfo,一切正常。上传xcache的管理文件查看,发现命中率还是很高的,可见Xcache还是比较有效的。

版本号的小陷阱

ps.本文所有红色的文字均为错误观点。

首先提出一个问题,php5.3.3和php5.3.21哪个版本高?perl5.1和perl5.01的版本哪个高?

perl中有时候可以看到这么一段代码:

use 5.010

这其中5.010就是perl的版本号。如果写成这个样子呢?

use 5.1

那么这回就不好玩了,perl会认为你要的是5.100,因为perl的版本号是3位小数的。

最近在搭lnmp环境,看到有的文章说PHP5.3.3以上的版本可以支持[HOST=xxx]这样的php.ini写法(via LNMP下防跨站、跨目录安全设置,仅支持PHP 5.3.3以上版本)。于是跑去php官网看,发现最新的php版本才5.3.21。我下意识的觉得,5.3.21要比5.3.3低(php5.3.30>php5.2.21)。于是直接升级到了php5.4.11。可是升级之后,GBK编码的DiscuzX的短消息全部成了空白。于是一脸悲剧的重装php到5.3.21,以为那个防跨站方法无缘了。但是实际测试发现,php5.3.21也能支持那样的写法。

于是这是怎么回事呢?PHP的版本号命名,其实是由3段数字组成的:主版本号、次版本号、发行次数。

因此,php5.3.21的意义是“5.3版本第21个发行版本”,而php5.3.3呢,则是“5.3版本的第3个发行版本”。显而易见的,21>3,所以php5.3.21比php5.3.3新也是理所当然的了,而不能错误的认为,php5.3.3比php5.3.21高

哦,对了,文章前面问题的答案呢?自然是perl 5.1和php5.3.21的版本要高了。

三三精选PHP脚本集之压缩解压

例行吐槽:呐,寒假大礼包之一也许就是这个精选脚本集了。大概会以非常不固定的频率更新一些常用的PHP脚本吧。大部分是可以自由使用的,当然也有来路不明的。嗯,仅供学习使用,版权归原作者所有哈。

作为一个网站管理者,每天和文件打交道是必不可少的。由于众所周知的原因 ,通过FTP上传下载一些零碎的小文件,特别是上传到国外空间,那简直就是灾难。虽然部分面板提供了在线压缩/解压,而且在VPS上压缩/解压也不是一个很大的问题,但是残酷的现实是,并非每个人都有可以压缩/解压的面板,也并非每个人都有VPS。所以,利用一些PHP脚本,能够对压缩文件解压或者将网站文件备份为压缩文件,那简直是太棒了。

这次要介绍的脚本集中收录的一共有三款脚本:phpzip,一个无名的脚本和博主自己写的压缩脚本。它们各有千秋,当然也不是每一个对所有的服务器都支持的,所以需要大家去尝试总结,哪个比较好用什么的。当然,如果试过了这里所有的脚本都没法实现的话,那么你得考虑换一个空间了。

嗯,先给出下载链接。按照我的惯例,分享的文件是放在微软的SkyDrive上的,大家点开链接以后只要点上部的“下载”链接就行了,不需要考虑下面那一大片其它乱七八糟的文件——当然如果你感兴趣的话也可以看看的。不过为了符合国情,还放了一份到百度网盘,大家自己看着办。

SkyDirve:http://sdrv.ms/MMNvDZ

百度网盘:http://pan.baidu.com/share/link?shareid=185587&uk=3340806281

首先是作者不详的压缩解压脚本,姑且叫它“unzipfiles”吧。这个脚本只有两个文件,zipfile.php和unzipfile.php。顾名思义,嗯,一个是解压一个是压缩。

下载到文件后解压缩,找到zip文件处理这个文件夹。两个文件就在这里。打开zipfile.php,找到第四行左右的位置修改密码:

然后对unzipfile.php也同样操作。修改完成后保存,将这两个文件上传到你的空间。(当然,如果只要解压的话上传一个就unzipfile.php够了,压缩亦然。)

上传完成后,使用自己的电脑将要上传的文件压缩成ZIP格式。打包时请选择“添加到压缩文件…”选项,在弹出的对话框中选择ZIP格式:

如果文件比较大,将这个zip文件上传到你的空间。文件不大的话,下一步可以通过浏览器直接上传。需要注意的是,压缩文件本身和里面的内容最好是不要出现中文,否则容易乱码。

上传完成后,来到你上传的脚本页面:http://<your_url>/unzipfile.php进行操作。

在这个简明的页面中,你可以选择服务器上现有的zip文件(前提是和这个文件同目录),也可以上传zip文件。解压目录保持不变即可,验证密码填写上一部你修改的密码,点击解压,服务器就会自动帮你解压这个文件。

解压完成后会有上面的提示信息。去到FTP中,就可以看到刚刚生成的文件了。是的,由于有中文文件名,所以很干脆的乱码了:

压缩也是同样的操作,这里就不再赘述了。

然后就是第二款压缩脚本phpzip了。这款脚本很古老,但是很好用。它分为在电脑上运行的exe程序和在服务器上运行的php脚本两个部分,采用了自己独特的dat格式并搭配gzip压缩,压缩率还不错。

首先将zip.php/unzip.php上传到服务器上,然后通过浏览器访问。页面上方有一段文字,说明你的服务器是否支持zlib库。根据这个提示我们打开phpzip.exe,设置对应的选项进行压缩:

同样,也有本地上传和服务器上传两种方式。压缩后的文件扩展名是dat.gz,很独特。

phpzip主界面上有一个“集成”按钮,点击它以后就可以让phpzip和winrar等压缩软件一样在右键菜单中出现了,如图:

在phpzip目录下还有一个神秘的rm.php文件。这个文件可以帮助我们删除那些在FTP上面无法删除的文件,或者由于文件太多,在FTP上删除需要很久的文件夹。用记事本打开这个文件修改密码,然后上传并在浏览器访问。

只需要填写密码和要删除的路径,提交就会发现文件不见了。

第三款压缩脚本是博主自己写的,只有简单的将当前目录下文件全部压缩的功能,只需要上传然后在浏览器中访问就可以了,不需要其它的操作,这里就不介绍了。

总之,PHP能够帮你减少文件管理的负担,让你的生活更加轻松自在。

百度开发者中心BAE服务收费通知——又一个免费服务的终结

都打算睡觉了,邮箱收到噩耗:

尊敬的开发者,您好, 为了给您提供更加简单可依赖的应用托管服务,防止资源的恶意滥用,百度开发者中心计划于2012年12月25日起,对BAE(百度应用引擎)进行收费。

不过,BAE这次收费不是完全开始收费,还是有一些免费额度的。

具体邮件如下:

Google Apps 客户通知——只有免费,没有永久免费

从今天起,我们不再接受 Google Apps 免费版本(即您当前正在使用的版本)的新帐户注册申请。由于您已经是我们的客户,因此这一更改不会对您的服务产生影响,您可以继续免费使用 Google Apps。

 

Google Apps曾是最受欢迎的免费企业邮箱之一。从一开始的自由服务,提供登录页面和最大用户数目为2000的企业邮箱,到后来取消了登录页面,但是保留了2000用户,然后在09年的时候取消了初始页,也没有了2000用户,变50了。

当年的截图:(2000个用户的样子)

当年的域名1314.fr.cr和2323043.cn呢……有点怀念的感觉。

是2000个用户,很不错的样子,有初始页,各种功能很开放……然后……到了09年的时候,我再申请,已经没有办法申请到2000个用户了。

免费的服务质量终究要降低吧……Google毕竟是商业机构,不是慈善机构嘛……50个用户其实也很够的样子。然而今天……

好吧,好在之前申请的还能用……

simsimi小黄鸡官方API发布 – 别来找我要代码了= =

自从发了两三篇simsimi的API调用以后,我的博客几乎变成了simsimi API的讨论区了OTL

本来就没什么人气,被这么一折腾倒是显得人气旺盛了= =

嗯……前两天和鸟麦说起这件事情来的时候发现小黄鸡都自己发布了官方API了,咱们就别折腾盗用了吧。

详情请戳http://developer.simsimi.com/api

不过呢,这个API需要到http://developer.simsimi.com/contact去申请key。官方说是只能用90天= =,但是,90天以后换个邮箱再申请就是啦=A=

百度应用引擎(BAE)短信服务暂时关闭的通知

亲爱的开发者您好,
       
      为了配合国家相关政策,我们将暂时关闭百度应用引擎(BAE)的短信服务,并进行系统升级。

      非常感谢您一直以来对BAE的支持,我们会尽快完成升级,并为您提供更加优质的服务。给您带来的不便,敬请谅解。
 
 
                                                                                             百度开发者中心

                                                                                             2012年10月25日
 

喜迎**大。

X2审核通过不提醒的解决方法

问题描述:后台审核或删除帖子,用户收不到提醒。分析源代码,发现无理由通过/删除帖子时,系统默认不发送pm。
问题解决:在php处理流程前判断是否有理由。如果没有理由,添加一个默认的理由,这样就可以实现总是发送pm。
解决方法:

需要修改的地方:
/source/admincp/moderate/moderate_thread.php
/source/admincp/moderate/moderate_reply.php
/source/include/modcp/modcp_moderate.php
可能还有moderate/下的其它文件(按照需求来修改)

在moderate_thread.php中查找

    if(isset($_G['gp_'.$pm]) && $_G['gp_'.$pm] <> '' && $thread['authorid']) {

在moderate_reply.php中查找

    if(isset($_G['gp_'.$pm]) && $_G['gp_'.$pm] <> '' && $post['authorid']) {

在上方插入

    $_G['gp_'.$pm] = (isset($_G['gp_'.$pm]) && $_G['gp_'.$pm] <> '') ? $_G['gp_'.$pm] : '感谢您的支持,论坛有您更加精彩!';

在/source/include/modcp/modcp_moderate.php中查找

if($_G['gp_reason'] != '' && $post['authorid'] && $post['authorid'] != $_G['uid']) {

修改为

    $_G['gp_reason'] = $_G['gp_reason']!='' ? $_G['gp_reason'] :'感谢您的支持,论坛有您更加精彩!';
    if($_G['gp_reason'] != '' && $post['authorid']) {

找到

if($_G['gp_reason'] != '' && $thread['authorid'] && $thread['authorid'] != $_G['uid']) {

修改为

    $_G['gp_reason'] = $_G['gp_reason']!='' ? $_G['gp_reason'] :'感谢您的支持,论坛有您更加精彩!';
    if($_G['gp_reason'] != '' && $thread['authorid']) {

注意,每个文件中可能存在多于一个这样的修改点。(前两个文件是两个,最后那个文件是四个)

懒人下载:http://www.ctdisk.com/file/10237915

SQLite中获取随机记录的两种方法以及效率比较

SQLite这个数据库我自己也用的很多。比起mysql它的好处在于不用设置繁琐的host啊username,password,database什么的,直接一个文件上去就好了,类似于Access的方式哈(Access和SQLite能比么~!)。

之前也研究过MySQL上的随机数据获取方法,Google一下一大堆,我就不多说了。总之看了很多MySQL上的文章,SQLite的却没有多少,于是我就自己研究了一下。

我用的环境是Apache/2.2.16 (Win32) PHP/5.2.14,加上PDO的SQLite3接口。还用到一个类库是我自己写的LFPSQlite库,这个库我没有发布过,因为实在是写的太坑了,不想丢丑什么的。

言归正传。今天说的两种获取随机记录的方法,第一种是这样的:

SELECT COUNT(*) FROM 'test';
SELECT * FROM 'test' LIMIT 1 OFFSET #;

其中#是rand(0,$count-1)。

第二种是这样的

SELECT * FROM 'test' ORDER BY random() LIMIT 1;

两种方法的效率究竟如何呢?先来理论分析下。

首先第一种方法是查出数据行数,然后用偏移值来实现读取数据。这两条SQL命令应当是非常快的。第二种方法是用random()排序。虽然有LIMIT 1来限定,但是SQLite应该会将整个表排一次序,那么这个方法就应当比上面慢很多。

具体如何呢?我们来分析一下。我写了一个小脚本,因为用到了我那个没公开的库,所以脚本也就不公开了。我很无聊的把它传到了一个免费空间上,访问地址是:http://jiaowo33.cwsurf.de/sqlite/test.php?times=5 最后那个5可以改成1~200的任意值。用的数据库比较小,只有2W多行。如果你感兴趣可以下载过来看看?在/sqlite/demo.db(406KB)这个位置。

分别执行1,10,100,200次,然后我们来看看程序运行的结果:

信息: 数据库记录数:20915.
信息: 执行1次 COUNT(*)+OFFSET所需时间为0.000886917114258s.
信息: 执行1次OREDER BY RANDOM所需时间为0.0190088748932s.
信息: 效率差值:0.0181219577789s
信息: 执行10次 COUNT(*)+OFFSET所需时间为0.00564503669739s.
信息: 执行10次OREDER BY RANDOM所需时间为0.193027973175s.
信息: 效率差值:0.187382936478s
信息: 执行100次 COUNT(*)+OFFSET所需时间为0.0537490844727s.
信息: 执行100次OREDER BY RANDOM所需时间为1.947660923s.
信息: 效率差值:1.89391183853s
信息: 执行200次 COUNT(*)+OFFSET所需时间为0.105569839478s.
信息: 执行200次OREDER BY RANDOM所需时间为4.20832800865s.
信息: 效率差值:4.10275816917s

效果显而易见。count(*)的执行效率明显比order by random()要高得多。

连接ssh出现Permission denied之一解

问题描述:

在一台centos 6.0的vps上使用ssh无论连接什么样的主机都连接不上,提示信息为:

Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).

排除了防火墙等原因,百思不得其解。后来在man ssh里面发现了一个参数-v

     -v      Verbose mode.  Causes ssh to print debugging messages about its
             progress.  This is helpful in debugging connection, authentica‐
             tion, and configuration problems.  Multiple -v options increase
             the verbosity.  The maximum is 3.

于是使用ssh -v localhost试图连接。在debug信息里面发现一条很奇怪的信息,如下:

debug1: Next authentication method: password
debug1: read_passphrase: can't open /dev/tty: No such file or directory

尝试使用password模式时,没办法调用read_passphrase来获取密码。提示/dev/tty这个文件缺失。

于是在本地的cygwin(我是win环境)下用ls -l /dev/tty得到以下信息:

crw-rw-rw- 1 oott123 None 5, 0 十月  5 14:53 /dev/tty

使用mknod /dev/tty c 5 0来创建一个新的设备文件,故障解除。

后来##Orz的atmouse发现了这个页面,和我遇到的问题一模一样:【这里】,解决方式也是一样的。