分类存档: Linux

Linux软件的使用顺序问题

前阵子被某诡异错误纠缠一天,解决了才发现如此简单,又一个被表象蒙蔽的实例。

nginx+php,直接访问浏览器功能正常,页面上通过接口调用后台shell运行php内容则报错找不到数据库,直接后台用php运行shell文件则没问题,修改为nginx用户运行也没问题,运行php -m查看模块加载正常。

开始怀疑是数据库的问题,因为刚出现过因为数据库版本对应不上而编译后无法使用的“段错误”问题,于是又重新编译等等花费不少时间。

中间其他的各种尝试和搜索不说了,最后取得进展的是在浏览器调用shell并输出phpinfo的时候发现参数内容和编译安装的版本对不上,终于发现是原来使用默认配置安装的一份php在作祟(由于版本号一致,一直没有看出来),之后删除除了制定路径的php之外的所有php相关文件,问题解决。

问题原因就是系统的环境设置和用户的环境设置的优先级并不一致,如果是用户的环境则优先使用/usr/bin下的软链接掉用目标php,如果是系统环境则会优先其他路径导致默认安装的php优先权更高,删除之后则继续寻找到/usr/bin下的php。

PHPUnit深入实践

近日在暴风成功推行了PHPUnit,这里记录一下实践的过程和心得。

安装

网上说的安装方法大致有两种,pear安装和自行下载压缩包安装,但是单独使用都不靠谱,两种结合一下就好了。

首先使用pear安装phpunit,具体操作步骤参考http://pear.phpunit.de/ 这是最便捷的取得最新版本并增加好所有依赖的方式。

然后取出runner文件夹中的PHPUnit.php,修改代码执行器目录到php的目录,并改名为PHPUnit,放在/usr/bin/文件夹下。(window用户可以设定path让它可以在环境中被找到)

基类整理

PHPUnit提供框架和数据库测试集成代码,但是封装了的工具并不完全够用,可以根据自己的需求增加一些更加实用的方法和类到基类中,如:

1,phpunit原生并不提供可以使用php数组进行数据库初始化的方式,所以需要一个额外的类去封装phpunit的Dataset方法,做到可以使用数组的方式组织初始数据,毕竟直接写在代码里的数组比额外的xml文件管理起来要方便的多,如:

Array DataSet
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
* 使用数组初始化数据库内容扩展类
* @author wangkepan
*
*/
class StromTest_DbUnit_ArrayDataSet extends PHPUnit_Extensions_Database_DataSet_AbstractDataSet
{
/**
* @var array
*/
protected $tables = array();
/**
* @param array $data
*/
public function __construct(array $data)
{
foreach ($data AS $tableName => $rows) {
$columns = array();
if (isset($rows[0])) {
$columns = array_keys($rows[0]);
}
$metaData = new PHPUnit_Extensions_Database_DataSet_DefaultTableMetaData($tableName, $columns);
$table = new PHPUnit_Extensions_Database_DataSet_DefaultTable($metaData);
foreach ($rows AS $row) {
$table->addRow($row);
}
$this->tables[$tableName] = $table;
}
}
protected function createIterator($reverse = FALSE)
{
return new PHPUnit_Extensions_Database_DataSet_DefaultTableIterator($this->tables, $reverse);
}
public function getTable($tableName)
{
if (!isset($this->tables[$tableName])) {
throw new InvalidArgumentException("$tableName is not a table in the current database.");
}
return $this->tables[$tableName];
}
}

2,对于一些protected 和 private 的方法,需要用反射类修改方法的可读性来对方法进行测试,实现方法参看http://stackoverflow.com/questions/249664/best-practices-to-test-protected-methods-with-phpunit

Reflection
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 取得私有对象方法。需要php版本大于5.3.2
* @param string $className
* @param string $methodName
* @return Ambiguous
*/
protected static function getMethod($className, $methodName)
{
$class = new ReflectionClass($className);
$method = $class->getMethod($methodName);
$method->setAccessible(true);
return $method;
}

3,对框架的初始化类,此处见仁见智,不一定要用类实现,只要达到目的。

框架整合

刚才提到对框架的整合,这里再补充一下对框架测试的心得。

选用框架ZF1.10,Zend的类库中已经对phpunit有了封装支持,这是非常方便的,不过对于版本上的兼容好像有一些问题,所以在DB的pdo初始化部分遇到了一些麻烦,由于Zend_Test_Phpunit_db并没有提供什么额外的功能,而且对于Model的测试DB_Unit已经足矣,故舍弃了集成Zend_Test的DB部分扩展,直接使用DB_Unit。这样做的唯一缺点是无法使用ZF的配置文件取得数据库参数,不过只要稍加修改手动引入各个变量就能达到目的。

框架测试部分择直接集成Zend封装之后的类,增加了对于Zend分发,路由,跳转,返回值路径等各方面页面等级的测试,相当强大,唯一的缺点是不具备数据库测试的功能,所以对于一些web接口类型的测试,显得有点力不从心。

终极整合:分析了一下类库源码,发现DB_Unit的主类和Zend的框架测试类继承的是同一父类,而且双方作为扩展都对通用性进行了处理,两方面也做的是完全不相干的事情,但是php不支持多继承,故用了一个下三滥的方法:拷贝出DB _Unit的主类,修改其父类为Zend框架测试类,自己封装的基类再继承拷贝出来的类,其代码不用做任何修改,则新的基类拥有了DB_Unit和Zend框架测试类的所有功能,可以同时对controller的分发和数据库反应进行测试,而且测试代码可以统一继承同一个基类,功能大大加强。

遗憾

必须拷贝出DB_Unit源码是非常不优雅的,而且可能会给后面的升级带来麻烦,但还未找到很合适的解决方法,也许反射可以做到这样的事情,研究了一下暂时未果。

另外一个比较难受的状态是无法(或未找到方法)对每个测试用例进行单独的数据初始化(虽然每个用例前都会做一次初始化),这就对新加入的测试造成一定的不便,因为需要去判断新加入的一些基础数据会不会对以前的测试造成影响。

第三点就是对controller的实例化比较麻烦(这个应该能解决,需要再深入研究一下zend框架),导致对Action的行为能够掌控,却无法对controller中的一些私有方法进行掌控,测试粒度比较大。

总结

总体来说当前的功能已经完全能够达到单元测试的目的了,虽然依旧存在一些问题,以后也一定会遇到更多问题,只要了解得足够详细,所有都会迎刃而解,钻研、想象力和追求完美的精神都不可缺少。

Apache实现flv视频拖动

此文开始于一个部署前一天才通知的操蛋需求:flv视频播放必须可以托动播放。

本来略有所知,如果需要实现此类功能,必须架设一个流媒体服务器。Red5或者Helix无所谓,比较的麻烦,只有一晚上时间,没任何经验从头架设谈何容易,但是也得硬着头皮架,谁让需求赶到这儿了。

网上搜教程的时候发现有一篇帖子写到nginx可以实现流媒体服务器,写的还是挺靠谱的,正琢磨是不是装个nginx时候突然想到,如果nginx可以,那么已经使用的Apache是不是也可以?搜了一下果然存在~ 虽然帖子不多不过讲述的相当详细,过程也简单得多,使用的还是刚才已经研究了一阵子的flv播放器,不错~ 于是选定方案,一夜的煎熬开始。。。 继续阅读 »

linux记录之一:ssh登录设置小结

淘宝是个好东西,以后内衣裤非山寨CK的不穿了~~

扯远了。。。没时间去村儿里,终于淘宝来了交换机,本子上server版的CentOS终于能上网了。

首先当然是折腾ssh登录,CentOS5.4自带了OpenSSH,所以安装省了,直接vi /etc/ssh/sshd_config修改设置。

下面是需要设置的逐项介绍:

Port 22  #打开 使用22端口

Protocol 2,1 #打开 兼容ssh1,ssh2方式

ListenAddress 0.0.0.0 #打开 监听所有网卡

PermitRootLogin no #为了安全不允许root用户远程登录 只能用su切换角色 注意:用su root可以切换到root用户 但是无法带入环境变量 如果需要带入环境变量用su – root

######

PermitEmptyPasswords no #禁止空密码登录

PasswordAuthentication no #禁止密码登录 取消用户名、密码的登录方式

######

RSAAuthentication yes #是否允许使用纯 RSA 公钥认证。仅用于SSH-1。默认值是”yes”。

PubkeyAuthentication yes #使用公密钥认证方式

AuthorizedKeysFile  .ssh/authorization #设置公钥保存路径

######

必要的设置就是这些 其他的参数说明可以参阅 http://lamp.linux.gov.cn/OpenSSH/sshd_config.html 有详细的说明。

最后service sshd start 服务器设置完毕。

下一步就是怎么设置客户端软件登录,这里其实有些麻烦,每种连接软件都有自己的key生成器,生成的key大相径庭,纵使都是1024位的SSH-2 RSA,内容、格式、长度也都不一样。这就导致了不同连接软件可能需要有不同的公钥密钥。不过服务器上的还算能够统一,经验验证只要把key全部放在一行内就能识别,格式为:

ssh-rsa AAAAAAAAB3NzaC1y……IvOWIGVxUos= rsa-key-20101205

存入.ssh/authorization即可。

初级说明暂时到这里,有更多必要的安全控制稍后补充。

加几句:

ssh软件推荐SSH Secure Shell Client 白色底色和其他软件反差比较小,其实都是黑色底色的比较保护眼睛,不过IDE啊网页啊FTP软件啊全部都搞成黑色的比较困难,一黑一白反而伤眼睛,所以索性都用白的吧。

SFTP软件推荐CuteFTP,很多方便节省时间的设置,而且他们是可以用一套公密钥的happy~,PuTTY暂时不可以。