auto-xhprof PHP自动性能测试工具


auto-xhprof 项目地址: https://github.com/smallfish/auto-xhprof

最近需要对一些PHP应用和底层函数进行一些排错和性能方面的分析,不由得想起xhprof这个小强的利器。

当然也可以按照官方的示例来监控应用或者页面的数据,使用起来还是有点不爽。比如想监控所有访问超过2秒的页面性能情况,或者自动打开/关闭分析,请求url、响应时间等。

随手基于xhprof写了一个扩展小工具。

主要思路如下:

通过修改php.ini中的auto_prepend_file可以预加载auto-xhprof.php,自动打开xhprof功能。 ;php.ini auto_prepend_file = '/path/prepend.php' ; <?php ; include_once '/path/auto-xhprof.php'; ; ?> 

主要功能点有如下:

  • 参数配置是否自动开启xhprof。
  • 参数配置超时的阀值,比如2秒。
  • 保存分析后的数据到MySQL中,供集中统一分析。
  • 数据内容含:请求的URL、相应时间。
  • 支持gearman异步保存数据。
  • 提供封装的xhprof_start/xhprof_end对部分程序进行手动分析。

图一(列表显示):

图二(部分函数显示):

源码文件说明:

auto-xhprof.php 全局加载文件。 auto-xhprof-config.php 全局配置文件,设置MySQL数据库和参数等。 gearman-worker.php gearman后台处理worker进程。 web/ web显示目录,xhprof列表页面和原xhprof展示部分 xhprof_lib/ xhprof库文件。 

——— 扩展安装步骤 ———

  • 编译xhprof.so扩展
% cd <xhprof_source_directory>/extension/ % phpize % ./configure --with-php-config= % make % make install 
  • 修改php.ini中extension,以支持xhprof扩展
[xhprof] extension=xhprof.so xhprof.output_dir= ; 需要有写入权限,可以写/tmp,或者不设置 
  • 从github上下载auto-xhprof,并配置。
1. 非web目录拷贝到系统php include目录下,比如:/usr/include。 2. web目录拷贝到可访问的应用目录下。比如:/var/www/app1/web,前端访问为:http://app1/web/ 3. 修改auto-xhprof-config.php中相应的数据库配置,超时阀值等参数。 

到这里,基本安装和配置结束了,访问web目录可以看到xhprof列表信息。

另外,如果支持gearman扩展的话,需要在php.ini中启动该扩展,并在auto-xhprof-config.php中配置:

define('__XHPROF_GERAMAN_SERVERS', '127.0.0.1:4730;127.0.0.1:4730'); // gearman 服务器定义 % gearmand -vvv -q libdrizzle --libdrizzle-host=127.0.0.1\ --libdrizzle-user=root --libdrizzle-password=123456 --libdrizzle-db=gearman\ --libdrizzle-table=queue --libdrizzle-mysql % php gearman-worker.php 

You should probably follow @smallfishxy on Twitter

supervisor – Python进程管理工具


经常会碰到要写一些守护进程,简单做法放入后台:

shell> nohup python xxx.py & 

偶尔这么做还可以接受,如果一堆这样的呢?

当然还有一个问题,就是各种服务,对应的命令或者路径都不太一致,比如Apache、MySQL或者其他自行编译的工具。

如果可以统一管理这些应用,是不是很哈皮?

按照惯例现Google一把,不失所望找到一个神奇的利器。supervisor!

supervisor地址:http://supervisord.org,官方标语就是:一个进程管理工具。

安装:

shell> sudo aptitude install supervisor # pip/easy_install 

也可以通过其他包管理来安装,比如apt/yum等。

安装好以后,有两个可执行文件和一个配置文件(平台差异,可能路径不一致):

/usr/bin/supervisord -- supervisor服务守护进程 /usr/bin/supervisorctl -- supervisor服务控制程序,比如:status/start/stop/restart xx 等 /etc/supervisor/supervisord.conf -- 配置文件,定义服务名称以及接口等等 

下面来一个示例,用web.py写一个hello的程序:

import web urls = ( '/(.*)','hello' ) app = web.application(urls, globals()) class hello: def GET(self, name): return 'hello: ' + name if __name__ == '__main__': app.run() 

这个时候可以直接启动这个程序了,下面来配置supervisor,加入管理。修改supervisord.conf,加入如下片段:

[program:hello] command=python /home/smallfish/hello.py autorstart=true stdout_logfile=/home/smallfish/hello.log 

上面的意思应该很容易懂,program后面跟服务的名称,command是程序的执行路径,autorstart是表示自动启动,stdout_logfile是捕获标准输出。

到这里,基本搞定了,下面就是启动管理:

shell> sudo /etc/init.d/supervisor start -- 启动supervisor服务 shell> sudo supervisorctl status hello -- 获取hello服务的状态,因为是autorstart,这里已经启动了 hello RUNNING pid 1159, uptime 0:20:32 shell> sudo supervisorctl stop hello -- 停止hello服务 hello: stopped shell> sudo supervisorctl stop hello -- 再次停止hello,会有错误信息 hello: ERROR (not running) shell> sudo supervisorctl start hello -- 启动hello服务 hello: started 

OK,基本的操作就是类似这个了,仔细看supervisord.conf文件里会发现有一段[unix_http_server]的配置,默认是9001端口,可以输入用户名和密码,主要用于Basic Auth认证用的。

填写一下,然后重启supervisor服务,打开浏览器输入:http://localhost:9001,如图:

pythonbrew – Python多版本管理利器


相信不少人在自己机器上有多个Python版本,我的机器上Python有四个版本:2.5.x、2.6.x、2.7和stackless。

测试Google App Engine时候需要切换到2.5,正式调试时候回归到2.6,自己玩的时候会选择2.7或者stackless,每次都是通过bash profile来调整,或者手动加link。真麻烦那。。。

无意间看到有一个Perl版本的brew工具:perlbrew,可以自由选择Perl版本,很是羡慕,遂想自己动手写一个类似的,可以根据参数修改profile,加载合适的Python版本。动手之前很明智的Google了一把,果然,有人先一步搞定:pythonbrew

安装:

$ easy_install pythonbrew
$ pythonbrew_install

# 或手动下载
$ curl -kLO http://github.com/utahta/pythonbrew/raw/master/pythonbrew-install
$ chmod +x pythonbrew-install
$ ./pythonbrew-install

把 source /xxx/.pythonbrew/etc/bashrc 加入到自己profile或者bashrc中去(xxx是自己的用户目录)

pythonbrew 常用命令如下:

install 安装版本:

$ pythonbrew install 2.6.6
过程可以参考安装日志:~/.pythonbrew/log/build.log
如果最后看到make error失败,应该是test过程失败。可以采取:
$ pythonbrew install --force 2.6.6

switch 选择版本:

$ pythonbrew switch 2.6.6

list 查看版本:

$ pythonbrew list       # 列出目前已安装的版本
pythonbrew list -k  # 列出可以下载和安装的版本

uninstall 卸载版本:

$ pythonbrew uninstall 2.6.6

参数还是很简单的。详见help或者pythonbrew

tornado 自动加载(autoreload)


自动加载主要用于开发和测试阶段,要不每次修改,都重启tornado服务,太囧。

tornado源码有autoreload模块。参考:autoreload.py

可以看到一个私有方法:_reload_on_update,其实只要引入这个模块,调用它即可。示例如下:

import tornado.autoreload
def main():
    server = tornado.httpserver.HTTPServer(application)
    server.listen(8888)
    instance = tornado.ioloop.IOLoop.instance()
    tornado.autoreload.start(instance)
    instance.start()

这样还是很麻烦,或者通过option参数来选择是否autoreload。偶然查看其 web.py 1000多行有这么一句:

        # Automatically reload modified modules
        if self.settings.get("debug") and not wsgi:
            import autoreload
            autoreload.start()

这个是读取Application里settings是否有debug变量,有则调用autoreload。简化后代码如下:

 settings = {'debug' : True}

 application = tornado.web.Application([
     (r"/", MainHandler),
     ], **settings)

def main():
    server = tornado.httpserver.HTTPServer(application)
    server.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

 

2010 – 继续前行的路上


每一天都在前行的路上,而这一年似乎去的特别的快,特别的短暂。

一年的时间辗转三个城市,从南京到杭州,再到上海。一切的一切似乎都是昨天,那般的清晰。

其实很早就想离开工作快五年的公司,只不过是自己一直下不了决心。性格和患得患失一直左右着自己的思绪。时间的流逝,青春不再,或许再过些时间,或许什么都不是了。

偶然的机会,很荣幸的进入淘宝工作。能够从自己的小圈子走出来,去接触外面的世界。短短的几个月中,成长的内容明显的超过了前几年的积累。这不仅仅是技术的成长,更多的是人,是视野,是想法。这一切的一切,都得感谢淘宝的师兄和主管。回想前几年,自己的世界里只有去完成一些事情,而现在更多的是应该觉得自己主动解决一些事情。当然,沟通上面来的更为明显。程序久了,思维的方式都会定死,而接触其他的岗位,去了解他们人的思路和想法,很多思绪都会豁然开朗。

杭州之行匆匆而逝,来到了大上海,这个充满魔力和摩登的都市。说真的,自己尚未体会。换了新环境,适应是必须的。在试用期内很快直接切入项目,几个月很快过去了。虽然在一些问题上自己不能决定什么,但是还是很幸运,可以从项目最初的雏形,到现在已经测试发布,自己都在其中。其实这个正是自己所擅长的。我想的就是自己能够决定更多,能够参与的更多,当然,或许这个可能性还需要自己去努力,或许现实总是那般无力,或许。

一年的流水账,想说,并不容易。希望自己一直能够如此前行,走自己的路,知道自己需要什么,能够得到什么。足矣。

零点的钟声已过,回忆这一年,许许多多的人,给了自己很多很多的帮助,感谢一下。

何伟平:很感谢何老师的推荐,才能有机会进入淘宝这样的大公司。何老师的谦虚和热心,很值得自己去学习。很遗憾,至今未有机会请何老师吃顿饭。

康伯:在淘宝时候我的主管。很感谢他跟自己多次的交流,有想法就说,就交流。给了自己很多机会。他是我至今为止唯一一个在系统方面很膜拜的人。

大舞:淘宝入职时候的师兄。试用期内给了自己很多建议和指导,一个很帅很帅的男人。@kemin_ukl

春哥:非芒果台的那位。感谢春哥推荐了自己来盛大,还混了不少饭,春哥工作和生活的太多很值得码农学习和借鉴。@mcspring

道神:灰常牛叉的DD,感谢刚来魔都时候收留了俺这个码农。回头还要多搭讪,求其在Debian方面的经验。@lidaobing

群众:鄙人群里那些哥们,你们都是神一样的男人!因为有了你们,才有了欢乐!@marchliu @xiaoxiaolu @guangfengio 等等大牛们。

话不多说,祝愿那些把帮助和关心过我的人,新年能够身体健康,幸福快乐!

去迎接新的一年,我,继续在路上。

 

互联网产品与技术的那些杂事儿


杂谈一下,我不是搞产品的也不是搞技术的,只是一个打杂的。随便扯谈一下。

作为一个产品,既然有这个名称,必定有其定位。在构思之前,就必须有明确的针对人群。比如是针对年轻人(80、90),抑或者上班族等等。模糊与笼统的定位,带来的只是无谓的“探索”。定位不是靠摸索出来的,也不是磨打出来的,是在你的脑海里,在你的产品里。即使现在模仿风气如此浓厚的时候,需要的也是定位。你的定位在哪儿,注定成就怎样的结果。

有了想法,下面就是一些调查和思考。你的这些针对人群在你的产品你会喜欢什么,会怎样的习惯?这个时候需要做的就是多和你的目标与非目标受众多去聊天,多去发觉他们的喜好与需求。或许你的改动只在某时一句话。所谓的走出去,这一步是必须的。闭门造车,最后可能出来就是一个自个儿意淫的杯具。

初期的实现与原型。很多时候喜欢在白板或者纸上写点什么,画点什么。记住!这一些都不能丢弃,或者擦掉。或许只是一些顺手涂鸦,或者解乏的简笔画。原型设计不需要一个完整的流程图,应该突出其顺序和关键点,以及部分UI的展示。这个过程中可以适当让受众面参与进来,设计出非自己主观的思路。

好吧,其实这些过程是可以修改和整合的。毕竟咱写的是互联网应用,不会给你完整的需求文档,完整的流程图,那样还叫互联网么?那是外包(无贬义,含笑)。

到现在为止应该糅合一些技术的关键字,比如哪些可以做到,哪些比较复杂。哪些技术可取,哪些可以折中。在考虑这个阶段的时候,技术人员需要的更多的是倾听,而不是纠结在某个环节,或者抵制某些习惯与思路。你可以说下自己的观点与想法,但是记住这些只是你自己的主观出发点,代表不了什么(如果正好受众面就是你,那恭喜了!)。需要做的就是记录下需求,转为脑海中虚拟的实现与流淌。一切心中有谱之后,可以适当“讨价还价”。毕竟每个人说出的都是自己的想法。

该画出流程图了。和上面原型一样,记住,别随意擦掉。用小人也可以,用箭头也可以,或者圆圈。你描述的只是过程,不是漫画和小说。当然加上这些元素会显得你的设计更加有爱。流程图的初衷在于走通整个流程,以及画出关键点。大致抽象出各个模型、结构和交互情况。适当写些文档把,这个总没有坏处的。或许这就是设计文档的初稿。

选型。有了需求,有了流程。下面当然是选择怎么去实现。说到用什么,仁者见仁,智者见智。啥好?啥不好?不是道听途说。关键在于自己。这些年来,喜欢的一句话就是:用自己熟悉的、用自己顺手的。看看外面的世界,好东西太多了,难不成有兴趣什么都来用一下?清醒吧哥们。你不是科学家,不是搞研究的。有这个时间,完全可以把你自己熟悉的搞的更透彻。这里并不是抵制新的或者好的工具,要明白一点,这些工具的作用域在哪儿,如果对自己实在可能起不到啥作用,或者只是存在你的假想中,放放把。未来再尝试也不迟。

关键点的实现与雏形。套句时髦的话,这个是不是应该算架构和设计?抽象出大致的模块,划分出结构。不必太在意其完整性和准确性,只要能走通就好。一次都给你写完了,其他人都去喝茶看报纸?雏形嘛,你懂得。当然,还得明确具体的工具,比如语言、数据库、系统等等。一个准则:用自己熟悉的,外加一条:简单就好。

是不是有了大体的架子了?可能下面就是大工作量的体力活啦。当然,分配体力活也是一个很体力的事情。没有一个好的管理者,这个产品就是大家拆东墙补西墙,互相推诿的产物。大致的职责有:传承需求和变化,分配与监察。消化和理解需求,确实是个跟天赋有关的事情,如果都是一个顺序跑下来的,那也不叫互联网了。需要很好的沟通能力,纸面或者口头的描述,随时可能千变万化,一成不变,继续去做外包把(囧)。分配这个环节就跟经验有关了,多去发觉你团队中的兴趣与擅长,用其长处,适当补短。合适的人干合适的事情,嘛效率?这就出来了。大家都在干活,进度就需要自己不断的监控与调整,适当多给自己宽裕的时间,哪怕只是那么一两小时。凡事没绝对,多想,多看,总是对的。

实现。设计数据库,写类库,写页面。详细罗列的话估计一长串。然后就是拆分逻辑,拆分页面,拆分功能点,然后就是与之对应的整合和补充。说到这边,可能就有人会说,用某某类库,或者某某框架,某某工具。这一切都建立在对其了解的基础上。不要太迷信,同样的刀在不同人手上是不一样的,用的好才是好刀,用不好连茅草都不如。折腾的滋味自己尝把。不是用了啥就牛逼,而是解决了啥,针对性的解决才是牛逼的关键。所有的一切,都只不过是实现的一种手段。条条大路,都可以。不要太迷信××,那只是一个传说。没有万能的实现,只有不断的解决与重新审视。实现细节滤过。。。

测试。不是写几个TestCase就是测试,那个只是证明你的代码看起来没啥问题,当然也不仅仅是用了啥测试框架,多专业。都只是辅助工具。除去功能性的测试,需要的是注意细节上。如果仅仅只是能用,没错没bug。这个不是产品,或许就是留言版。当然应该提供更多的可用性、流畅性以及体验。

唉,一不小心快十二点了,洗洗睡吧。未完再补充。

 

Pylons 入门实例教程 – 发布应用


前面几篇教程简单讲述了如何使用 Pylons 进行 WEB 方面开发的步骤,包括简单的 Hello、表单和数据库操作等内容。本篇将描述一下如何在正式环境中发布基于 Pylons 的 WEB 应用。

测试环境:Nginx 0.8.53 + FastCGI 模式 (需要安装 flup 模块)

pip install flup
# easy_install -U flup

测试代码,延用前面的 Hello 示例。

mac:python smallfish$ paster create -t pylons hello
mac:python smallfish$ cd hello/
mac:hello smallfish$ paster controller hi
mac:hello smallfish$ paster serve --reload development.ini

确保以上过程无错,访问:http://127.0.0.1:5000 可以看到默认页面。

好把,开始配置发布环境。
需要修改 development.ini 配置文件,找到 [server:main] 节点,修改其中的 use 方式(默认是 egg:Paste#http)。

[server:main]
use = egg:PasteScript#flup_fcgi_thread
host = 0.0.0.0
port = 5000

另外建议修改 [DEFAULT] 节点中 debug = false,以免错误会打印具体的环境和堆栈信息。

到这里 Pylons 部分以及设置好了,如果出现一下错误:

LookupError: Entry point 'flup_fcgi_thread' not found in egg 'Paste'

请注意上面的 use 部分里是 PasteScript 而不是 Paste哦。淡定淡定,别光看后面的 http 改成 flup_fcgi_thread。

下面修改 Nginx 的配置 nginx.conf,修改其中 / 部分设置。

        location / {
            fastcgi_pass   127.0.0.1:5000;
            fastcgi_index  index;
            fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            include        fastcgi_params;
            fastcgi_intercept_errors off;
        }

其中 fastcgi_pass 中 host 和 port 对应 development.ini 中的配置。

好把,这里可以启动,看看是否正确,请注意相应的目录。

启动 Pylons 部分(启动 daemon 进程,或参考搜狐邮箱使用的 zdaemon 来管理进程):

mac:hello smallfish$ paster serve --reload development.ini  --daemon start
# 注意,正式环境中请去除 reload 参数
# daemon 后面参数有 start | stop | restart | status,可以很方便的管理进程

启动 Nginx 部分:

mac:~ smallfish$ sudo /opt/nginx/sbin/nginx

尝试一下访问: http://localhost/ 和 http://localhost/hi/index 。是不是都可以了?OK,到这里已经整合好了。

这里是采用 FastCGI 方式发布,当然还可以用默认 http 或者本地 socket 方式,然后通过 proxy_pass 方式转发过去也是可以的。

当然,这个只是简单示例,可能正式发布时候需要注意的事项比这个复杂的多。这里只是介绍一种方式而已。

希望通过这一系列的教程,希望能对喜欢 Python 和关注 Pylons 框架的朋友能有所帮助。

前几篇链接分别如下:

1. Pylons 入门实例教程 – Hello
2. Pylons 入门实例教程 – 表单和文件上传
3. Pylons 入门实例教程 – 数据库操作
4. Pylons 入门实例教程 – cookie 和 session

 

PostgreSQL Key-Value 数据类型 hstore 使用教程


现在满地都是KV数据库的文字,PostgreSQL 也有类似的结构。不过是通过其强大的扩展方式实现的。

官网文档请参考:http://www.postgresql.org/docs/current/static/hstore.html

本文测试环境在 Mac OS 下,Pg采用源码编译。

编译 hstore 扩展

mac:~ smallfish$ cd Downloads/postgresql-9.0.1/contrib/hstore/
mac:hstore smallfish$ make
... 一堆编译信息
mac:hstore smallfish$ sudo make install

导入到数据库中,注意必须以 postgres 用户,如果需要装入到指定数据库,请指明。这里采用默认数据库。

mac:hstore smallfish$ ls /opt/postgresql/share/contrib/
hstore.sql		uninstall_hstore.sql
mac:hstore smallfish$ psql -U postgres -f /opt/postgresql/share/contrib/hstore.sql
... 一堆导入命令

进入数据库,建一个测试表

postgres=# CREATE TABLE testhstore (id SERIAL, value hstore);
NOTICE:  CREATE TABLE will create implicit sequence "testhstore_id_seq" for serial column "testhstore.id"
CREATE TABLE

查看下表结构

postgres=# \d
                List of relations
 Schema |       Name        |   Type   |  Owner
--------+-------------------+----------+----------
 public | testhstore        | table    | postgres
 public | testhstore_id_seq | sequence | postgres
(2 rows)

postgres=# \d testhstore;
                         Table "public.testhstore"
 Column |  Type   |                        Modifiers
--------+---------+---------------------------------------------------------
 id     | integer | not null default nextval('testhstore_id_seq'::regclass)
 value  | hstore  |

尝试下简单 hstore类型

postgres=# select 'a=>1, b=>2'::hstore;
       hstore
--------------------
 "a"=>"1", "b"=>"2"
(1 row)

postgres=# select 'a=>1, b=>a'::hstore;
       hstore
--------------------
 "a"=>"1", "b"=>"a"
(1 row)

写几条测试数据先

postgres=# INSERT INTO testhstore (value) VALUES ('name=>smallfish, age=>29'::hstore);
INSERT 0 1
postgres=# SELECT * FROM testhstore;
 id |              value
----+----------------------------------
  1 | "age"=>"29", "name"=>"smallfish"
(1 row)

postgres=# INSERT INTO testhstore (value) VALUES ('name=>nnfish, age=>20'::hstore);
INSERT 0 1
postgres=# INSERT INTO testhstore (value) VALUES ('name=>aaa, age=>30, addr=>China'::hstore);
INSERT 0 1

查看下所有数据

postgres=# SELECT * FROM testhstore;
 id |                    value
----+---------------------------------------------
  1 | "age"=>"29", "name"=>"smallfish"
  2 | "age"=>"20", "name"=>"nnfish"
  3 | "age"=>"30", "addr"=>"China", "name"=>"aaa"
(3 rows)

查询列里面的指定 key

postgres=# SELECT id, value->'name' AS name FROM testhstore;
 id |   name
----+-----------
  1 | smallfish
  2 | nnfish
  3 | aaa
(3 rows)

postgres=# SELECT id, value->'name', value->'age' AS age FROM testhstore;
 id | ?column?  | age
----+-----------+-----
  1 | smallfish | 29
  2 | nnfish    | 20
  3 | aaa       | 30
(3 rows)

修改列某 key 值

postgres=# UPDATE testhstore SET value=value||('addr=>Shanghai') WHERE id = 2;
UPDATE 1

postgres=# SELECT * FROM testhstore;
 id |                       value
----+---------------------------------------------------
  1 | "age"=>"29", "name"=>"smallfish"
  3 | "age"=>"30", "addr"=>"China", "name"=>"aaa"
  2 | "age"=>"20", "addr"=>"Shanghai", "name"=>"nnfish"
(3 rows)

删除列里某 key

postgres=# UPDATE testhstore SET value=delete(value, 'addr') WHERE id = 3;
UPDATE 1

postgres=# SELECT * FROM testhstore;
 id |                       value
----+---------------------------------------------------
  1 | "age"=>"29", "name"=>"smallfish"
  2 | "age"=>"20", "addr"=>"Shanghai", "name"=>"nnfish"
  3 | "age"=>"30", "name"=>"aaa"
(3 rows)

按条件查询列里某 key ,注意要数据类型,CAST 强转。默认都是字符串的值。

postgres=# SELECT * FROM testhstore WHERE (value->'age')::INT > 20;
 id |              value
----+----------------------------------
  1 | "age"=>"29", "name"=>"smallfish"
  3 | "age"=>"30", "name"=>"aaa"
(2 rows)

postgres=# SELECT * FROM testhstore WHERE value->'name' = 'smallfish';
 id |              value
----+----------------------------------
  1 | "age"=>"29", "name"=>"smallfish"
(1 row)

 

开源网页截屏工具 CutyCapt Linux 下安装和使用


目的是想在服务器端生成某个网页的缩略图。Google了好久,发现一个好开源东西:CutyCapt。

系统:CentOS 5.5
官网:http://cutycapt.sourceforge.net/
依赖:QT http://www.qtsoftware.com/

首次是在Debian下测试的,很顺利。换了CentOS不是太爽。具体安装和使用步骤如下:

1. 下载RPM包

(64位)
wget http://dl.atrpms.net/el5-x86_64/atrpms/testing/qt44-4.4.3-10_4.el5.x86_64.rpm
wget http://dl.atrpms.net/el5-x86_64/atrpms/testing/qt44-x11-4.4.3-10_4.el5.x86_64.rpm
wget http://dl.atrpms.net/el5-x86_64/atrpms/testing/qt44-devel-4.4.3-10_4.el5.x86_64.rpm

(32位)
wget http://ftp.riken.go.jp/Linux/atrpms/el5-i386/atrpms/testing/qt44-4.4.3-10_4.el5.i386.rpm
wget http://ftp.riken.go.jp/Linux/atrpms/el5-i386/atrpms/testing/qt44-x11-4.4.3-10_4.el5.i386.rpm
wget http://ftp.riken.go.jp/Linux/atrpms/el5-i386/atrpms/testing/qt44-devel-4.4.3-10_4.el5.i386.rpm

2. 安装 qt-devel 依赖包

yum install libXi-devel
yum install libXinerama-devel

3. 安装 qt 相关

rpm -ivh qt44-4.4.3-10*
rpm -ivh qt44-x11-4.4.3-10*
# rpm -e qt-devel --nodeps --allmatches
rpm -ivh qt44-devel-4.4.3-10*

4. 修改 /etc/profile,最后并:source /etc/profile

export QTDIR=/usr/lib64/qt44
export QTLIB=/usr/lib64/qt44/lib
export QTINC=/usr/lib64/qt44/include
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
export PATH=$QTDIR/bin:$PATH

5. 安装 cutycapt

svn co https://cutycapt.svn.sourceforge.net/svnroot/cutycapt
mv cutycapt/CutyCapt /usr/local/CutyCapt
cd /usr/local/CutyCapt
qmake
make

6. 安装模拟 x-server 服务端

wget http://www.flexthinker.com/wp-content/uploads/2009/11/xvfb-run.sh.txt
mv ./xvfb-run.sh.txt /usr/local/CutyCapt/xvfb-run.sh
chmod u+x /usr/local/CutyCapt/xvfb-run.sh

7. 开始欢快的截图吧

/usr/local/CutyCapt/xvfb-run.sh --server-args="-screen 0, 1024x768x24" /usr/local/CutyCapt/CutyCapt --url=http://www.163.com --out=163.jpg

8. 如果看不到汉字或乱码,需要安装chinese字体

yum install fonts-chinese

9. 由于截屏的是整个网站的页面,只需要第一屏幕

convert -crop 1024x768+0+0 163.jpg 1632.jpg

10. 缩小图片

convert -resize 40%x40% 1632.jpg 1632.jpg

Python Story


http://www.slideshare.net/nnfish/python-story


http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=pythonstory-100920035248-phpapp01&stripped_title=python-story&userName=nnfish

加关注

Get every new post delivered to your Inbox.