存档在 ‘服务器技术’ 分类

[HOW TO] complie intl extension for php 5.3.2 under Mac OS X 10.6

2010年12月29日

近期我在研究 Symfony2,这是一个全新的、个人认为很有前途的 php 框架。和 Symfony 1.x 相比基本是推倒重来的一个版本,官方号称这是这是最快的 php 框架之一。具体可以自己上官方网站看看。

然而 Symfony2 要求 php 5.3.2+ 以上版本,还需要 php intl 库,而 Mac OS X 10.6 默认自带的 php 没有 intl 扩展,我只好自己安装。php 扩展嘛,最方便的安装方法莫过于用 pecl 安装了,然而:

$ sudo pecl install intl
downloading intl-1.1.2.tgz ...
...
/usr/temp/intl/collator/collator_class.c:92: error: duplicate ‘static’
/usr/temp/intl/collator/collator_class.c:96: error: duplicate ‘static’
/usr/temp/intl/collator/collator_class.c:101: error: duplicate ‘static’
/usr/temp/intl/collator/collator_class.c:107: error: duplicate ‘static’
make: *** [collator/collator_class.lo] Error 1
ERROR: `make' failed

Google 了一番,没什么结果,好多人在问这个问题,但就是没有一个的解决方法。

那就自力更生吧,经过一番“研究”,发现原来是 php 5.3 的使用了新的内存回收方式,zval 结构体也和 php 5.2 不一样了,一些宏也改变了,ZEND_BEGIN_ARG_INFO_EX 这个宏在 php 5.2 是这样的:

#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \
    zend_arg_info name[] = { \
        { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },

在 php 5.3 下是这样的:

#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args)   \
    static const zend_arg_info name[] = {                                                                       \
        { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },

而 intl 1.1.2 中很多地方都用到了这个宏,比如上面出错的 collator/collator_class.c 文件:

static
ZEND_BEGIN_ARG_INFO_EX( collator_0_args, 0, 0, 0 )
ZEND_END_ARG_INFO()

看见没有,php 5.3 中 ZEND_BEGIN_ARG_INFO_EX 的定义中已经那个包含了一个 static 关键字,而 intl 1.1.2 中用到这个宏的地方还是按照 php 5.2 的方式使用,这个宏经过预处理后,导致出现 static 关键字重复,编译出错。 知道了问题原因,就试着修改下吧。由于 intl 1.1.2 库中是用这个宏的地方很多,不好一个一个该,我就用了一个邪恶的方法,在 intl_common.h 中重新定义这个宏:

// HACK!!!
#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args)   \
    const zend_arg_info name[] = {                                                                      \
        { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },

保存再编译,这次上面的那个错误没有了,但出现了别的错误:

/Users/liang/apps/intl-1.1.2/resourcebundle/resourcebundle_class.c:215: error:‘zval’ has no member named ‘refcount’;
make: *** [resourcebundle/resourcebundle_class.lo] Error 1

这个就是上面说的 zval 结构体的改变了。php 5.3 使用了新的 GC 方式,zval 结构体中的 refcount 成员改名为 refcount__gc,is_ref 改名为 is_ref__gc,而且也有配套的管理这个新成员的宏。经过研究,intl 1.1.2 中只有 3 个地方使用 php 5.2 的方式直接访问了 refcount 成员:

$ grep -r refcount *
msgformat/msgformat_format.c:#define Z_ADDREF_P(z) ((z)->refcount++)
msgformat/msgformat_format.c:       /* TODO: needs refcount increase here? */
resourcebundle/resourcebundle_class.c:  retval->refcount--;
resourcebundle/resourcebundle_iterator.c:   object->refcount--;
resourcebundle/resourcebundle_iterator.c:   object->refcount++;

其中 msgformat/msgformat_format.c 文件已经和 php 5.3 兼容了,所以只需要修把后面的三个地方修改为 php 5.3 的方式,那这个错误应该就修改好了。 修改方法很简单,分别打开上面的几个 resourcebundle/resourcebundle_class.c 文件和 resourcebundle/resourcebundle_iterator.c 文件,按照下面的方式修改:

retval->refcount--;     => Z_DELREF_P(retval);
bject->refcount--;      => Z_DELREF_P(object);
object->refcount++;     => Z_ADDREF_P(object);

完成后重新编译,OH YEAH~~~~能通过编译了。不过别高兴得太早,可能还有问题呢。先修改一下 php.ini 中的 intl 配置为:

[intl]
intl.default_locale = zh-CN

然后运行一下测试自带的测试用例,发现有很多测试用例没通过。。。 :-(

$ make test
=====================================================================
TEST RESULT SUMMARY
---------------------------------------------------------------------
Exts skipped    :    0
Exts tested     :   55
---------------------------------------------------------------------
Number of tests :   78                78
Tests skipped   :    0 (  0.0%) --------
Tests warned    :    0 (  0.0%) (  0.0%)
Tests failed    :   17 ( 21.8%) ( 21.8%)
Expected fail   :    0 (  0.0%) (  0.0%)
Tests passed    :   61 ( 78.2%) ( 78.2%)
---------------------------------------------------------------------
Time taken      :   10 seconds
=====================================================================

=====================================================================
FAILED TEST SUMMARY
---------------------------------------------------------------------
get_locale() [tests/collator_get_locale.phpt]
collator_get_sort_key() [tests/collator_get_sort_key.phpt]
datefmt_get_pattern_code and datefmt_set_pattern_code() [tests/dateformat_get_set_pattern.phpt]
datefmt_localtime_code() [tests/dateformat_localtime.phpt]
datefmt_parse_code() [tests/dateformat_parse.phpt]
datefmt_parse_localtime() with parse pos [tests/dateformat_parse_localtime_parsepos.phpt]
datefmt_parse_timestamp_code()  with parse pos [tests/dateformat_parse_timestamp_parsepos.phpt]
datefmt_set_timezone_id_code() [tests/dateformat_set_timezone_id.phpt]
numfmt_format() [tests/formatter_format.phpt]
numfmt_format_currency() [tests/formatter_format_currency.phpt]
grapheme() [tests/grapheme.phpt]
locale_get_display_name() [tests/locale_get_display_name.phpt]
locale_get_display_region() [tests/locale_get_display_region.phpt]
locale_get_display_script() [tests/locale_get_display_script.phpt]
locale_get_display_variant() [tests/locale_get_display_variant.phpt]
locale_get_region() [tests/locale_get_region.phpt]
locale_parse_locale() [tests/locale_parse_locale.phpt]
=====================================================================

因为这些测试用例本身也是 php 程序,我就自己在命令行下运行了一遍检查为什么会导致测试失败。发现大部分输出都是正确的,但有一些情况下输出和测试用例中的断言不匹配。为什么会这样呢?我没有深入研究,也不知道为什么。哪位朋友如果熟悉这方面请赐教。

我最后的结论: 我使用了这个自己编译的版本用了一段时间,没发现有什么不正常的地方,所以这种 patch 方式应该是可行的。但是,由于存在部分测试用例没有通过,可能会隐藏着一些意想不到的bug,所以不建议在生产环境下使用。

懒人有福了,patch 后的版本我放到了 github 上,大家可以直接 clone 一份下来编译,不用自己手动修改代码了,链接在此: https://github.com/liangzhenjing/php53-intl

SELinux 导致 PHP 无法使用 fsockopen 连接到 Memcached 服务器

2010年8月5日

前段时间刚刚写了一篇关于 SELinux 导致 httpd(Apache2) 无法启动 的文章,今天又碰到 SELinux 的问题了。

事情是这样的:

首先是服务器硬盘出问题了:-(,我给换了块硬盘,然后重装系统(CentOS 5.4 i386),然后安装各种程序、还原各种数据。最后一步是使用 memcache.php 来监控 Memcache 状态。然而却发现该工具无法连接上 Memcached 服务器。经检查,Memcached 服务器已经正常启动,使用 telnet 能够正常连接上去,使用 Memcached 的应用程序(PHP程序)也正常工作。查看 memcache.php 代码发现其是使用 fsockopen 来连接 Memcached 服务器,遂怀疑 Socket 扩展的问题。然而,检查发现可以在命令行中使用 fsockopen 连接到任意地址的任意端口,说明 Socket 扩展没问题。但在 httpd 中使用 fsockopen 来就只能连接本机的 80、8080、443 端口,连接其他端口均失败。

检查 httpd 的 log 也没发现任何问题。上网搜索也没发现类似问题,郁闷ing……

于是又想到是否是 SELinux 的问题。grep 了下 /var/log/audit/audit.log,发现以下线索:

» 阅读更多: SELinux 导致 PHP 无法使用 fsockopen 连接到 Memcached 服务器

推荐一个 PHP 写的 Memcache 管理器

2010年7月13日

其实,查看 memcache 服务器状态的最简单的办法是直接 telnet 上去:

[liang@iMac: ~]$ telnet localhost 11211
Trying ::1…
Connected to localhost.
Escape character is ‘^]’.
stats
STAT pid 6404
STAT uptime 8865
STAT time 1279025383
STAT version 1.2.8
……
END

但这个结果实在是太简陋了,很不直观。而且有些情况下是无法使用 telnet 连接 memcache 服务器的(比如在外网),这时候如果有一个像 PhpMyAdmin 那样的 Web 程序来管理 memcache 服务器的话,是一件非常方便的事情。

我在网上找了找,找到了这个 memcache 管理程序直接下载连接),该程序主要的功能有:

  1. 管理多个 memcache 服务器
  2. 实时查看各个服务器的内存使用状况
  3. 实时查看缓存命中情况
  4. 直接浏览缓存内容,删除指定缓存项
  5. 等等等。。。自己发掘吧

» 阅读更多: 推荐一个 PHP 写的 Memcache 管理器

从备份还原后 SELinux 导致 httpd(apache2) 无法启动,提示 DocumentRoot must be a directory

2010年7月3日
SELinux 是美国国安局开发的一个能有效增强 Linux 安全性的套件,现在现在很多 Linux 发行版都默认集成。这个东西用好了能极大的增强服务器性能,然而,有时候也会带来一些不便和困惑。如果对它不了解的话,有时候出的问题甚至能把人搞迷糊了。建议大家去了解一下它,至少要知道它的用途、如何禁用、启用它,和由它引发的一些常见问题,以免碰到了一些由它引发的问题的时候一头雾水,不知所措。
比如我今天碰到这这个问题,要是事先不知道 SELinux 的话,估计会把人搞疯了,不过好在哥们我比较 professional,哪能随便被一些小 case 磕倒啊,哈哈  :-)
今天的事情是这样的,我今天把服务器重装了,重装好了以后把之前做好的网站备份还原到了新系统上,但启动 httpd 时报错,提示:
[root@www vhosts]# service httpd restart
Stopping httpd:                                            [  OK ]
Starting httpd: Syntax error on line 290 of /etc/httpd/conf/httpd.conf:
DocumentRoot must be a directory
[FAILED]
我看了下配置文件,DocumentRoot 指向的目录确确实实是存在的,权限设置也是没问题的,但 apache 就是不认,WTF????
反复确认了几次后,我100%确认配置是没有问题的,权限也是没有问题的,那会是什么原因捏~~ SELinux,只有这个可能了。先确认一下:
[root@www vhosts]# ls -Z
drwxr-xr-x  root  root  root:object_r:user_home_t www.liang.eu
[root@www vhosts]# grep denied /var/log/audit/audit.log
type=AVC msg=audit(1278157850.075:163): avc:  denied { search } for  pid=10100 comm=”httpd” name=”vhosts” dev=dm-1 ino=4391538 scontext=root:system_r:httpd_t:s0 tcontext=root:object_r:user_home_t:s0 tclass=dir
看到没,文件夹的 SELinux 属性必须是 httpd_sys_content_t 才能被 web 服务器访问,但现在却是 user_home_t
[root@www vhosts]# cd ..
[root@www www]# chcon -R -t httpd_sys_content_t vhosts/
检查一下结果:
[root@www www]# ls -Z vhosts/
drwxr-xr-x  root  root  root:object_r:httpd_sys_content_t www.liang.eu
好了,已经正确改回来了,重启下 httpd:
[root@www www]# service httpd start
Starting httpd:                                            [  OK ]

OK,访问一下网站,也能正常访问了。

总结:
当时我是先把备份文件解压到自己的用户目录下,结果就被自动设置上了 user_home_t 属性,把移动到网站目录下后,没有被重新设置为 httpd_sys_content_t 属性,导致 httpd (以 apache 用户身份启动) 无权限访问该文件夹。使用 chcon 修改属性为 httpd_sys_content_t 后,httpd 即可以正常访问,问题解决。
例行公事:http://LiANG.eu 原创文章,转载请注明出处和保留链接,否则将会有很低俗的事情发生。

在 CentOS 上安装 CPU 温度监控软件(lm_sensors)

2010年7月1日

前段时间新装了一台服务器,系统是 CentOS 5.4 x64,托管在天通苑的一个机房里,上次去装机器的时候注意到他们机房有时候不开空调,机房内温度很高,所以有点不放心,所以想装一个 CPU 温度监控软件方便随时查看机器是否在正常温度下工作。

查了些资料,基本都是 lm_sensors 的,网上说的都很简单,看了几遍后心中比较有数了,就开始动手。本以为会很顺利,结果走了不少弯路,查了很多资料才最终安装成功成。现在在这里记下一些网上的文章都没有提到的细节,正是这些细节让我走了不少弯路。 » 阅读更多: 在 CentOS 上安装 CPU 温度监控软件(lm_sensors)

买了一个Linode的VPS, 简单评测

2010年7月1日
久闻Linode大名, 再加上受够了 burst.net 的龟速, 忍不住就下手买了一个. 还专门去通过某站的referrals买的(国内做aff的太多….忘了是哪个站了), 反正都是一样的价格, 大家挣钱都不容易, 通过referral送给他们点推介费, 就当是为兲朝创汇吧, 感谢国家! 哪位朋友要是想买了, 可以通过我的推荐链接购买, 作为回报, 我可以无偿提供 Linux 技术支持, 我的链接是: http://www.linode.com/?r=17f2ec6bf305b5cf5cee48e59a8c59eb3310579f

言归正传, 我买的是是 512M 内存的那款, $19.99/mon, 配置如下:

内存: 512M
硬盘空间: 16G
月流量: 200G
看起来还很不错, 就是价格比我现在在用的burst.net那款贵了接近4倍, 心怪疼的…
Linode只能通过信用卡支付, 好在我有招行双币卡, 很顺利的就支付成功了. 付款成功后就可以进入后台进行安装了, 我以前在金山工作的时候经常使用CentOS, 对CentOS最熟悉, 所以就选择了CentOS 5.5. 安装系统过程系统非常简单, 简单到我懒得说. Skipping…
不得不赞扬下Linode, 开通过程很简单, 效率非常高, 不到10分钟就机器就起来了, 受够了burst的龟速, 我对ping值都有心理阴影了, ping一下先….
Hackintosh:~ liang$ ping liang.eu PING liang.eu (173.230.146.50): 56 data bytes 64 bytes from 173.230.146.50: icmp_seq=0 ttl=50 time=245.278 ms 64 bytes from 173.230.146.50: icmp_seq=1 ttl=50 time=245.676 ms 64 bytes from 173.230.146.50: icmp_seq=2 ttl=50 time=244.975 ms 64 bytes from 173.230.146.50: icmp_seq=3 ttl=50 time=245.388 ms 64 bytes from 173.230.146.50: icmp_seq=4 ttl=50 time=245.815 ms 64 bytes from 173.230.146.50: icmp_seq=5 ttl=50 time=247.755 ms
不错的ping值, 暗爽中, 接着就ssh进去了, 先装编译环境和常用的库再说:
# yum install -y gcc gcc-c++ flex bison autoconf automake libtool bzip2-devel zlib-devel ncurses-devel pam-devel fontconfig-devel libjpeg-devel libpng-devel libtiff-devel freetype-devel make pcre-devel openssl-devel ibxml2-devel curl-devel
本来我以为光下载这些安装包就得二十来分钟, 但很快发现我错了, 万恶的资本主义不单单生活奢侈, 连网络都照样奢侈, 刷刷地没两分钟就都给我装好了, 连杯咖啡都没来得及泡, NND…
然后第二件事情是装个unixbenchmark跑跑看…
# wget http://byte-unixbench.googlecode.com/files/unixbench-5.1.2.tar.gz # tar -zxf unixbench-5.1.2.tar.gz # cd unixbench-5.1.2 # ./Run
———————————漫长的等待的分割线————————————-
========================================================================
BYTE UNIX Benchmarks (Version 5.1.2)

   System: li156-50: GNU/Linux
   OS: GNU/Linux -- 2.6.34-linode26 -- #2 SMP Wed Jun 23 18:47:16 UTC 2010
   Machine: i686 (i386)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0: Intel(R) Xeon(R) CPU L5520 @ 2.27GHz (4533.5 bogomips)
          Hyper-Threading, MMX, Physical Address Ext
   CPU 1: Intel(R) Xeon(R) CPU L5520 @ 2.27GHz (4533.5 bogomips)
          Hyper-Threading, MMX, Physical Address Ext
   CPU 2: Intel(R) Xeon(R) CPU L5520 @ 2.27GHz (4533.5 bogomips)
          Hyper-Threading, MMX, Physical Address Ext
   CPU 3: Intel(R) Xeon(R) CPU L5520 @ 2.27GHz (4533.5 bogomips)
          Hyper-Threading, MMX, Physical Address Ext
   06:30:07 up 7 min,  2 users,  load average: 0.08, 0.18, 0.08; runlevel 3

------------------------------------------------------------------------
Benchmark Run: Tue Jun 29 2010 06:30:07 - 06:58:01
4 CPUs in system; running 1 parallel copy of tests

Dhrystone 2 using register variables        8795015.0 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     1791.8 MWIPS (9.7 s, 7 samples)
Execl Throughput                               1407.2 lps   (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        265155.3 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks           70283.3 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks        767878.3 KBps  (30.0 s, 2 samples)
Pipe Throughput                              392079.7 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                  47525.9 lps   (10.0 s, 7 samples)
Process Creation                               1814.3 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   2770.6 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                    898.8 lpm   (60.0 s, 2 samples)
System Call Overhead                         408650.8 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0    8795015.0    753.6
Double-Precision Whetstone                       55.0       1791.8    325.8
Execl Throughput                                 43.0       1407.2    327.3
File Copy 1024 bufsize 2000 maxblocks          3960.0     265155.3    669.6
File Copy 256 bufsize 500 maxblocks            1655.0      70283.3    424.7
File Copy 4096 bufsize 8000 maxblocks          5800.0     767878.3   1323.9
Pipe Throughput                               12440.0     392079.7    315.2
Pipe-based Context Switching                   4000.0      47525.9    118.8
Process Creation                                126.0       1814.3    144.0
Shell Scripts (1 concurrent)                     42.4       2770.6    653.4
Shell Scripts (8 concurrent)                      6.0        898.8   1498.0
System Call Overhead                          15000.0     408650.8    272.4
                                                                   ========
System Benchmarks Index Score                                         433.0

------------------------------------------------------------------------
Benchmark Run: Tue Jun 29 2010 06:58:01 - 07:26:11
4 CPUs in system; running 4 parallel copies of tests

Dhrystone 2 using register variables       32821581.9 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     6356.7 MWIPS (11.6 s, 7 samples)
Execl Throughput                               4532.7 lps   (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        274179.2 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks           72439.1 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks        945148.7 KBps  (30.0 s, 2 samples)
Pipe Throughput                             1490792.2 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 186991.4 lps   (10.0 s, 7 samples)
Process Creation                               6600.3 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   6839.9 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                   1002.4 lpm   (60.1 s, 2 samples)
System Call Overhead                        1423594.7 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   32821581.9   2812.5
Double-Precision Whetstone                       55.0       6356.7   1155.8
Execl Throughput                                 43.0       4532.7   1054.1
File Copy 1024 bufsize 2000 maxblocks          3960.0     274179.2    692.4
File Copy 256 bufsize 500 maxblocks            1655.0      72439.1    437.7
File Copy 4096 bufsize 8000 maxblocks          5800.0     945148.7   1629.6
Pipe Throughput                               12440.0    1490792.2   1198.4
Pipe-based Context Switching                   4000.0     186991.4    467.5
Process Creation                                126.0       6600.3    523.8
Shell Scripts (1 concurrent)                     42.4       6839.9   1613.2
Shell Scripts (8 concurrent)                      6.0       1002.4   1670.7
System Call Overhead                          15000.0    1423594.7    949.1
                                                                   ========
System Benchmarks Index Score                                        1020.1
1020分, 挺不错的分数了
————————-困了睡觉的分割线—————————–
困了, 明天再继续
例行公事:http://LiANG.eu 原创文章,转载请保留出处和链接。