今天升级完PHP出现了502 Bad Gateway错误,根据经验是php-fpm的问题,但是看到网上那些什么访问量,子进程设置什么的,但是我这太服务器压根没啥流量。所以只能从配置文件下手看看
[global] pid = /usr/local/php/var/run/php-fpm.pid error_log = /usr/local/php/var/log/php-fpm.log log_level = notice [www] listen = /tmp/php-cgi.sock user = www group = www pm = dynamic pm.max_children = 20 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 6 request_terminate_timeout = 100
看到 /tmp/php-cgi.sock 直觉发现应该是个文件,所以前往该目录查看权限,发现文件属主是 root:root,而我的nginx和php-fpm进程是以www用户运行的。所以应该是权限问题。
而配置文件中的user = www,group = www也设置了一个权限,通过 ps -aux|grep php 发现,这是php-fpm进程的属主。
知道问题的源头后便开始查php-fpm的配置,查到了 listen.ower listen.group 设置。
这是改进之后的文件:
[global] pid = /usr/local/php/var/run/php-fpm.pid error_log = /usr/local/php/var/log/php-fpm.log log_level = notice [www] listen = /tmp/php-cgi.sock listen.owner = www listen.group = www user = www group = www pm = dynamic pm.max_children = 20 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 6 request_terminate_timeout = 100
如果不知道查看配置可以尝试下面方法
1、查看当前的PHP FastCGI进程数是否够用:
netstat -anpo | grep "php-cgi" | wc -l
如果实际使用的“FastCGI进程数”接近预设的“FastCGI进程数”,那么,说明“FastCGI进程数”不够用,需要增大。
2、部分PHP程序的执行时间超过了Nginx的等待时间,可以适当增加nginx.conf配置文件中FastCGI的timeout时间,例如:
...... http { ...... fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; ...... }
......
补充另一篇文章
1.php-fpm进程数不够用
使用 netstat -napo |grep "php-fpm" | wc -l 查看一下当前fastcgi进程个数,如果个数接近conf里配置的上限,就需要调高进程数。
但也不能无休止调高,可以根据服务器内存情况,可以把php-fpm子进程数调到100或以上,在4G内存的服务器上200就可以。
2. 调高调高linux内核打开文件数量
可以使用这些命令(必须是root帐号)
echo 'ulimit -HSn 65536' >> /etc/profile echo 'ulimit -HSn 65536' >> /etc/rc.local source /etc/profile
3.脚本执行时间超时
如果脚本因为某种原因长时间等待不返回 ,导致新来的请求不能得到处理,可以适当调小如下配置。
nginx.conf里面主要是如下
fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300;
php-fpm.conf里如要是如下
request_terminate_timeout = 10s
4.缓存设置比较小
修改或增加配置到nginx.conf
proxy_buffer_size 64k; proxy_buffers 512k; proxy_busy_buffers_size 128k; 5. recv() failed (104: Connection reset by peer) while reading response header from upstream
可能的原因机房网络丢包或者机房有硬件防火墙禁止访问该域名
但最重要的是程序里要设置好超时,不要使用php-fpm的request_terminate_timeout,
最好设成request_terminate_timeout=0;
因为这个参数会直接杀掉php进程,然后重启php进程,这样前端nginx就会返回104: Connection reset by peer。这个过程是很慢,总体感觉就是网站很卡。
May 01 10:50:58.044162 [WARNING] [pool www] child 4074, script '/usr/local/nginx/html/quancha/sameip/detail.php' execution timed out (15.129933 sec), terminating
May 01 10:50:58.045725 [WARNING] [pool www] child 4074 exited on signal 15 SIGTERM after 90.227060 seconds from start
May 01 10:50:58.046818 [NOTICE] [pool www] child 4082 started
说一千道一万最重要的就是程序里控制好超时,gethostbyname、curl、file_get_contents等函数的都要设置超时时间。
PHP date()如果要使用我们必须在php.ini中配置时间时区了,如果不设置使用date函数会出现It is not safe to rely on the system s timezone settings错误,下面一起来看看一个例子。
在写php文件上传程序时有时会出现这样的警告:
Upload: 屏幕截图2014-09-28_160214.png
Type: image/png
Size: 66.84765625 Kb
Temp file: D:\Users\Aven\AppData\Local\Temp\php742F.tmp
Warning: move_uploaded_file() [function.move-uploaded-file]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'UTC' for '8.0/no DST' instead in F:\PHP\upload_file.php on line 26
Warning: move_uploaded_file(upload/屏幕截图2014-09-28_160214.png) [function.move-uploaded-file]: failed to open stream: No such file or directory in F:\PHP\upload_file.php on line 26
Warning: move_uploaded_file() [function.move-uploaded-file]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'UTC' for '8.0/no DST' instead in F:\PHP\upload_file.php on line 26
Warning: move_uploaded_file() [function.move-uploaded-file]: Unable to move 'D:\Users\Aven\AppData\Local\Temp\php742F.tmp' to 'upload/屏幕截图2014-09-28_160214.png' in F:\PHP\upload_file.php on line 26
Stored in: upload/屏幕截图2014-09-28_160214.png
这是因为PHP所取的时间是格林威治标准时间,所以和你当地的时间会有出入格林威治标准时间和北京时间大概差8个小时左右,我们可以按照下面的方法解决:
1、在页头使用date_default_timezone_set()设置我的默认时区为北京时间,即 <?php date_default_timezone_set("PRC"); ?>就可以了。
2、在php.ini中设置date.timezone的值为PRC,设置好以后的为:date.timezone=PRC,同时取消这一行代码的注释,即去掉前面的分号就可以了。
这里选用修改配置文件的方式解决问题:
用Notepad++打开php.ini,
查找“date.timezone”,把语句前的分号去掉,值设置为“PRC”,重启FastCGI服务,问题解决
本文章为各位介绍phpmyadmin-“无法在发生错误时创建会话,请检查 PHP 或网站服务器日志,并正确配置 PHP 安装。”报错解决办,有需要了和小编来看看。当登录 phpMyAdmin 出现错误提示“无法在发生错误时创建会话,请检查 PHP 或网站服务器日志,并正确配置 PHP 安装。”。原因是退出phpMyAdmin的时候,没有点“退出”而退出,而是直接叉掉浏览器窗口,当再次登录phpMyAdmin的时候就会出现这个错误。如下图:
解决办法如下:
进入 C:\ZkeysSoft\Php\tmp 文件夹,将里面的内容都删除掉即可恢复正常。
再次登录phpMyAdmin,即可进入。下次退出phpMyAdmin的时候一定要记得点“退出”来退出哦。
把这个模块打开,重启apache就可以了
遇到这个错误的原因只有一个,那就是PDO对应的数据库扩展没有加载进来,不要去怀疑PDO的错误,假如你在使用PDO的过程中遇到could not find driver报错,下面这些排查项获取能够帮你解决问题。
排查项一:是否安装对应驱动
在Windows下一般pdo_mysql.dll是自带的,所以去掉分号后能直接加载进来,但是在Linux下,你得确保你安装了PHP的pdo_mysql扩展,否则加载不进来。
排查项二:是否加载对应驱动
一般大家用的都是用的MySQL,所以PDO的driver就是pdo_mysql,所以你需要在启动PHP的时候把这个扩展包含进来。
检查php.ini看看是否包含了这个扩展,在Windows下需要将pdo_mysql.dll前面的分号去掉,Linux上加上extension='pdo_mysql.so'
排查项三:命令行下加载的配置文件是否正确
在Linux平台上我们可以在命令行下执行PHP程序,有时候会遇到在正常浏览器中访问PHP,PDO不会报错说could not find driver,但是在命令行下执行PHP是会报错could not find driver,这个时候一般是执行PHP时加载的PHP配置文件不对
其它排查方法
如果以上排查项检测都正确,仍然报错could not find driver,那么恭喜你是个幸运的孩子,遇到这种问题您可以去看看错误日志,多百度,或者Google一下,或许能解决问题,当然解决了问题也欢迎分享到这来,我会一一整理的
浮点数在php运行中会发现算出的结果与我们想象中的结果是不一样了,对于这个问题我们整理了一些关于浮点数计算的一些问题与解决办法。
在用PHP进行浮点数的运算中,遇到一个坑,没有得到预期中的结果,如下代码:
$a = 69.1;
$b = $a*100;
$c = $b-6910;
你猜$c的值是多少?$c输出的值是-9.0949470177293E-13.为什么会这样?
在PHP官网Float浮点型页面中,讲到:
浮点数的精度
浮点数的精度有限。尽管取决于系统,PHP 通常使用 IEEE 754 双精度格式,则由于取整而导致的最大相对误差为 1.11e-16。非基本数学运算可能会给出更大误差,并且要考虑到进行复合运算时的误差传递。
此外,以十进制能够精确表示的有理数如 0.1 或 0.7,无论有多少尾数都不能被内部所使用的二进制精确表示,因此不能在不丢失一点点精度的情况下转换为二进制的格式。这就会造成混乱的结果:例如,floor((0.1+0.7)*10) 通常会返回 7 而不是预期中的 8,因为该结果内部的表示其实是类似 7.9999999999999991118…。
所以永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。如果确实需要更高的精度,应该使用任意精度数学函数或者gmp函数。
那么如何正确处理PHP浮点数计算有误的问题呢?
$x = 8 - 6.4; // which is equal to 1.6
$y = 1.6;
var_dump($x == $y); // is not true
以上例子中$x和$y的值并不等。解决办法是用round()函数,如:
var_dump(round($x, 2) == round($y, 2)); // this is true
问题的原因在于$x并不是1.6,而是1.599999.
所以本文开头的例子改成下面这样就OK了:
$a = 69.1;
$b = $a*100;
$c = round($b)-6910;
或者使用number_format((float)$a, 2)格式化。
再看一个关于PHP浮点数算出来结果不符合预期的例子。
$a = intval( 0.58*100 );
$b = 0.58*100;
$a的值出乎意料的是57,$b的值是58.
解决办法是:
$a = intval( (0.58*1000)/10 );
或者使用Binary Calculator,即BCMath扩展解决以上问题
补充:<?php
$f = 0.58;
var_dump(intval($f * 100)); //为啥输出57
?>
为啥输出是57啊? PHP的bug么?
我相信有很多的同学有过这样的疑问, 因为光问我类似问题的人就很多, 更不用说bugs.php.net上经常有人问…
要搞明白这个原因, 首先我们要知道浮点数的表示(IEEE 754):
浮点数, 以64位的长度(双精度)为例, 会采用1位符号位(E), 11指数位(Q), 52位尾数(M)表示(一共64位).
符号位:最高位表示数据的正负,0表示正数,1表示负数。
指数位:表示数据以2为底的幂,指数采用偏移码表示
尾数:表示数据小数点后的有效数字.
这里的关键点就在于, 小数在二进制的表示, 关于小数如何用二进制表示, 大家可以百度一下, 我这里就不再赘述, 我们关键的要了解, 0.58 对于二进制表示来说, 是无限长的值(下面的数字省掉了隐含的1)..
0.58的二进制表示基本上(52位)是: 0010100011110101110000101000111101011100001010001111
0.57的二进制表示基本上(52位)是: 0010001111010111000010100011110101110000101000111101
而两者的二进制, 如果只是通过这52位计算的话,分别是:
0.58 -> 0.57999999999999996
0.57 -> 0.56999999999999995
至于0.58 * 100的具体浮点数乘法, 我们不考虑那么细, 有兴趣的可以看(Floating point), 我们就模糊的以心算来看… 0.58 * 100 = 57.999999999
那你intval一下, 自然就是57了….
可见, 这个问题的关键点就是: “你看似有穷的小数, 在计算机的二进制表示里却是无穷的”
so, 不要再以为这是PHP的bug了, 这就是这样的…..