标签为 "Php" 的存档

PHP安装时libiconv错误问题解决

/var/tools/php-5.6.17/ext/iconv/iconv.c:2512: undefined reference to `libiconv_open’
ext/xmlrpc/libxmlrpc/encodings.o: In function `convert’:
/var/tools/php-5.6.17/ext/xmlrpc/libxmlrpc/encodings.c:73: undefined reference to `libiconv_open’
/var/tools/php-5.6.17/ext/xmlrpc/libxmlrpc/encodings.c:81: undefined reference to `libiconv’
/var/tools/php-5.6.17/ext/xmlrpc/libxmlrpc/encodings.c:101: undefined reference to `libiconv_close’
collect2: ld returned 1 exit status
make: *** [sapi/cli/php] Error 1

在阿里云安装php时,make的时候,发生了libiconv错误,通过安装libiconv,指定with-iconv-dir也没解决。最终是在make时加了一个参数,然后顺利编译通过的。
make ZEND_EXTRA_LIBS='-liconv'

怎么修改ulimit,开启php的coredump输出

大家应该都知道,开启php的coredump输出,修改ulimit -c就可以了,但是很多情况下,会提示权利受限,无法修改

[fukun@10.16.29.xxx]$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 30678
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 32768
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

$ ulimit -c unlimited
-bash: ulimit: core file size: cannot modify limit: Operation not permitted

解决方案:
1.检查配置
看看shell配置里有没有 ulimit -c 0 这种类似的关闭的操作,例如 $HOME/.bash_profile 或者 $HOME/.bashrc 之类的,如果有,注释掉。

#
# Do not produce core dumps
#
# ulimit -c 0

Read more…

360指数项目概况总结

最近在搞360指数项目,挑战还是比较多的,现在项目已经基本ok了,拿出点时间来总结一下。

360指数搜索

360指数搜索

首先说说存储,需求的数据量比较大,又有一些弱关系的查询需求,首先放弃的就是mysql和redis,然后跟DBA沟通了下,使用mongoDB似乎是个不错的选择,在开动了之后才发现,数据量比预估的还要大,DBA的SSD资源不足以支持我们的项目,我们就自己搞了一台有4个2Tsas盘的机器,DBA在上边搞了24个分片,很轻易的,我们就把磁盘IO搞满了,数据写的速度慢的要死,在ssd上有1-2w/s的速度,在sas盘上,就只有几百了,数据量实在太大,需要录入一直到去年年初的指数数据,如果要想在上线前把数据录入完成,这样下去是不可能了。 随后我们又搞了两台给Hadoop集群使用的机器,每台机器有12块SCSI硬盘,看起来些写性能应该能翻个几番,但其实,部署完了之后,才发现,写入速度也才刚能达到1-2k,距离我们的需求还差的很远。
其实,我们要求的也只是数据的初始化速度要快一些,上线之后,这样的写性能也足以支持我们把增量数据录入,所以,我们还可以通过借一些ssd硬盘来加快写入速度,然后把数据对拷到scsi硬盘,这样,数据初始化的问题就可以解决了。本来已经从其它部门的同事那里借到了25块ssd,不过在跟他们进一步沟通之后,发现公司有可以提供线上服务的Hbase集群,虽然在存储选型初期也想过Hbase,由于当时对Hbase了解较少,也不知道有可以提供线上服务的集群,就这么错过了,与系统部的同事沟通后,我们数据量最大的两块数据,是可以迁移到Hbase使用的,这块数据占到我们总数据的90%,这部分数据通过Hbase解决后,其它数据再使用Mongodb就毫无压力了。最终,我们的最大数据部分的需求,通过合理使用Hbase的column_qualifier和version得以解决。而且单纯存入这批数据的map/reduce时间,仅仅使用了17分钟。
这里还要感谢一下DBA和系统部的同事,在好几个夜晚帮我们部署环境,解答疑问,使我们的项目得以顺利前进。

嗯,,,项目中还用到了一个自己封装的php扩展,单独写个文章介绍下吧。

undefined symbol: itoa

itoa不是c的一个标准输入输出,所以可能不在stdlib.h里。
解决办法很简单,不就是要把整型转为字符串么。sprintf 格式化输出一下就好了。

举个例子:

int val = 177;
char *val_s ;
spprintf(&val_s, 0, "%d", val);

libcurl.so.3: cannot open shared object file

php配置扩展时遇到了个这个问题:PHP Warning: PHP Startup: Unable to load dynamic library ‘/home/s/apps/php-5.2.6/extensions/curl.so’ – libcurl.so.3: cannot open shared object file: No such file or directory in Unknown on line 0

google了下,都说解决办法是:

ln -s /usr/lib/libcurl.so.4 /usr/lib/libcurl.so.3

我看了下自己的lib目录,发现也没有 libcurl.so.4,然后又查没有libcurl.so.4怎么样,答案是:

ln -s /usr/lib/libcurl.so.3 /usr/lib/libcurl.so.4

啊哈哈哈哈哈哈,乐死我了。

我个人觉得是curl.so不靠谱,从别的地方搞了一个拷贝过来,ok了。

如何在不重新make install PHP的情况下编译出PHP扩展.so文件

生成一个PHP扩展.so文件,一般就是这两种方法,第一种是在php源码内configure –[with|enable]-extension_name,然后make && make install,新扩展就会生成并保存在PHP的环境中了。
不过多半会有这种情况,我们跟别人共用一台开发机,开发机已经安装了标准的php开发环境,如果我们在用这种重新编译PHP的情况,如果我们有调试php源码,或者调试扩展,很有可能会损坏原有的标准环境,所以我们就需要另一种方法,只生成一个.so文件,然后把so手动放到标准环境下,就可以不影响大局了。
这种方式呢,也很简单,跟第一种方法一样,三步搞定。

一、phpize
进入你开发php扩展的扩展根目录,比如我想做的扩展是 fkhelloworld,目录在这里 /home/s/www/fukun/clang/php-5.2.6/ext/fkhelloworld.
在这里执行phpize,如果提示找不到此命令,就找到你php的bin目录,执行全路径的命令,比如我的phpize在这里:/home/s/apps/php-5.2.6/bin/phpize

If you look in the current directory at this point, you’ll notice a lot more files than you had there a moment ago. The phpize program combined the information in your extension’s config.m4 file with data collected from your PHP build and laid out all the pieces necessary to make a compile happen. This means that you don’t have to struggle with makefiles and locating the PHP headers you’ll be compiling against. PHP has already done that job for you.

phpize会结合你的config.m4文件中描述的信息以及你的php构建相关数据,制定合并所需的部分数据,这意味着你不必再在意makefile文件和定位要编译的php文件头,PHP已经把这些都做好了。

Read more…

PHP扩展:如何在Zend Api中对参数进行获取:zend_parse_parameters()和zend_parse_parameters_ex()

首先要知道, ZEND_NUM_ARGS()宏定义可以得到参数的个数。

参数解析函数:
int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, …);
第一个参数num_args表明了我们想要接收的参数个数,一般都使用ZEND_NUM_ARGS() 来表示对传入的参数“有多少要多少”,如果有特殊需求,可以自己直接指定。第二参数应该总是宏 TSRMLS_CC 。第三个参数 type_spec 是一个字符串,用来指定我们所期待接收的各个参数的类型,有点类似于 printf 中指定输出格式的那个格式化字符串。剩下的参数就是我们用来接收PHP参数值的变量的指针。需要说明的一点是:zend_parse_parameters中如果声明了一个字符串类型,那么后面对应的参数将是两个,第一个代表字符串,第二个代表字符串长度。如果声明了一个指定类型的对象实例,那么后面对应的参数也是两个,第一个代表对象,第二个代表对象的类型。

type_spec 的各类型表示如下:
• l – 长整数
• d – 双精度浮点数
• s – 字符串(也可能是空字节)和其长度
• b – 布尔值
• r – 资源, 保存在 zval*
• a – 数组, 保存在 zval*
• o – (任何类的)对象, 保存在 zval*
• O – (由class entry 指定的类的)对象, 保存在 zval*
• z – 实际的 zval*
| – 表明剩下的参数都是可选参数。
/ – 表明参数解析函数将会对剩下的参数以 SEPARATE_ZVAL_IF_NOT_REF()
的方式来提供这个参数的一份拷贝, 除非这些参数是一个引用。
! – 表明剩下的参数允许被设定为 NULL(仅用在a、o、O、r和z身上)。

下边给几个例子,自己体会下:

Read more…

结构体struct和联合体union的区别

结构体-struct是把若干个数据类型组合到一起,相当于形成一个结构类型,这样的结构体变量就拥有结构体所包含的所有的数据类型。
结构体所占用的内存单元是它里面包含数据类型所占内存单元的总和。

联合体-union是为了节省内存而设置的,若干个不同数据类型共用一组内存单元。
联合体所占的内存单元是它所包含的数据类型中占用内存单元最大的那个数据类型所占用的内存单元的值。

  union   test1
  {   
          long   a;   
          char   b;   
  }   
  sizeof(test1)==sizeof(long)   
    
  struct  test2
  {   
          long   a;   
          char   b;   
  }   
  sizeof(test2)==sizeof(long)+sizeof(char)

struct和union都是由多个不同的数据类型成员组成, 但在任何同一时刻, union中只存放了一个被选中的成员, 而struct的所有成员都存在。
对于union的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于struct的不同成员赋值是互不影响的。

Read more…

Cannot assign requested address 出现原因及解决方案

今天在压测时,会偶尔遇到错误,错误提示: Cannot assign requested address ,看了下,大致上是由于客户端频繁的连服务器,由于每次连接都在很短的时间内结束,导致很多的TIME_WAIT,以至于用光了可用的端 口号,所以新的连接没办法绑定端口,即“Cannot assign requested address”。是客户端的问题不是服务器端的问题。通过netstat,的确看到很多TIME_WAIT状态的连接。

解决办法是需要做一下内核参数优化:(需要root权限)
sysctl -w net.ipv4.tcp_timestamps=1 开启对于TCP时间戳的支持,若该项设置为0,则下面一项设置不起作用
sysctl -w net.ipv4.tcp_tw_recycle=1 表示开启TCP连接中TIME-WAIT sockets的快速回收

改完还不能解决问题,需要修改tcp_max_tw_buckets
sudo sh -c “echo ‘5000’> /proc/sys/net/ipv4/tcp_max_tw_buckets”

nginx client intended to send too large body 却没有触发error_page 413

在做以图搜图时,需要用户上传图片,同时需要对用户上传图片做大小限制。
如果文件全部上传到服务器了,可以用$_FILES变量来获取文件信息,判断文件大小,来决定是否拒绝用户的请求。
不过当文件过大时,会直接出发nginx的413 Request Entity Too Large 错误,如何友好的来提示用户呢。
这里就可以用到nginx的error_page用法了,直接指定413的错误跳转到一个指定页面,在指定页面内友好提示即可。

client_max_body_size 3M; #限定nginx允许上传的文件大小

#错误提示页面,指定哪个错误跳转到哪个页面,url可以是一个Action的路径
error_page 404 /404.html;
error_page 413 /stu?a=error413;
error_page 500 502 503 504 /50x.html;

这样设置了之后,就可以使用了,当上传的文件过大时,会直接被nginx拦截到413错误,进而重定向到友好的错误提示页。
不过在一次bug修复之后,发现再提交过大的文件时,没有出现这个提示页面了,而是等了很长时间之后出现了一个500错误,而且500错误也没有被拦截到50x的错误页面,很是奇怪。排查了下nginx日志,出现的错误提示就是 client intended to send too large body: 4224579 bytes.

排查了一会之后,再测试环境下打开错误输出,发现原来是413重定向后的Action在视图里有php语法错误。修复之后,就又恢复正常啦。

client intended to send too large body

client intended to send too large body