老韩
7三/122

FreeBSD8.2上部署Lighttpd+MySQL+Redmine

  本来不想写这样一篇文章,因为实在只是体力活,没有意外的情况下,反复Configure/make/make install即可以顺利完成,可是生活偏偏这么狗血,就在这样一个简单的任务上,我居然为之整整折腾了一天,颇为郁闷,所以还是记录一下。
  先说一下我的环境,硬件是一台自己买零件配的Atom小型机,CPU: Intel(R) Atom(TM) CPU D525 @ 1.80GHz (1810.46-MHz K8-class CPU),内存4G,硬盘是一个从MacBookPro上拆下来的500G硬盘,上面跑着一个FreeBSD8.2(reeBSD dev.0d0f.com 8.2-RELEASE FreeBSD 8.2-RELEASE #0: Thu Feb 17 02:41:51 UTC 2011)系统,采取最简单的安装,外加Lighttpd、PHP、MySQL,组成了我们的测试环境。因为项目接下来的管理的需要,所以打算加一个Redmine。以上是背景。
  作为一个曾经读了一个多月Redmine代码的技术宅,安装这个本来是轻车熟驾的。首选当然是直接RVM安装方案。说干就干,装好RVM之后开始 rvm install 1.8.7,gems也自动安装好了,没有报错,貌似挺成功的。但是接下来就开始了噩梦,首先是Gems在装rails的时候,虽然能够安装成功,但是装不了RDoc,提示是找不到iconv库(gem install rails no such file to load -- iconv),当时觉得没什么,大不了不用Doc呗,只要能跑,于是忽略继续,然而在跑代码的时候却发现依然提示找不到iconv,于是明白这是一个关键的包依赖,忽略不了的。前前后仔细查看了一下系统库,Libiconv好好的呆在/usr/local里,不管怎么加参数,都是不行,联想到FreeBSD的各种变态的安全限制,于是决定抛弃RVM,Root到根目录下直接从源代码编译。
  手动编译比RVM快多了。然而意外的是,安装Rails时依然是提示找不到iconv,这就不对了,翻了一下Google发现这个包居然是由FreeBSD提供而不是由Ruby自带的,只好祭起万能的Ports。

  1. [root@dev]#cd /usr/ports/converters/ruby-iconv/
  2. [root@dev]#make install clean

完了再重新编译Ruby和Gem,还是不行,无奈之下只好不情不愿的编译起FreeBSD的Ports原生包来:

  1. [root@dev]# echo "RUBY_VERSION=1.8.7" >> /etc/make.conf
  2. [root@dev]# cd /usr/ports/lang/ruby18
  3. [root@dev]# make install clean
  4. [root@dev]# cd /usr/ports/devel/ruby-gems
  5. [root@dev]# make install clean
  6. [root@dev]# cd /usr/ports/converters/ruby-iconv
  7. [root@dev]# make install clean
  8. [root@dev]# cd /usr/ports/databases/ruby-mysql
  9. [root@dev]# make install clean
  10. [root@dev]# gem18 install rails --version=2.3.14

这一编译就折腾了一下午各种依赖的包都要编译,比如一个ruby-rmagick库就安装了63个依赖包。安装好了Ruby rails接下来就安装Redmine吧,从rubyforge上拉最新代码来装:

  1. [root@dev]# mkdir /usr/local/www/
  2. [root@dev]# cd /usr/local/www/
  3. [root@dev]# svn co http://redmine.rubyforge.org/svn/trunk redmine
  4. [root@dev]# cd redmine

创建Redmine数据库:

  1. CREATE DATABASE `redmine` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

# 设定Redmine环境

  1. [root@dev]# cp config/configuration.yml.example config/configuration.yml
  2. [root@dev]# cp config/database.yml.example config/database.yml
  3. [root@dev]# vi config/configuration.yml
  4. [root@dev]# vi config/database.yml
  5.  
  6. # 生成session store secret.
  7. [root@dev]# rake generate_session_store
  8.  
  9. # 生成production数据库
  10. [root@dev]# rake db:migrate RAILS_ENV=production
  11. [root@dev]# rake redmine:load_default_data RAILS_ENV=production
  12.  
  13. # 设置目录权限
  14. [root@dev]# find /redmine_docroot/ -type f -exec chmod 644 {} \;
  15. [root@dev]# find /redmine_docroot/ -type d -exec chmod 755 {} \;
  16.  
  17. # 设置目录权限
  18. [root@dev]# mkdir tmp public/plugin_assets
  19. [root@dev]# sudo chown -R redmine:redmine files log tmp public/plugin_assets
  20. [root@dev]# sudo chmod -R 755 files log tmp public/plugin_assets
  21.  
  22. # 启动Redmine
  23. [root@dev]# ruby18 script/server webrick -e production

安装thin:

  1. [root@dev /usr/local]# gem18 install thin
  2. Fetching: eventmachine-0.12.10.gem (100%)
  3. Building native extensions.  This could take a while...
  4. Fetching: daemons-1.1.8.gem (100%)
  5. Fetching: thin-1.3.1.gem (100%)
  6. Building native extensions.  This could take a while...
  7. Successfully installed eventmachine-0.12.10
  8. Successfully installed daemons-1.1.8
  9. Successfully installed thin-1.3.1
  10. 3 gems installed
  11. Installing ri documentation for eventmachine-0.12.10...
  12. Installing ri documentation for daemons-1.1.8...
  13. Installing ri documentation for thin-1.3.1...
  14. Installing RDoc documentation for eventmachine-0.12.10...
  15. Installing RDoc documentation for daemons-1.1.8...
  16. Installing RDoc documentation for thin-1.3.1...
  17.  
  18. 检查thin包是否安装成功:
  19. [root@dev /usr/local]# gem18 list
  20. *** LOCAL GEMS ***
  21. actionmailer (2.3.14)
  22. actionpack (2.3.14)
  23. activerecord (2.3.14)
  24. activeresource (2.3.14)
  25. activesupport (2.3.14)
  26. bundler (1.0.22)
  27. coderay (1.0.5)
  28. daemons (1.1.8)
  29. eventmachine (0.12.10)
  30. i18n (0.4.2)
  31. mysql2 (0.2.18)
  32. net-ldap (0.3.1)
  33. pg (0.9.0)
  34. rack (1.1.3)
  35. rails (2.3.14)
  36. rake (0.9.2.2)
  37. rmagick (2.13.1)
  38. ruby-openid (2.1.8)
  39. sqlite3 (1.3.5)
  40. thin (1.3.1)

创建thin运行配置文件:

  1. [root@dev /usr/local]#thin config -C /usr/local/www/redmine/config/redmine.yml -c /usr/local/www/redmine --servers 1 -e production

确认:

  1. [root@dev]# cat /usr/local/www/redmine/config/redmine.yml
  2. ---
  3. chdir: /usr/local/www/redmine
  4. environment: production
  5. address: 0.0.0.0
  6. port: 3000
  7. timeout: 30
  8. log: log/thin.log
  9. pid: tmp/pids/thin.pid
  10. max_conns: 1024
  11. max_persistent_conns: 512
  12. require: []
  13. wait: 30
  14. servers: 1
  15. daemonize: true

启动thin:

  1. [root@dev]# thin -C /usr/local/www/redmine/config/redmine.yml start
  2. Starting server on 0.0.0.0:3000 ...

写一个脚本放到/usr/local/etc/rc.d下面去,供启动用:

  1. [root@dev]#cd /usr/local/etc/rc.d
  2. [root@dev]#touch thin.rc
  3. [root@dev]#touch thin_init.rc
  4. [root@dev]#vi thin.rc
  1. #!/bin/sh
  2. function_start_jobs(){
  3. printf "Starting thin...\n"
  4.     thin -C /usr/local/www/redmine/config/redmine.yml start
  5. }
  6.  
  7. function_stop_jobs(){
  8.     thin -C /usr/local/www/redmine/config/redmine.yml stop
  9. }
  10. if [ "$1" = "start" ]; then
  11.     function_start_jobs
  12. elif [ "$1" = "restart" ]; then
  13.     function_stop_jobs
  14.     function_start_jobs
  15. elif [ "$1" = "stop" ]; then
  16.     function_stop_jobs
  17. else
  18.     printf "Usage:/usr/local/etc/rc.d/thin {start|stop|restart}\n"
  19. fi
  1. [root@dev]#vi thin_init.rc
  2. #!/bin/sh
  3. /usr/local/etc/rc.d/thin start

修改 lighttpd 配置文件 modules.conf,加入mod_proxy模块:

  1. server.modules = (
  2.   "mod_rewrite",
  3.   "mod_redirect",
  4.   "mod_alias",
  5.   "mod_access",
  6.   "mod_fastcgi",
  7.   "mod_proxy",
  8.   "mod_simple_vhost",
  9. )

给lighttpd配置加上反向代理:

  1. [root@dev]# vi /usr/local/etc/lighttpd/lighttpd.conf
  2.  
  3. $HTTP["host"] == "redmine.handaoliang.com" {
  4.     $HTTP["url"] =~ "^/((images|stylesheets|javascripts|assets)/(.*)$|(favicon\.ico|robots\.txt))" {
  5.         server.document-root = "/usr/local/www/redmine/public/"
  6.     }
  7.  
  8.     proxy.balance = "hash"
  9.  
  10.     proxy.server  = (
  11.         "" =>((
  12.             "host"  =>"127.0.0.1",
  13.             "port"  =>"3000"
  14.         ))
  15.     )
  16. }

重启Lighttpd和thin,应该就可以了。

附Nginx的反向代理配置:

  1. upstream redmine_pass {
  2.     server 127.0.0.1:3000;
  3. }
  4. server {
  5.     listen          80;
  6.     server_name     redmine.handaoliang.com;
  7.  
  8.     root /usr/local/www/redmine/public;
  9.  
  10.         location / {
  11.             proxy_set_header  X-Real-IP  $remote_addr;
  12.             proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
  13.             proxy_set_header  Host $http_host;
  14.             proxy_redirect off;
  15.             proxy_read_timeout 30;
  16.  
  17.                 if (-f $request_filename/index.html) {
  18.                     rewrite (.*) $1/index.html break;
  19.                 }
  20.  
  21.                 if (-f $request_filename.html) {
  22.                     rewrite (.*) $1.html break;
  23.                 }
  24.  
  25.                 if (-f $request_filename.txt) {
  26.                     rewrite (.*) $1.txt break;
  27.                 }
  28.  
  29.                 proxy_pass http://redmine_pass/;
  30.         }
  31. }
23二/116

开源的压力测试工具PyLot

  几天前新开了一个专门介绍国内外优秀开源项目的网站:“秀码趣”(www.showmuch.com),这是写给ShowMuch的稿子。

  一、什么是Pylot:

  Pylot(www.pylot.org)是一款开源的用以测试Web Service性能和扩展性的工具,它运行HTTP负载测试,这对于制定容量计划、确定基准点、分析系统瓶颈以及系统调优都非常有用。在使用过程中,Pylot会发起并发请求(HTTP Requests),检验服务器响应,以及带有相关指标的报表。它通过GUI或者Shell/Console来执行和监视对被测试网站的测试过程。

  Pylot基于Python开发,和著名的Apache压力测试工具ab一样,默认在命令行运行,也可以通过参数触发GUI界面,当然前提是安装了wxPython的。

  二、Pylot如何工作:
  Pylot的使用方法很简单,你只要在一个XML文件里预定义好测试项目的相关参数即可。Pylot通过对得到的内容进行正则表达式匹配以及通过HTTP状态码来验证服务器响应,在测试开始前,你可以通过图行用户界面或者命令行来调整测试参数(如:Agents数量、请求间隔、时间增量以及测试持续时间等),这些设定使得你可以为各种不同的测试场景建立模型,通过Agents向测试服务器发起并发请求,整个测试过程可以实时地监测运行状态以及错误报告。

  三、安装和使用:
  1、安装。
  Pylot的安装非常简单,首先是必须具备Python2.5以上的环境,然后去它的官网下载发行包(当前是1.26版本),如果你对于图形界面有一定的要求,则必须安装wxPython,另外还有两个可选的安装包是NumPy和Matplotlib,都是用来生成图形报表的。
  具体请参考Pylot的官方使用文档:http://www.pylot.org/gettingstarted.html

  2、使用。
  使用很简单,先解压出来,在解压目录下,会看到有一个:testcases.xml文件,先配置一下:
pylot

pylot

  配置好了之后,运行:python run.py -a 5即可以开始进行压力测试,这里参数“-a 5”的意思是:运行5个Agents。

pylot

  测试报表会保存在Result目录下。通过访问results.html可以查看网页版报表。

pylot

  四、简评:
  Pylot有着简洁而优雅的源代码,功能强大,有用户图形界面,可生成友好的测试报表,虽然同样开源的压力测试工具有很多,比如Apache自带的大名鼎鼎的压力测试工具AB,但是作为使用Python编写的专业开源压力测试工具,却是值得关注和学习的。

21二/110

Nginx+PHP+PHPFPM文件类型错误解析漏洞

刚刚接到信息安全部的通知,说是有一台主机存在文件类型错误解析漏洞,吓了一跳。Nginx配置我早就亲自检查了一遍,按说如果有错误类型文件解析会跳转到403才对。但是事实证明还是疏忽大意了。

测试:

curl -I http://www.test.com/images/inbanner_4.jpg/1.php?c=ls

果然得到:
HTTP/1.1 200 OK
Server: nginx/0.8.41
Date: Mon, 21 Feb 2011 07:40:04 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: PHP/5.2.13

这就意味着,黑客可以通过上传图片,在图片中添加可执行代码来获取服务器权限。这对于一个网站来说,是极为可怕的。

解决方法:
修改php.ini将cgi.fix_pathinfo设为0 (注:前面可能有注释符号; 需要删除掉。)
执行php/sbin/php-fpm restart重启。

18九/103

PHP5.3.3小BUG

编译了一下PHP5.3.3,结果Configure时一切正常,却卡在了Make上,出错信息如下:

  1. In file included from /Users/handaoliang/MySoft/src/php-5.3.3/ext/mysqli/php_mysqli_structs.h:57,
  2.                  from /Users/handaoliang/MySoft/src/php-5.3.3/ext/mysqli/mysqli.c:33:
  3. /opt/iapps/mysql/include/mysql/my_global.h:1008: error: duplicate ‘unsigned’
  4. /opt/iapps/mysql/include/mysql/my_global.h:1008: warning: useless type name in empty declaration

根据提示看了一下代码,原来是MySQL为unsigned long这种数据类型定义了一个新名字,而PHP5.3.3没有跟上。
当然也可能是因为我的MySQL版本比较新(mysql-5.1.48),这个我没有去验证过。旧版的MySQL也许没这问题。

vi /opt/iapps/mysql/include/mysql/my_global.h

  1. typedef unsigned long   ulong;        /* Short for unsigned long */

修正方法,编辑php_mysqli_structs.h:
vi ext/mysqli/php_mysqli_structs.h

查找:WE_HAD_MBSTATE_T(应该是在第54行,直接跳到第54行也可以)

  1. 54 #define WE_HAD_MBSTATE_T
  2.  55 #endif
  3.  56
  4.  57 #define HAVE_ULONG 1
  5.  58 #include <my_global.h>

在#include 前面加上一行:#define HAVE_ULONG 1

或者使用Patch:

  1. Index: ext/mysqli/php_mysqli_structs.h
  2. ==========================================
  3. --- ext/mysqli/php_mysqli_structs.h (revision 301474)
  4. +++ ext/mysqli/php_mysqli_structs.h (working copy)
  5. @@ -54,6 +54,7 @@
  6.  #define WE_HAD_MBSTATE_T
  7.  #endif
  8.  
  9. +#define HAVE_ULONG 1
  10.  #include <my_global.h>
  11.  
  12.  #if !defined(HAVE_MBRLEN) && defined(WE_HAD_MBRLEN)

修改之后再make,然后就一切正常了。

3九/101

让iPhone跑得更快,对iPhone进行系统盘瘦身

iPhone有一个Fonts文件夹,是放在系统盘下的,占据了90多M的磁盘空间。对于像Fonts这种不经常替换的文件,完全可以移到别的磁盘,以节约系统盘有限的空间。下面,我们就通过SSH来连接到iPhone,对iPhone进行一次小小的系统盘瘦身。

先看一下fonts文件夹的大小,94M:

  1. handaoliang-iphone:/System/Library/Fonts root# du -lh
  2. 94M     .

再看磁盘空间,发现系统盘已经被占用了89%:

  1. handaoliang-iphone:~ root# df -lh
  2. Filesystem            Size  Used Avail Use% Mounted on
  3. /dev/disk0s1          750M  654M   89M  89% /
  4. devfs                  33K   33K     0 100% /dev
  5. /dev/disk0s2s1         30G  4.9G   25G  17% /private/var

那么首先,我们把/System/Library/Fonts目录拷贝到 /private/var目录下:

  1. handaoliang-iphone:~ cp -r /System/Library/Fonts /private/var

然后把/System/Library/Fonts目录重新命名为/System/Library/Fonts.bak:

  1. handaoliang-iphone:~ mv /System/Library/Fonts /System/Library/Fonts.bak

建立一个软连接,把新的/System/Library/Fonts指向/private/var/Fonts目录:

  1. ln -s /private/var/Fonts /System/Library/Fonts

重新启动IPHONE,如果工作正常,putty重新登录进入iphone。

删掉备份,删除/System/Library/Fonts.bak目录:

  1. rm -rf /System/Library/Fonts.bak

再看系统盘空间,可用空间已经增加到了23%:

  1. handaoliang-iphone:/System/Library root# df -lh
  2. Filesystem            Size  Used Avail Use% Mounted on
  3. /dev/disk0s1          750M  560M  183M  76% /
  4. devfs                  33K   33K     0 100% /dev
  5. /dev/disk0s2s1         30G  4.9G   25G  17% /private/var
   下一页