月度归档:2013年11月

Apache的DOCUMENT_ROOT坑,第二次踩

现在写代码很多东西可以从以前写的里面拿来重用,有种渐入佳境的感觉。

某系统过两天要交付,我这边在测试各种情况,在测试把系统部署到子目录的时候发现跳转有问题,然后追查到一个自己写的url函数,之前我写的这两个函数用于获取基于web根目录的子目录信息和url。这个东西比较常用,例如要html模板里面要引入css/js等资源的时候,相对路径是个不好的实践,特别是现在各种friendly url之下,相对路径很容易乱套,写绝对路径的话,你得确保部署环境,总归不方便,要是被别人部署到子目录然后你的资源引用路径有前面斜杠的话,dead。

好吧还是先上代码,下面是已经改好的版本。

这两个函数到处都能用,例如在模板里面我会这样用<?php echo get_baseurl()?>/static/css/xxx.css,redirect的时候也可以用。然后回到题目,坑在哪里呢?

坑就在于服务器配置,关于DOCUMENT_ROOT,参看这里,官方文档说DocumentRoot的设定应该不要有末尾斜杠,但是很多wamp傻瓜包(已知wamp、phpnow)的虚拟主机设置都会有末尾斜杠,在计算basedir的时候我用dirname($_SERVER[‘SCRIPT_FILENAME’]) 减去$_SERVER[‘DOCUMENT_ROOT’] 来获取相对web根目录的子目录路径,如果DocumentRoot配置值末尾有斜杠,会直接导致$_SERVER[‘DOCUMENT_ROOT’]末尾有斜杠,然后导致相减之后得到的子目录路径没有前面的斜杠。于是在跟别的东西(例如域名)拼合的时候导致粘结,出来例如abc.comindex.php的效果。

然后今年一月份别的系统已经有人用wamp踩过坑,我才关注到这个问题,但是后来别的项目又直接拷贝这两个函数去用,又一次踩到坑,所以在这里记录一下,现在get_basedir函数增加了前面斜杠的检查,他的行为应该能符合注释描述。

然后最后谈一下斜杠问题,从linux的标准来看,表示文件夹路径都是用的前面有斜杠后面没斜杠的格式(例如pwd看看,或者php的dirname函数)。有时候感觉那样不方便,例如你要拼接一个目录和文件名,你还得目录名 + ‘/文件名’,要自己显式加上前面斜杠。但是其实这样的做法是比较能统一的,都是前有杠后没有杠,表示文件名和目录都能统一,如果改成前后都有杠可能造成目录拼接出现双斜杠,如果前面没有杠后面有杠又变成相对路径。

 

PHP 简单的文件kv cache

之前做一个小东西的时候随手写了下面这样的一个cache函数 [11.5增补]后来加了直接存储而不序列化的参数,之后这个函数就凌乱了,而且糅合读写在一个函数代码可读性也不好,得数参数才知道是读是写,用来存放一些小的信息,可以省掉数据库,kv方式,git风格文件存储,简单序列化变量数据写入文件。

使用起来很简单的,原本这个函数只有两个参数,k和v,后来发现如果想要清除某种特定类型的cache的时候拙计,因为都混在一个文件夹里面了,而跟很多kv的东西一样,不能列出来都有哪些k,所以后面加了第一个参数,分区,就是子目录存放。v留空为读取,v有值为写入,v为null删除。不序列化的选项就相当于简单的以某个key存放原信息,例如图像或者其他二进制、纯文本字符串等。PHP低版本还没有从变量(内存)获取图像的getimagesizefromstring,所以有时候必须传入文件名,而如果这些二进制文件被序列化过,那格式就对不上,而且对这些进行序列化也是没意义的。

PHP & Git 最简单的自动部署

最近比较喜欢用bitbucket,因为要用私有库又不舍得交钱给Github只能这样了,虽然自己也用gitolite搭了git server,但是毕竟仅仅是一个git server。

回到正题,之前的玩法都是开着putty,本地编辑好提交好push上去bitbucket/github,然后putty里面在原地git pull,今天突然想到能不能利用hook简单做个自动部署,稍微看了一下bitbucket的hook文档,bitbucket有个简单的Post Hook(github也有类似的),其实简单的利用这个,都不用出来post过来的关于提交的数据,直接pull就好,于是就有了下面的脚本

然后在仓库的设置那边加个hook,注意看我这里加了简单的http auth,bitbucket是支持的。

这样完事之后发现还不行,因为默认php执行的httpd运行账户是www,一般为了安全都会把web运行账户弄得不能shell登陆(/sbin/nologin或者/bin/false),而且连home目录都没有,为了实现自动部署最好给www一个home,里面要放keys什么的。[11.5补充] 还最好为www用户config一下email和username,不然像bitbucket会说empty ident而无法pull [11.18补充]根据这里,empty ident的问题也可能是因为passwd里面第5个字段为空,最好在第5字段填上东西,是啥不重要

因为httpd什么的都在跑,直接usermod -d肯定说用户已登录改不了,这时候可以用vipw直接修改/etc/passwd,找到没有home(或者home是/dev/null什么的)的可怜的www,给一个home目录给他,shell不用改,保存退出会提示你可以vipw -s来改/etc/shadow保持一致性,这里只改了个home就不必了,后面执行命令可以直接sudo -u www 加命令来以www身份运行。

先sudo -u www mkdir ~/.ssh吧,然后sudo -u www ssh-keygen随便生成个key,不要设置密码,不然git pull困难还得请ssh-agent。生成之后吧id_rsa.pub cat出来加到仓库的部署key,部署key只有只读权限还是挺安全的。

好了之后你可以sudo -u www git pull测试能不能正常pull,能不能pull到,最好这样试一次,因为这里还有个交互是第一次访问要把对方加到known_host里面的,要回答yes,好了之后应该能pull到,web上面的php应该也能调用到git pull并返回信息。这里php后面可以再加别的东西例如针对自动部署的环境做的一些适应性修改、导数据库等工作,注意不要弄出conflict导致下次git pull困难就行。

我喜欢这样随随便便的写,长篇大论的博文我自己都不大愿意看,特别是没干货的东西