windows下php5.6启用opcache
最近几天一直帮朋友配置服务器,考虑只部署wordpress,为了性能原因直接上了到目前位置最新的稳定版 php 5.6.16 ,搭建 apache 2.4.17 + php 5.6.16。
部署安装配置都很简单也很顺利,唯独就是启用opcache折腾了很多时间。死活opcache就是无法开启,然后php启动也无报错信息。
最初的做法以为opcache是内置了,只需要在php.ini中启用就可以了,如下:
opcache.enable=1
opcache.enable_cli=1
结果重启apache后,发现opcache根本未加载,各种折腾也不行。
最后到看了下官方文档:http://php.net/manual/zh/opcache.installation.php,发现这段:
PHP 5.5.0 及后续版本
OPcache 只能编译为共享扩展。 如果你使用 –disable-all 参数 禁用了默认扩展的构建, 那么必须使用 –enable-opcache 选项来开启 OPcache。
编译之后,就可以使用 zend_extension 指令来将 OPcache 扩展加载到 PHP 中。在非 Windows 平台使用zend_extension=/full/path/to/opcache.so, Windows 平台使用 zend_extension=C:\path\to\php_opcache.dll。
看来真是个坑啊,虽然内置了,但并未加载.dll文件。因此,在php.ini的[opcache]下一行加入(具体php_opcache.dll路径根据实际情况):
zend_extension=C:\php\ext\php_opcache.dll
重启apache后即可。
要说明的是,windows下无论apache还是iis做web服务都要这么做。
关于跨域Cors
除了常规的jsonP等方式,还可以使用server+client方式。
server:(下面代码是为调试方便来写的,实际环境下必须设置指定的域,否则会引起安全问题!)
if (isset($_SERVER['HTTP_REFERER'])) { $url_parse = parse_url($_SERVER['HTTP_REFERER']); $port = ''; if (isset($url_parse['port']) && $url_parse['port'] != 80) { $port = ':'.$url_parse['port']; } @header("Access-Control-Allow-Origin: ".$url_parse['scheme'].'://'.$url_parse['host'].$port); } @header("Access-Control-Allow-Credentials: true");
client:
jQuery
jQuery.ajax({ "url": "/", "dataType": "json", "success": function (data) { console.log(data); }, "xhrFields": { "withCredentials": true } });
[ERROR] Can’t open shared library ‘udf.dll’ (errno: 0 )
有3个多月没写博客了,现在似乎越来越懒了:( 今天竟然忘记了登录密码,幸好,输入几次终于想起来了……
如标题,[ERROR] Can’t open shared library ‘udf.dll’ (errno: 0 )
这是MySQL在启动时报的一个错误,在一个朋友的服务器上看到的,这个错误几乎已经持续了很久很久了,虽然报错,但似乎不影响使用,只不过,对于一个很洁癖的人来说,每次看到都很闹心。
之前曾经尝试过查找原因,包括建立plugin目录,以及遍历整个系统来查找udf.dll,都没什么结果。
也在谷歌和度娘上找过,说是什么提权文件,实话说,用了这么多年还真从来没听过这个功能……也按搜索到的文章操作过,但全部都是失败。
最后,考虑到可以尝试升级一下MySQL的版本(之前是5.0很早期的一个版本),由于系统还有很多不太熟悉的程序,所以为了考虑稳定性,所以只是升级到MySQL5.0的最后一个版本。
升级很简单,轻车熟路,一贯是我最懒人的做法:
1.由于想重新使用mysql的配置向导来配置my.ini所以,先将mysql的服务删除掉,命令行执行,mysqld-nt –remove即可。
2.不改变mysql的安装目录,因此,只需要将原来的安装目录改个名就行(权当备份了)
3.执行mysql安装程序,安装到之前的目录下。
4.执行mysql的配置向导,进行my.ini的配置。
5.手动打开my.ini,修改数据库文件储存目录变量“datadir”,修改为之前的数据库储存位置
6.重启mysql
升级操作就算完毕了,原来的帐号都可以继续使用,其他无须做什么改变。
回头再来看系统日志,发现一个很奇怪的现象,就是刚升级完启动mysql的时候那个错误是没有的,但改完数据库储存目录后再重启那个错误又出现了。
看来,这个错误本身应该还是来自于mysql数据库,而且只能是mysql自身的数据库(数据库名:mysql),
于是,关闭mysql。
尝试将旧的mysql系统数据库(数据库名为mysql),改成其他名字,将新的mysql默认的系统数据库copy过来。
同时将旧系统数据库内的user表文件(三个)都覆盖到新系统数据库内。
这时候再启动mysql就不会有错误提示了。
查看了一下旧系统数据库表,发现其中一个数据表(mysql\func)里存在一条记录:
mysql> select * from func; +-------+-----+---------+----------+ | name | ret | dl | type | +-------+-----+---------+----------+ | baker | 0 | udf.dll | function | +-------+-----+---------+----------+ 1 row in set (0.00 sec)
挺有意思的,真的不知道这是干什么用的,似乎没有它也一样正常运行。
结论:如果有类似这样错误的,可以尝试找一下系统数据库(mysql)的func表,把dl=udf.dll的这条记录删除掉,然后再重启mysql应该就可以了,如果怕出问题可以提前进行一下备份。
PS:网上其他的解决方案真的不知道是否可行,反正我是没成功。我的这个方案只是清除掉错误(功能),可能未必是一个完美的解决方案。但就个人而言,utf.dll似乎真的没什么用,删了也无所谓。
windows 2003安装PHP的FastCGI模式
以前一直使用sapi的方式来在windows服务器的iis上执行php,一直也是推荐这种方式,但自windows 2008以及高版本php开始后官方开始推荐fastcgi模式,自己内心比较排斥这种方式(没来由的)。
今天接到托管商要求用户访问记录端口留存(估计可能因为打击传谣而起的),才发现,运行在sapi模式下的php无法获取$_SERVER['REMOTE_PORT']变量。
没办法,只能更改运行方式了。
首先因为历史和时间原因,很多程序很老了,高版本的php可能有兼容问题,因此还是使用php5.2版本。
先是安装IIS6的FCGI组件,在 http://www.iis.net/download/fastcgi 进行下载,直接安装就可以。
其次是安装PHP,在 http://windows.php.net/download/ 找到对应版本
我推荐安装php不要将任何文件放到非php目录(比如dll文件,比如php.ini文件等),这样做主要是为了保证未来升级的方便性。
一般我是这样做:
1.先指定php.ini 以及 php的安装路径。可以看一下这里 http://www.deepseath.com/?p=1059
2.确保安装了 VC 库,在早期版本php可能没问题,但还是推荐安装 参看 http://www.deepseath.com/?p=858
PHP的相关配置根据自己需要进行配置就可以,没特别的硬性要求。
大体上配置:
1。extension_dir 目录
2。修改默认的时区
安装后,主要是检查iis的“Web服务扩展”是否有“FastCGI Handler”且允许状态。并且配置php的执行文件为:C:\WINDOWS\system32\inetsrv\fcgiext.dll
最后修改一下fastcgi的配置文件:C:\WINDOWS\system32\inetsrv\fcgiext.ini
在最下面的[Types]后面加入:
php=PHP
[PHP]
ExePath=php的安装路径\php-cgi.exe
InstanceMaxRequests=10000
;MaxInstances=64
EnvironmentVars=PHP_FCGI_MAX_REQUESTS:10000
RequestTimeout=30(默认是30,我推荐900或者3000)
ActivityTimeout=30
如果需要也可以安装一个wincache,在 http://www.iis.net/download/WinCacheForPHP
innerHTML的使用遇到的一个问题
在项目中涉及到一种场景:提交某个表单(id=source)后,利用ajax输出一个新的表单(id=target)并显示在一个id为A的容器内并自动提交。这是项目内一个在线支付的一个功能。
实现很简单,ajax提交id=source表单后,返回一个新表单id=target,然后利用innerHTML将新表单数据写入到id=A的容器内。
但在实际做的时候发生了一个意外,在firefox(22.0)内是没有错误的最终会跳转到target的表单自动提交,但在Chrome(29)无法不能运行点击提交表单id=source后无任何反应,在IE8提交时,会显示
此网页上的错误可能会使它无法正确运行。未知的运行时错误
程序的安全考量
上次帮朋友处理了被注入的一些后遗症:http://www.deepseath.com/?p=1107
今天再次被注入,而且那人竟然联系朋友说网站的目录权限做得真死,哈哈,这人真的是明目张胆,幸亏上次把很多目录权限写操作去掉了,否则更严重。
这次通过web日志彻底清查了一下具体的注入入口,找到了具体的程序,发现竟然是一个数组参数的键名未过滤导致的,加了过滤,测试了一下应该是堵上了。
感触颇深,再次说明,写代码,是反外来的数据都不要理所当然的认为它是安全的,参数尽量保持一个类型,引入的时候判断类型甚至字符集是否合法,然后再进行字符过滤,虽然麻烦了点,但起码不会被日后的注入所烦恼。
有时候一个小疏忽可能就会被人利用。
关于外来参数,早两年自己就不再接受全局变量了,一个程序只接受它需要的参数,所有变量都尽可能的事先进行声明,临时的变量用完后尽量马上销毁,外来的参数要尽可能的明确类型,严格检查它的类型是否合法,如果可能也可以再进一步判断字符集是否同网站的一致,不一致的也不接受。这样做不一定能保证完全绝对的安全,起码感觉漏洞暴漏的相对会少一些。
网站目录安全的一些小总结
今天帮朋友处理了一个挂马的问题,除了开发代码的一些必要安全外,程序部署、web目录架构方面还有一些总结。
这里只是说程序部署和web目录架构权限安排方面的,不涉及纯粹代码安全问题,那是另外的一个话题。
1.程序部署上尽量不要对根目录进行操作(比如,建立目录什么的)
2.将引用文件和可直接执行文件分开放置,只对可直接执行文件有运行脚本权限,对于引用文件所在的路径禁止web可读写。
3.只对专门的目录进行写操作,其他一律禁止写操作。
4.无关web可访问的目录都禁止读取。
5.web目录设定时尽量别太懒惰,给予不同站点不同目录分别设置web用户,一个站点只有一个web用户,只对这个web用户进行权限分配。
基本上,如果能确保这些,我想网站起码在文件注入上能够最大的避免出问题。
VisualSVN Server设置同步服务
做web开发为了随时能了解和看到和测试程序发布后的效果,之前是开发的时候多数情况下是svn提交完后,再FTP提交,麻烦费事,就想着将SVN提交后自动将数据同步到测试目录下,然后随时让团队其他人看到效果。
查看了一下svn的命令,写了一个post-commit钩子脚本,发现不行,然后搜了下其他人的,多数都是这么写钩子:
@echo off
“C:\visualSVN\VisualSVN Server\bin\svn.exe” update “D:\webHost” –username svn –password 000000
但实际运行的时候发现是不行的,必须要将svn设置为非安全链接http,才可以,否则始终会提示类似
svn: E175002: OPTIONS of ‘https://xxxxxxx: Server certificate verification failed: issuer is not trusted (https://xxxxx)
这样的错误提示,在这之前还有其他类似的错误,但基本属于权限问题,一般将visualsvn的启动用户设置一下权限就可以了。
这个错误始终搞不定,看过有人说是通过缓存什么的(http://my.oschina.net/bufenye/blog/58264)(3楼),但实际做起来还是不行,后来考虑svn应该有类似的命令能解决这样的问题的,
使用:svn help update 会输出关于update命令的参数帮助:
Valid options: -r [--revision] ARG : ARG (some commands also take ARG1:ARG2 range) A revision argument can be one of: NUMBER revision number '{' DATE '}' revision at start of the date 'HEAD' latest in repository 'BASE' base rev of item's working copy 'COMMITTED' last commit at or before BASE 'PREV' revision just before COMMITTED -N [--non-recursive] : obsolete; try --depth=files or --depth=immediates --depth ARG : limit operation by depth ARG ('empty', 'files', 'immediates', or 'infinity') --set-depth ARG : set new working copy depth to ARG ('exclude', 'empty', 'files', 'immediates', or 'infinity') -q [--quiet] : print nothing, or only summary information --diff3-cmd ARG : use ARG as merge command --force : force operation to run --ignore-externals : ignore externals definitions --changelist [--cl] ARG : operate only on members of changelist ARG --editor-cmd ARG : use ARG as external editor --accept ARG : specify automatic conflict resolution action ('postpone', 'working', 'base', 'mine-conflict', 'theirs-conflict', 'mine-full', 'theirs-full', 'edit', 'launch') (shorthand: 'p', 'mc', 'tc', 'mf', 'tf', 'e', 'l') --parents : make intermediate directories Global options: --username ARG : specify a username ARG --password ARG : specify a password ARG --no-auth-cache : do not cache authentication tokens --non-interactive : do no interactive prompting --trust-server-cert : accept SSL server certificates from unknown certificate authorities without prompting (but only with '--non-interactive') --config-dir ARG : read user configuration files from directory ARG --config-option ARG : set user configuration option in the format: FILE:SECTION:OPTION=[VALUE] For example: servers:global:http-library=serf
看到上面的蓝色三个参数,豁然开朗,果断加入,终于可行了^_^
有个小插曲,挺尴尬的,在网上搜索来的那句钩子,我直接给复制了,只该了路径,结果显示出现什么“文件、卷标错误”之类的,后来才看到是引号用的全角(因为编辑器里看双引号全角和半角不是很明显的区别),再后来是出现类似
svn: E170001: OPTIONS of ‘https://xxxxxx’: authorization failed: Could not authenticate to server: rejected Basic challenge (https://xxxxxx)
应该是帐号无法访问的缘故,可明明是正确的帐号密码的,开始想着可能是密码包含特殊字符的缘故,改了,还不行,再后来才发现那个–username svn –password 000000看着好奇怪,哈哈,是“-”写成了“–”。改过来,成功!事实证明,无脑的单纯复制会造成多么大的困扰,哈哈。以后还是自己敲键盘吧。
总结上面的操作,基本上,先实现svn自动同步更新到web测试目录,需要做几件事(使用https安全链接方式,可能使用非安全链接的http方式可能比较省事)
1.确保你的svn启动用户和用户组具有对web目录的可读写权限。
2.确保你的帐号密码是正确并有权限访问svn(只需要只读权限就可以)
送上一个post-commit钩子脚本,没有标点符号错误哦,哈哈,你需要将你的路径和帐号密码对应改一下
“C:\Program Files\VisualSVN Server\bin\svn.exe” update “D:\yyyy\xxx” –non-interactive –trust-server-cert –no-auth-cache –username 11111111 –password 22222
联通宽带避免跳出垃圾页面(www.tao123.com)的解决
首先说联通宽带真的很垃圾,花钱用宽带,然后被强迫看广告。
最近有时候访问一些域名的时候发现总是会被重定向到一个域名为:www.tao123.com 的垃圾网址,开始不以为然,但偶尔总是如此就真的很烦了。
下决心找到是怎么回事,开始以为是浏览器被恶意植入了插件,但查遍注册表以及文件也未发现什么异样,可还是不太确信,又使用360和腾讯的电脑管家都查了一遍还是没问题。
后来决定抓数据包检查,结果就发现猫腻了。
更多 »
font-family:中文字体的英文名称
宋体* SimSun
黑体* SimHei
微软雅黑* Microsoft YaHei
微软正黑体 Microsoft JhengHei
新宋体 NSimSun
新细明体 PMingLiU
细明体 MingLiU
标楷体 DFKai-SB
仿宋 FangSong
楷体 KaiTi
仿宋_GB2312 F angSong_GB2312
楷体_GB2312 K aiTi_GB2312
css 中中文字体(font-family)的英文名称
更多 »
MySQL数据整理耗时备忘
今天帮一个好朋友整理MySQL数据库,由于数据量比较大(580W+)耗时比较长,记录一下未以后再次遇到时可以预估一下维护时间^_^
当然时间也只是一个参考,不同服务器环境以及表的索引多少等等还是有一些差别的。
对容量为:126M的MyISAM表的主键进行 alter table ** order by key操作:
Query OK, 589713 rows affected (40.78 sec)
Records: 589713 Duplicates: 0 Warnings: 0
执行:Optimize,耗时:11.89s
对容量为:4.2G的MyISAM表的主键进行 alter table ** order by key操作:
Query OK, 5873759 rows affected (28 min 27.70 sec)
Records: 5873759 Duplicates: 0 Warnings: 0
执行:Optimize,耗时:57.89s
全部使用MySQL命令行方式。
[PHP]数组移除某个值的两种方式
php中从数组中移除某个值,可以有两种方式,一种是常规的遍历比值然后移除,另一种是利用array_diff函数。
先利用是利用遍历数组的方式写了个函数:
function array_delete_value($array,$delete_value){ foreach ( $array AS $k=>$v ) { if ( $v === $delete_value ) { unset($array[$k]); } } return $array; }
用法:array_delete_value(原数组,待移除的值);
两种方式的使用:
1.利用自定义函数:
<?php $del = ''; $t = 0; function array_delete_value($array,$delete_value){ foreach ( $array AS $k=>$v ) { if ( $v === $delete_value ) { unset($array[$k]); } } return $array; } for ( $i=1;$i<5000;$i++ ) { $s1 = microtime(true); $file2 = array('','net920','cn','','xxxx','kkkk','sdfasd','53453','sdfsadfsafddsaf',0); $file2 = array_delete_value($file2,$del); $s2 = microtime(true); $t = $t + ($s2-$s1); } echo number_format($t/$i,10); print_r($file2); ?>
2.利用array_diff函数:
<?php $del = ''; $t = 0; for ( $i=1;$i<5000;$i++ ) { $s3 = microtime(true); $file = array('','net920','cn','','xxxx','kkkk','sdfasd','53453','sdfsadfsafddsaf',0); $file = array_values(array_diff($file, array($del))); $s4 = microtime(true); $t = $t + ($s4-$s3); } echo number_format($t/$i,10); print_r($file); ?>
从效率上来说,使用自定义方式效率稍微高一点点,不多,呵呵。看情况来决定吧,自定义函数方式不会改变键名,第二种方式会改变键名。