分类目录归档:PHP

Mysql: Too many connections in …Session:Failed to write session data(files).两个问题的解决

近日在网上发现了这样一个问题,以前没有碰到过,如下图

问题一

mysql_connect(); too many connections in …connRadio.php错误信息,这个是mysql的运行错误问题,目前这个mysql也就是挂起状态的,这个错误是因为mysql的连接数超过了它设置的最大连接数。整个网站也就处于崩溃状态了。网上查找原因说是my.cnf(windows下为my.ini)文件里面的max_connections设置值太小的问题,直接更改为更大的值,如1000就行了。默认的linux上安装的mysql配置文件里面的max_connections 为100(本人暂未证实,来源于网上)mysql默认的my-medium.cnf,中型服务器配置。

[code]
[mysqld]
port = 3306
socket = /tmp/mysql.sock
skip-locking
key_buffer = 160M
max_allowed_packet = 1M
table_cache = 64
sort_buffer_size = 512K
net_buffer_length = 8K
read_buffer_size = 256K
read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 8M
max_connections=1000

[/code]

不过这个也与整体程序有关,很可能是mysql_connect()连接多次创建打开后,并没有使用mysql_close()进行关闭,导致连接越来越多,最后崩溃。上面的修改max_connections值,重启mysql服务器也只是权宜之计。真正需要修改的还有程序代码。目前普遍的开源cms或者blog都没有发现过这样类似的问题,一般对于数据库实例的实现是采用单例模式或者mysql_pconnect()永久连接(通常设计存在于一对一的分布而设计的,如单http服务器对于单mysql服务器,下面附php manual中对数据库永久链接的说明)。

 

问题二

failed:  No space left on device (28) 意思就是说磁盘空间不够用了。。。Failed write to session data(files) session文件不可写,如果没有空间了当然也就不可写了。我们知道php默认的session信息时写在服务器的临时目录中的,如/var/tmp,C:\WINDOWS\Temp,上面的使用的是系统默认的临时文件夹,所以应该不是权限问题导致不可写。至于空间不够用的问题,也可能随着短时间访问量暴增会增加很多session文件。而结合上面的mysql_connect()连接次数过多,出现这样的问题可能是短时间访问量过大导致

session可以通过gc_maxlefttime设置最大的生存周期,而php自身的GC(Garbage Collector)垃圾回收处理方式,防止内存溢出。当一个PHP线程结束时,当前占用的所有内存空间都会被销毁,当前程序中所有对象同时被销毁。GC进程一般都跟着每起一个SESSION而开始运行的。gc目的是为了在session文件过期以后自动销毁删除这些文件。

引用:http://developer.51cto.com/art/200912/168020.htm

有关详细的session与gc的运行关系

由于PHP的工作机制,它并没有一个daemon线程来定期的扫描Session信息并判断其是否失效,当一个有效的请求发生时,PHP 会根据全局变量 session.gc_probability和session.gc_divisor的值,来决定是否启用一个GC, 在默认情况下,session.gc_probability=1, session.gc_divisor =100也就是说有1%的可能性启动GC(也就是说100个请求中只有一个gc会伴随100个中的某个请求而启动).

PHP垃圾回收机制的工作就是扫描所有的Session信息,用当前时间减去session最后修改的时间,同session.gc_maxlifetime参数进行比较,如果生存时间超过gc_maxlifetime(默认24分钟),就将该session删除。
但是,如果你Web服务器有多个站点,多个站点时,GC处理session可能会出现意想不到的结果,原因就是:GC在工作时,并不会区分不同站点的session.

那么这个时候怎么解决呢?

1. 修改session.save_path,或使用session_save_path()让每个站点的session保存到一个专用目录,
2. 提供GC的启动率,自然,PHP垃圾回收机制的启动率提高,系统的性能也会相应减低,不推荐。
3. 在代码中判断当前session的生存时间,利用session_destroy()删除.

 

数据库永久连接

引用至php manual
永久的数据库连接是指在脚本结束运行时不关闭的连接。当收到一个永久连接的请求时。PHP 将检查是否已经存在一个(前面已经开启的)相同的永久连接。如果存在,将直接使用这个连接;如果不存在,则建立一个新的连接。所谓“相同”的连接是指用相同的用户名和密码到相同主机的连接。

对 web 服务器的工作和分布负载没有完全理解的读者可能会错误地理解永久连接的作用。特别的,永久连接不会在相同的连接上提供建立“用户会话”的能力,也不提供有效建立事务的能力。实际上,从严格意义上来讲,永久连接不会提供任何非永久连接无法提供的特殊功能。

为什么?

这和 web 服务器工作的方式有关。web 服务器可以用三种方法来利用 PHP 生成 web 页面。

第一种方法是将 PHP 用作一个“外壳”。以这种方法运行,PHP 会为向 web 服务器提出的每个 PHP 页面请求生成并结束一个 PHP 解释器线程。由于该线程会随每个请求的结束而结束,因此任何在这个线程中利用的任何资源(例如指向 SQL 数据库服务器的连接)都会随线程的结束而关闭。在这种情况下,使用永久连接不会获得任何地改变——因为它们根本不是永久的。

第二,也是最常用的方法,是把 PHP 用作多进程 web 服务器的一个模块,这种方法目前只适用于 Apache。对于一个多进程的服务器,其典型特征是有一个父进程和一组子进程协调运行,其中实际生成 web 页面的是子进程。每当客户端向父进程提出请求时,该请求会被传递给还没有被其它的客户端请求占用的子进程。这也就是说当相同的客户端第二次向服务端提出请求时,它将有可能被一个不同的子进程来处理。在开启了一个永久连接后,所有请求 SQL 服务的后继页面都能够重新使用这个已经建立的 SQL Server 连接。

最后一种方法是将 PHP 用作多线程 web 服务器的一个插件。目前 PHP 4 已经支持 ISAPI、WSAPI 和 NSAPI(在 Windows 环境下),这些使得 PHP 可以被用作诸如 Netscape FastTrack (iPlanet)、Microsoft’s Internet Information Server (IIS) 和 O’Reilly’s WebSite Pro 等多线程 web 服务器的插件。永久连接的行为和前面所描述的多过程模型在本质上是相同的。注意 PHP 3 不支持 SAPI。

如果永久连接并没有任何附加的功能,那么使用它有什么好处?

答案非常简单——效率。当客户端对 SQL 服务器的连接请求非常频繁时,永久连接将更加高效。连接请求频繁的标准取决于很多因素。例如,数据库的种类,数据库服务和 web 服务是否在同一台服务器上,SQL 服务器如何加载负载等。但我们至少知道,当连接请求很频繁时,永久连接将显著的提高效率。它使得每个子进程在其生命周期中只做一次连接操作,而非每次在处理一个页面时都要向 SQL 服务器提出连接请求。这也就是说,每个子进程将对服务器建立各自独立的永久连接。例如,如果有 20 个不同的子进程运行某脚本建立了永久的 SQL 服务器永久连接,那么实际上向该 SQL 服务器建立了 20 个不同的永久连接,每个进程占有一个。

注意,如果永久连接的子进程数目超过了设定的数据库连接数限制,系统将会产生一些缺陷。如果数据库的同时连接数限制为 16,而在繁忙会话的情况下,有 17 个线程试图连接,那么有一个线程将无法连接。如果这个时候,在脚本中出现了使得连接无法关闭的错误(例如无限循环),则该数据库的 16 个连接将迅速地受到影响。请查阅使用的数据库的文档,以获取关于如何处理已放弃的及闲置的连接的方法。

Warning
在使用永久连接时还有一些特别的问题需要注意。例如在永久连接中使用数据表锁时,如果脚本不管什么原因无法释放该数据表锁,其随后使用相同连接的脚本将会被永久的阻塞,使得需要重新启动 httpd 服务或者数据库服务。另外,在使用事务处理时,如果脚本在事务阻塞产生前结束,则该阻塞也会影响到使用相同连接的下一个脚本。不管在什么情况下,都可以通过使用 register_shutdown_function() 函数来注册一个简单的清理函数来打开数据表锁,或者回滚事务。或者更好的处理方法,是不在使用数据表锁或者事务处理的脚本中使用永久连接,这可以从根本上解决这个问题(当然还可以在其它地方使用永久连接)。

以下是一点重要的总结。永久连接是为通常连接建立一对一的分布而设计的。这意味着必须能够保证在将永久连接替换为非永久连接时,脚本的行为不会改变。使用永久连接将(非常)有可能改变脚本的效率,但不改变其行为!

kohana3.2部署到新浪SAE平台所需要的修改

近日学习用kohana框架,写了一个在线查字的小应用。在本地测试良好,效果图

主要实现的是按部首、按拼音查检索文字,搜索汉子查询。

主要业务逻辑很简单。预览地址请点击这里 现在部署在SAE平台上面。一些问题的参考文档来自这里

正常运行

本地测试完成代码,刚刚部署到SAE平台上时会出现这样的错误。

ErrorException [ Warning ]: Set the ini directive 'unserialize_callback_func' without permission

可以看到kohana完善的错误信息提示已经指向了APPPATH/bootstrap.php中得这一行

[code]

ini_set(‘unserialize_callback_func’, ‘spl_autoload_call’);

[/code]

这个是因为SAE平台禁用了ini_set()函数的原因,已经没有权限执行了。

解决办法就是直接注释,这个注释的影响是

“代码中使用了unserialize(),并且其解析的结果是一个对象,同时这个对象对应的类还没有定义。这种情况下就会导致一个错误。”来自上面那篇参考文章。

第二个错误则是日志、文件cache不能正常写入了。

Kohana_Exception [ 0 ]: Directory APPPATH/logs must be writable

这个是因为SAE平台禁止了程序对本地的文件进行操作,所以也就没有权限了。“唯一可以直接使用并提供了写入权限的是一个虚拟目录SAE_TMP_PATH。但是这个目录会在php脚本执行完后销毁,所以实际上并不能真正起到缓存的作用。”

解决办法 同样注释掉

[code]

Kohana::$log->attach(new Log_File(APPPATH.’logs’));

[/code]

这样则禁用了日志功能了,不过对于一般的程序来说没有太大的影响。

加入SAE的缓存目录常量

[code]

Kohana::init(array(
‘base_url’   => ‘/’,
‘index_file’ => ‘index.php’,
‘cache_dir’ => SAE_TMP_PATH // 这里
));

[/code]

至此如果你的程序不用缓存,那么配置好SAE平台的数据库连接参数等,程序就能正常访问了。

提示一下:

SAE的数据库参数hostname的常量,这个一定要注意,最好把SAE_MYSQL_PORT这个端口常量加上去,否则出现数据库连接不上的问题,但这个问题不容易被注意到,好吧,我就是好不容易才注意到的。SAE云平台的mysql端口不是默认的3306所以我刚开始时没有加上这个端口常量,想不出问题原因,最后登录sae后天,进入管理mysql数据库才看到,原来sae的mysql端口是3307

于是加上了这个端口常量,果然好了。。

[code]

‘hostname’   => SAE_MYSQL_HOST_M.’:’.SAE_MYSQL_PORT,
‘database’   => SAE_MYSQL_DB,
‘username’   => SAE_MYSQL_USER,
‘password’   => SAE_MYSQL_PASS,
‘persistent’ => FALSE,

[/code]

因为还有考虑到本地环境运行的问题;所以我再bootstrap.php中加入了SAE常量,值为true或false,true为sae,false为本地

最后bootstrap.ph的代码修改为

[code]

// 添加sae的环境控制,也能让程序在本地正常运行
define(‘SAE’, TRUE);

if( ! SAE){
define(‘SAE_TMP_PATH’, APPPATH.’/cache’);
}

/**
* 本地环境,非SAE平台的独立设置

*  注意这一段必须在 spl_autoload_register(array(‘Kohana’, ‘auto_load’)); 之后

*  否则Kohana类未加载情况下,调用$log会出错
*/
if( ! SAE ){

// SAE不支持ini_set函数的运行
ini_set(‘unserialize_callback_func’, ‘spl_autoload_call’);
// SAE暂不支持对文件夹进行文件写入,暂时关闭日志
Kohana::$log->attach(new Log_File(APPPATH.’logs’));

define(‘SAE_MYSQL_HOST_M’, ‘localhost’);
define(‘SAE_MYSQL_PORT’, ‘3306’);
define(‘SAE_MYSQL_DB’, ‘xhzd’);
define(‘SAE_MYSQL_USER’, ‘root’);
define(‘SAE_MYSQL_PASS’, ‘root’);

}

[/code]

使用SAE memcache 缓存

不过我的这个查字程序在部首;拼音列表,以及部首拼音相关的文字这些操作都用了缓存的。所以在sae上文件缓存是用不了了,但是还有memcache缓存啊。

因为SAE平台的memcache缓存启用不是原生的new memcache,而是memcache_init()所以程序还得改下。要改的地方比较简单。大致思路就是重写Kohana_Cache_Memcache的构造函数,重写初始化_memcache

modules\cache\classes\cache\memcache.php

[code]

class Cache_Memcache extends Kohana_Cache_Memcache {

public function __construct(array $config) {

parent::__construct($config);
// SAE平台则初始化sae平台memcache
if( SAE ){
$this->_memcache = memcache_init();
}

}

}

[/code]

不过还是有问题,在SAE平台上会显示 modules\cache\classes\kohana\cache\memcache.php

call undefined function   $this->_memcache->addServer() 估计也是被禁掉了。

那也好办注释掉就好了

[code]

/**
* 区别sae平台以及本地环境
*/
if( ! SAE){

// Add the memcache servers to the pool
foreach ($servers as $server)
{
// Merge the defined config with defaults
$server += $this->_default_config;

if ( ! $this->_memcache->addServer($server[‘host’], $server[‘port’], $server[‘persistent’], $server[‘weight’], $server[‘timeout’], $server[‘retry_interval’], $server[‘status’], $server[‘failure_callback’]))
{
throw new Cache_Exception(‘Memcache could not connect to host \’:host\’ using port \’:port\”, array(‘:host’ => $server[‘host’], ‘:port’ => $server[‘port’]));
}
}
}

[/code]

因为kohana默认采用的是文件缓存

所以在调用Cache::instance();前应当Cache::$default = 'memcache';

至此,memcache缓存就能正常的运行了。Kohana框架在SAE平台上的主要修改也完成,不过肯定还有一些不知道的问题,主要是对于SAE平台的不熟悉以及SAE平台处于安全考虑禁用的一些函数、方法等。

最后宣传下个人在sae上的这个应用地址欢迎访问http://xhzd.sinaapp.com/


centos6安装包过程中出现的问题

今天安装centos6后,准备测试下mysql的主从配置。因为centos6采用的是最小安装方式,所以好到安装包都没有。刚才也不知道是什么原因。

好久没有用了,linux命令又都快忘光了。首先还是网卡设置

更新yum源

其中默认是官方的源,不过我用的一般是163网易的源。

[code]

# CentOS-Base.repo
#
# This file uses a new mirrorlist system developed by Lance Davis for CentOS.
# The mirror system uses the connecting IP address of the client and the
# update status of each mirror to pick mirrors that are updated to and
# geographically close to the client.  You should use this for CentOS updates
# unless you are manually picking other mirrors.
#
# If the mirrorlist= does not work for you, as a fall back you can try the
# remarked out baseurl= line instead.
#
#

[base]
name=CentOS-$releasever – Base
baseurl=http://mirrors.163.com/centos/6/os/$basearch/
gpgcheck=1
gpgkey=http://mirrors.163.com/centos/RPM-GPG-KEY-CentOS-6

#released updates
[updates]
name=CentOS-$releasever – Updates
baseurl=http://mirrors.163.com/centos/6/updates/$basearch/
gpgcheck=1
gpgkey=http://mirrors.163.com/centos/RPM-GPG-KEY-CentOS-6

#packages used/produced in the build but not released
#[addons]
#name=CentOS-$releasever – Addons
#baseurl=http://mirrors.163.com/centos/$releasever/addons/$basearch/
#gpgcheck=1
#gpgkey=http://mirrors.163.com/centos/RPM-GPG-KEY-CentOS-6
#additional packages that may be useful
[extras]
name=CentOS-$releasever – Extras
baseurl=http://mirrors.163.com/centos/6/extras/$basearch/
gpgcheck=1
gpgkey=http://mirrors.163.com/centos/RPM-GPG-KEY-CentOS-6
#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever – Plus
baseurl=http://mirrors.163.com/centos/6/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=http://mirrors.163.com/centos/RPM-GPG-KEY-CentOS-6

[/code]

 

 

因为centos是最小化安装所以很多命令库都没有,要一一安装比如

-bash: wget: command not found 安装 wget
-bash: make: command not found 安装 make

还有编译工具如gcc等。这下就可以直接yum  install … 了。

不过总是有这个错误

/repomd.xml: [Errno 14] PYCURL ERROR 6 - ""】想不到原因,搜索得到一篇文章。centos yum 源 问题解析

其中的解释说了很清楚了“

此时聪明的我马上想到了是不是服务器解析不了域名了,导致repomd.xml下载不下来呢?

然后我就ping了一下mirrors.ustc.edu.cn , 果然出现错误:ping: unknown host mirrors.ustc.edu.cn。显然是DNS配置问题了,DNS域名服务器IP地址配的不对。”

解决办法:1、在其他机器上ping源镜像地址,把/etc/hosts里面 加了一行 mirrors.ustc.edu.cn  202.38.95.110,不过这是权宜之计 。2、推荐使用,需要配置正确的DNS。方法是:打开/etc/resolv.conf 文件,加入一行 nameserver ip。此处把ip换成IDC运营商给的DNS的地址就可以了。我的加上了google的dns地址 nameserver 8.8.8.8

这样yum 就可以正常下载,自动安装了。

然后就继续安装vsftpd,这里就是遇上了,执行make时,遇上command not found的问题;经查make包没有安装,yum直接安装上便好。

 

其中vsftd安装成功后,遇上553 Could not create file问题。经搜索得知。

可能一、是文件目录中的写入权限不够或者是目录所有者及用户组不对。可能二、/etc/vsftpd.conf 中write_enable属性是否为write_enable = yes

以新添加的username为例。

useradd -d /opt/ftp -g ftp-s /sbin/nologin username

1、其中 /opt/ftp的写入权限没有;chmod 755 /opt/ftp 即可

2、owner应该是username,group应该是ftp组;chown -v username:ftp /opt/ftp

 

在编译mysql中欧make时,遇到了

【/depcomp: line 571: exec: g++: not found】 这样的问题,查找gcc的已安装包

再查看一下本机上与gcc相关的安装包有哪些,缺少gcc-c++包
[code]

yum install gcc-c++ -y

[/code]

安装之后

再次进入mysql目录,make clean 再重新编译。

不过又碰到问题了。

【../include/my_global.h:1099: 错误:对 C++ 内建类型 ‘bool’ 的重声明】搜索得来的解决方案

“再次make && make install 后出现错误
../include/my_global.h:1099: 错误:对 C++ 内建类型 ‘bool’ 的重声明

这个错误 是不是你 先./congfigure 又 装的GCC 又make 的?

是的话 重新./configure  在make clean  make make install  就解决了”  网上好东西就是多,确实如此,真是要多分享啊。

 

还是mysql编译中,遇见了【xmalloc.h:29:31: 错误:readline/rlstdc.h】这样的问题,不过没有搜索到对应的解决方法。个人觉得刚才多次make && make install 后可能出现安装了,但部分内容没有卸载清除干净的问题,于是执行

[code]

[root@localhost mysql-5.0.81]# make uninstall

[root@localhost mysql-5.0.81]# make clean

[root@localhost mysql-5.0.81]# make && make install

[/code]

这次执行便成功了,没有问题了。

通过yuicompressor-2.4.7压缩css或js的php应用文件

yuicompressor这是个很好的工具,通过java库编译css或js文件进行压缩。压缩css或者js文件的好处是很多的,减少数据请求量,可以更快的进行数据传输,防止其他人进行窥探或整体直接挪用等等。。。

首先你要去下载一个yuicompressor现在最新版本是2.4.7 下载地址: yuicompressor  使用方法怎么工作在这里都有详细的说明,就不一一介绍了。

最常用的yuicompressor语法就是

[code]
java -jar yuicompressor-x.y.z.jar myfile.js -o myfile-min.js –charset utf-8
[/code]

其中需要注意的地方就是 如果不在yuicompressor-x.y.z.jar这个文件目录下,需要采用绝对的路径比如 E:/compressor/yuicompressor/build/yuicompressor-x.y.z.jar 这样的。同样需压缩文件myfile.js和压缩后输出的文件myfile-min.js 也是一样的采用绝对的路径。

好了,有了yuicompressor后;就要首先有一个java环境,不知道是否已安装java环境的可以通过 运行 ->cmd 输入


java -version

如果看到

java的版本结果就说明java的运行环境是ok的了。如果没有这个结果,不用担心可以去oracle官网去下载。如果觉得下载比较慢可以直接百度搜索java jdk下载,下载完成后下一步,下一步安装完成即可。

不出问题,你现在就可以正常的运行yuicompressor了,能够进行完成压缩文件了。

但是这样就出现了一个问题每次通过这样来执行,只能执行一个文件。我们的css和js文件通常有很多,不能一下完全执行,所以就写了一个小应用,直接输入本地的css和js目录就可以直接遍历压缩完成,这样就很省事了。

三个文件index.php ,index.tpl.html , do.php 很小

好吧,直接上码。

index.php


<?php
/**
* @author alex
* @time 2011年12月1日
* @todo php通过yuicompressor批量压缩css和js文件
* @email leiyu_ai@qq.com
*/
session_start();
require_once 'index.tpl.html';
?>

index.tpl.html


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>compressor js/css</title>

<style type="text/css">
body { font: 12px Microsoft Yahei, Verdana, Geneva, sans-serif, "宋体"; }
h1,h2,h4 { margin: 0; padding: 0; font-weight: normal;  }
input { border: 1px solid #eee; }

form span { display: inline-block; width: 80px; }
form h4 { margin-bottom: 10px; }
.go { border-color: #000; }
</style>
</head>

<body>
<?php
$_SESSION['rand'] = mt_rand(100,999);
?>
<form action="do.php" method="post">
<h4><span>css文件目录</span><input type="text" name="cssdir" /></h4>
<h4><span>js文件目录</span><input type="text" name="jsdir" /></h4>
<h4><input type="submit" name="go" value="提交" /><input type="hidden" name="rand" value="<?php echo $_SESSION['rand'];?>" /></h4>
</form>
</body>
</html>

do.php


<?php
/*
* 示例:我的yuicompressor-2.4.7.jar是放在这个地址下的,所以在运行前请更改为你的存放地址
* $cmd = "java -jar E:/compressor/yuicompressor-2.4.7/build/yuicompressor-2.4.7.jar --type js --charset utf-8 -o E:/tmp/js/home.min.js".
* " E:/tmp/js/home.js";
*/
session_start();
header('Content-type:text/html; charset=utf-8');

$rand = $_POST['rand'];
$srand = isset($_SESSION['rand'])? $_SESSION['rand']: '';
$submit = $_POST['go'];

if ($rand == $srand ){
if ($submit){
$jsdir = $_POST['jsdir'];
$cssdir = $_POST['cssdir'];
if ( !empty($jsdir) || !empty($cssdir)){
// 获取所有的文件集合
$jslist = getFileList($jsdir);
$csslist = getFileList($cssdir);
// 压缩js、css文件内容
$bool = doIt($jslist);
$boolc = doIt($csslist);

if ( $bool || $boolc){
echo $jsdir.'|'.$cssdir.' 目录执行成功';
}else{
echo $jsdir.'|'.$cssdir.' 目录执行失败';
}
}else {
echo '请输入css或js的文件目录';
}
echo '  <a href="'.$_SERVER['HTTP_REFERER'].'">返回首页</a>';
}
unset($_SESSION['rand']);
}

function getExt($file){
return strrev(substr(strrev($file), 0, strpos(strrev($file),'.')));
}

function getName ($file){
return strrev(substr(strrev($file), strpos(strrev($file),'.')+1 ));
}

function getPathFile($dir, $file){
return $dir.DIRECTORY_SEPARATOR.$file;
}

function doIt($list){

$tfile = $list[0][0];
$ext = getExt($tfile);
foreach($list as $key=>$val){
$cmd = "java -jar E:/compressor/yuicompressor-2.4.7/build/yuicompressor-2.4.7.jar --type {$ext} --charset utf-8 -o {$val[1]}".
" {$val[0]}";
exec($cmd, $output, $rv);
// 执行成功
if ( $rv == 0){
// 删除源文件
unlink($val[0]);
// 重命名新的压缩文件
rename($val[1], $val[0]);
}else {
$str .= $val[0].',';
}
}
if (!empty( $str)){
echo $str.' 执行失败';
return false;
}else {
return true;
}
}

function getFileList($dir){
$filelist = array();
if (is_dir($dir)){
$handle = opendir($dir);
while(($file = readdir($handle)) !== false){
if ( $file == '.' || $file == '..') continue;
$tmpdir = getPathFile($dir, $file);
if ( is_dir( $tmpdir)){
$rs = getFileList( $tmpdir);
if ( !empty($rs)){
$filelist = array_merge($filelist, $rs);
}

}else {
$filename = getName($file);
$ext = getExt($file);
$file = getPathFile($dir, $file); // 源文件完整路径
$minname = getPathFile($dir, $filename.'.min.'.$ext); // 压缩目标文件名称完整路径
$filelist[] = array($file, $minname);

}
}
closedir($handle);
return $filelist;
}else{
return false;
}
}

?>

ok完成。现在展示下我的测试结果

css文件

压缩前:                                                                            压缩后:

js 文件

压缩前:                                                                                    压缩后:

效果还是很明显的~~ ^_^

LNMP搭建中可能出现的一些问题及解决方法


在搭建的过程中出现很多问题,尽管以前装过几次,但也并不轻松。

首先系统安装好。这次我采用的是Centos5.6VM7.0环境

 

刚开始就出现了一个问题,系统安装好后,ssh竟然无法连接,照理说应该是默认已经安装好了的。

Ps –ef | grep ssh

也有程序运行。22端口也开了。网络连接dhcp自动分配地址,也是可以ping通的,telnet通信也是正常的。但ssh客户端就是怎么也连接不上。

 

我的错误状态和这位童鞋说的一模一样。

问题一   问题二

 

具体原因还是没有明白,最后系统重装,但依然如此,可能就是我机器的问题?!叫同事机器连接,果然就连接上了。很不明白。于是系统再次替换为Centos6.0

 

总结:ssh连接问题

1、  保证网络连接正常能ping

2、  Sshd服务器是启动状态

3、  22端口是打开的,或者暂时关闭防火墙测试

4、  采用telnet测试下

5、  多用几种客户端工具测试如putty,xshell等,多用其他的机器测试下。

6、  那就只好悲催的重装咯。。。

 

安装过程中可能产生的错误

 

Ps:在安装nginx或者php等得过程中,主要出现的问题都是缺少依赖包问题。一部分是程序数据路径错误等的问题,还有一部分是读写权限不够的问题。还有查找错误的时候不要只看报出来的错误信息,要多看更深层次的日志信息。

Tail –f  /var/log/messages

Tail –f  /var/log/mysqd.log

less /var/log/messages 

 

Nginx

安装加载ssl错误

***[/usr/local/ssl/.openssl/include/openssl/ssl.h] Error 2

 

with-pcre Nginxrewrite功能需要使用pcre库才能工作,而Nginx的编译参数里面的这个选项并不是像常规的那样指定pcre的安装目录,而是指定pcre源代码的目录。

参考

 

 

Mysql

error: Nocurses/termcap library found

解决:需要安装依赖库ncurses-5.2.tar.gz

 

[ERROR]Fatal error: Can’t open and lock privilege tables: Table ‘mysql.host’ doesn’texist

数据库的数据文件未找到所以无法找到打开权限表了。

解决:

mysql源目录中,运行初始化权限表的时候使用增加参数–datadir ,命令格式为:

scripts/mysql_install_db–user=mysql –datadir=/u01/mysql/data

参考 


 

libexec/mysqld:Can’t create/write to file ‘/var/run/mysqld/mysqld.pid’

无法创建或写入mysqld.pid文件。

解决:创建写入权限问题,如果没有mysqld目录则建立

mkdir/var/run/mysqld

chmod g+w /var/run/mysqld/

参考 


 

mysql启动错误

Startingmysqld daemon with databases from /var/lib/mysql
STOPPING server from pid file /var/run/mysqld/mysqld.pid
071112 00:22:06 mysqld ended

 

bin/mysqladmin:connect to server at ‘localhost’ failed

error:’Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock’ (2)

Checkthat mysqld is running and that the socket: ‘/tmp/mysql.sock’ exists!

分析:是/tmp/mysql.sock 不存在

解决:

# cd/var/lib/mysql/

由于mysql 默认的mysql.sock 是在/var/lib/mysql/mysql.sock,创建符号连接:

# ln -s/var/lib/mysql/mysql.sock /tmp/mysql.sock

 

参考  

 

 

GD库安装产生错误

GD库需要fontconfig依赖包所以需要安装

make[3]:*** [fcfreetype.lo] Error 1

../fontconfig/fcfreetype.h:27:22:error: ft2build.h: No such file or directory

解决:

./configure–with-freetype-config=/usr/local/freetype/bin/freetype-config,应该用freetype下的可执行程序来编译!

参考 

 

 

errorwhile loading shared libraries: libiconv.so.2: cannot open shared object file:No such file or directory

解决:

但是在/usr/local/lib下却能找到libiconv.so.2,解决方法是将/usr/local/lib路径添加到/etc/ld.so.conf文件中,然后用sudo ldconfig命令加载,再重新输入sudo make install命令就可以了。

参考一   参考二 


 

PHP

libxml2未找到

Consideradjusting the PKG_CONFIG_PATH environment variable if you

installedsoftware in a non-standard prefix.

 

Alternatively,you may set the environment variables LIBXML2_CFLAGS

andLIBXML2_LIBS to avoid the need to call pkg-config.

See thepkg-config man page for more details.

解决:

已经安装好了libxml2库,但环境变量未设置好。

确定 /usr/local/libxml2/lib/pkgconfig 目录下有 libxml-2.0.pc

exportPKG_CONFIG_PATH=/usr/local/libxml2/lib/pkgconfig:$PKG_CONFIG_PATH

再次make install

参考

 

ldap这个包始终没有安装成功,在安装过程中包一个又一个的依赖,明明已经安装了包却还是报告你必须先安装某些包。。。都已经搞晕了。

configure:error: Cannot find ldap.h

缺少openldap

参考


解决:暂无

error:BDB/HDB: BerkeleyDB not available

缺少依赖包BerkeleyDB

参考

解决:暂无

 

Make: *** [sapi/cgi/php-cgi.exe] Error 1

解决:缺少libiconv

 

Make test 错误

ERROR:invalid PHP executable specified by TEST_PHP_EXECUTABLE  = /opt/software/lamp/php-5.2.17/sapi/cli/php

解决:直接忽略 make install

参考

 

 

zend studio 7.2.1编码时的错误

zend studio正编码时,“编写后,保存”发生了这样的错误 an internal error occurred during: “Processiong Dirty Regions”

继而查看workspace里的日志详细信息。

看的不是很明白。于是想可能是zendstudio本身的问题,于是就卸载重装了。但是之后继续编写这个php时,还是有这个问题。

只好问一下老大了,果断得出结论,是因为php类继承父类的类名问题!

我的这个父类名称是很普通的

<?php

class indexFE extends indexPB{

}

?>

这个情况下就出现如上的问题。但如果把”indexPB”替换成”indexPBs”或其它的字符,就不会出现这个问题了。只好改为其它名称,继续完成该页面其它的代码后,在更改回来。

但有哪些类名是可能会引起这样的错误,目前也还不清楚,我想这个可能也是与程序整体的编写代码有关。

Zend Studio代码不能自动提示的修复解决方法

源地址:http://www.jb51.net/softjc/29359.html

这次用zend studio 7.2用的好好的,就是不知什么时候没有了代码提示。

找到上面这篇文章。

解决方案:

1、找到zend studio下的工作空间的路径“[your wrokspace name]\.metadata\.plugins\org.eclipse.core.runtime\.settings”

2、删除该文件夹下的“org.eclipse.dltk.ui.prefs”文件;或者打开该文件

可以看到上图中所选择的这段话,然后删掉,保存,重启zend studio。不出问题就ok了。

之前也有过这样的问题:关于zend studio 代码自动补全不能正常显示的原因

 

 

Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE

在编码过程中,出现了这样的一个错误:Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting T_STRING or T_VARIABLE or T_NUM_STRING in…

源码测试:

<?php
    header(“Content-type:text/html; charset=utf-8”);
    echo 123,’沃尔沃’; //注意格式

   //注意这个里的action里的值
    echo “<form action=\”$_SERVER[‘PHP_SELF’]\” method=\”post\”>请输入:<input type=\”text\”/> </form>”;
?>

1、接触php这么久,没想到echo输出还有这样的写法。echo 输出内容还能以”,”逗号间隔的输出。以前几乎重没留意过。。。之前只了解echo 对单引号与双引号的区别。

 

2、上面那个错误则是action=\”$_SERVER[‘PHP_SELF’]\”这个格式造成的。解决方案则是加上action=\”{$_SERVER[‘PHP_SELF’]}\” 

有关大括号{} 的应用则是,在字符串中隔开变量与字符的作用。 还有如:$str = ‘abc’; echo $str{1}; 不过中文字符因为编码原因不能显示。

 

网上的有关信息:

     将多个独立语句合并为一个复合语句,例如 if … else …中经常如此使用
    在变量间接引用中进行定界,避免歧义。例如 ${$my_var[8]}与${$my_var}[8]的区分
    用于指示字符串变量中的单个字符(下标从0开始),例如
   $my_str=”1234″;
   $my_str{1}=’5′;  //现在 $my_str 内容为 ‘1534’
    此用法为 5之后的特性,用于消除使用中括号引起的歧义

 

 

Access denied for agent changed,uc错误解答

地址:xixian.ha.cn/home/space.php 汗点不开。我在快照里面看的。
主要东东》

UC/model/base.php 中校验的http_user_agent是在模拟提交的过程中的当前客户浏览器的user agent ,

如果在模拟提交过程中,没有将当前用户的useragent提交上去的话,那么UC在

uc/model/base.php 中的 init_input方法获取到的http_user_agent将会是应用服务器当前系统的默认useragent,

而不是客户端的http_user_agent,从而导致http_user_agent 校验失败,而无法正常通信。

附图一张:/uc_server/model/base.php  init_put()函数

======

还可以看看faq.comsenz.com/viewnews-204 的解答。

——————————————————————–

出现这样的原因是该应用的appid 与ucenter配置的应用项不相同造成的。修改本应用的config.inc.php里的UC_APPID与ucenter里的一致就好了。

不过这样有可能导致这样的错误Error:Unknown column ‘app1’ in ‘where clause’  可能是discuz的一个小bug吧。这个问题也有很多人问。

php配置optimizer&&debuger;

zend_extension="D:\Program Files\Zend\ZendOptimizer-3.3.0\lib\ZendExtensionManager.dll"
zend_extension_ts="D:\Program Files\Zend\ZendOptimizer-3.3.0\lib\ZendExtensionManager.dll"

zend_extension_manger.optimizer="D:\Program Files\Zend\ZendOptimizer-3.3.0\lib\Optimizer-3.3.0"
zend_extension_manager.optimizer_ts="D:\Program Files\Zend\ZendOptimizer-3.3.0\lib\Optimizer-3.3.0"

zend_extension_manager.debug_server="D:\Program Files\wamp\PHP\debugger"
zend_extension_manager.debug_server_ts="D:\Program Files\wamp\PHP\debugger";

关于评论的无限引用结构的一点认识

前几日,需要做到一个评论系统;要求在普通的评论功能基础上加上,能够无限引用的功能,即“盖楼”。那就做吧。。。

首先普通的评论,很简单;知道数据库设计的一般都知道。但现在是需要类似“盖楼”这样的情况;所以,没了头绪,Google,baidu。

找到一篇牛人文章:自反+递归 实现评论的无限引用 
不得不说牛人就是牛人,对数据库表设计真是的很有见解的。大家可以去看看,现在结合我所面对的说我自己的理解吧(当然是看过这篇文章后额。^-^)

术语:初始评论:表示这个评论没有引用其他任何评论。
引用评论:表示这个评论包含对其他评论的引用。  (引用自以上博文)

类似“盖楼”的评论结构,大体上有两种模式。

一、传统模式
如下表结构:

Cm_feedback         留言表

              Id    

              Article_id    –文章id

              Archive_title  –文章标题

              Userid   –用户id

              Username  –用户名

              Ip   –ip

              Ischeck   –是否审核

              Dtime    –发表时间

              Good    –支持数

              Msg     –留言内容

效果图

这个评论存储不论是初始评论,还是引用评论都存放到msg这个字段中。这样的好处就是方便存储,业务逻辑清晰,存入取出;不合理的地方呢就是要是某条评论被删除了,但某条评论的引用中却还存在这段内容。所以这样审核就比较关键,要保证展示出来的评论,都是能够被引用的。如果是十几楼,二十几楼这样很多的内容,那么都是重复的,所以就很占数据库空间;其次这些都是html代码,所以存入数据库时还要把html正则匹配替换为分隔符,然后再存入数据库;所以缺点也是很明显的。
示例:
css
<style type="text/css" >

*{margin:0;padding:0;}

body{margin:10px;font-size:14px;font-family:宋体}

h1{font-size:26px;margin:10px 0 15px;}

#commentHolder{width:540px;border-bottom:1px solid #aaa;}

.comment{padding:5px 8px;background:#f8fcff;border:1px solid #aaa;font-size:14px;border-bottom:none;}

.comment p{padding:5px 0;}

.comment p.title{color:#1f3a87;font-size:12px;}

.comment p span{float:right;color:#666}

.comment div{background:#ffe;padding:3px;border:1px solid #aaa;line-height:140%;margin-bottom:5px;}

.comment div span{color:#1f3a87;font-size:12px;}

</style>

html
<div class=’comment’>

<p class=’title’><span>2008-3-24 16:33:49 发表</span>内蒙古网友</p>

<div>

<div>



<div><span>广州网友 原贴:</span><br />

向马XX同志荣升台湾省省长表示祝贺!

</div>



<span>四川网友 原贴:</span><br />

四川人民发来贺电!

</div>



<span>陕西西安网友 原贴:</span><br />

陕西网友发来贺电  

</div>





<p>内蒙网友发来贺电</p>

</div>

共同点是明显的。我是这样匹配的。
{quote}

{quote}



{quote}

{title}广州网友 原贴:{/title}

向马XX同志荣升台湾省省长表示祝贺!

{/quote}



{title}四川网友 原贴:{/title}

四川人民发来贺电!

{/quote}



{title}陕西西安网友 原贴:{/title}

陕西网友发来贺电!



{/quote}



{content}内蒙网友发来贺电{/content}

就是  <div>  => {quote} ; </div>  =>{/quote} ; <span> => {title}  ;</span><br/>  =>{/title}  ;<p>  =>{content} ;</p> =>{/content}  一一对应。
这个方案的优缺点:
优点:1、方便存储很写入,
2、业务逻辑清晰简单,写入,取出。
缺点:1、占用数据库空间;
2、html代码正则匹配有点麻烦。
3、不能删除已被删除评论的引用内容。

虽然比较麻烦。但是我还是采用了这个模式。关键还是业务逻辑比较简单,服务器压力比较小。

二、自反模式:
先看表结构:

Cm_feedback         留言表

              Id    

              Article_id    –文章id

              Archive_title  –文章标题

              Userid   –用户id

              Username  –用户名

              Ip   –ip

              Ischeck   –是否审核

              Dtime    –发表时间

              Good    –支持数

              Msg     –留言内容

              commentid  –评论id 

可以看到表结构和上面比起来,就是多了一个commentid字段。这个字段就是本身的外键,相当于自己引用自己。初始评论的commentid默认为0,而引用评论的commentid则是对应的其他评论的id。默认为0时,只有评论内容,不包含引用分隔符。commentid不等于0时,则查找commentid=id的评论,然后再次验证被查找id评论的commentid是否为0,如果为0则停止;果然不为0则继续查找,直到找到commentid=0的评论记录为止。

业务逻辑:
写出一方法或函数。据id 来获取对应的记录,即可获得commentid的值;然后判断commentid是否等于0,如等于则退出返回记录显示;如不等于则把commentid作为参数调用方法或函数本身。即递归。
示例:
//返回一条评论记录
function getComment($id){

             return $rs;             
}

//递归函数,调用getcomment()
function comment($id){

$rs = getComment($id);

          if( $rs[‘commentid’] ==0){         //初始评论

                     return $rs;

          }else{

                    $rs = comment( $rs[‘commentid’]);

                    $comm[] = $rs;

                    return $comm;

          }

}

commentid!=0这个情况,那么这个$rs应该存放在一个list中。在php里即数组中,那么就存放在数组$comm中;$comm就是一个二维数组了。而这些返回的二维数组然后再与只有一条评论的记录组合成一个数组,即初始评论与引用评论这个二维数组一起组合成为一个新的数组,从而把这个数组返回到前台页面展示;相当于把引用评论的二维数组当做了一条普通的评论记录,在页面展示中在加上上面的html。
这个也是我自己的想法,不知道是否与上面的大牛有出入,仅供各位参考,如有不正之处,请指出。

第二方案优缺点:
优点:1、很方便的管理每一条评论。如审核不当也可以随时删除该条评论。
2、数据库空间占用很小;不存在评论内容重复情况。
缺点:1、因为使用的递归操作,如果有几十楼层那样的情况,那么会很占服务器资源。
2、逻辑不是那么清晰;个人感觉很绕人。

centos IPTables配置方法[转]

源地址:centos IPTables配置方法

注:红色字体是我的个人解读;

需要的命令:
查看配置情况 iptables -L -n
记得保存 /etc/init.d/iptables save
添加input记录 iptables -A INPUT -p tcp —dport 22 -j ACCEPT
添加output记录 iptables -A OUTPUT -p tcp –sport 22 -j ACCEPT
一些软件的默认端口:
ftp用到端口是 20 21
ssh 端口是 22
http端口是 80
telnet端口是 23
rsync端口是 873
svn 端口3690
pop3端口110
smtp端口25
dns端口53
mysql端口3306
nfs端口111
大概常用的就这些,其他的可查看具体软件
1、查看本机关于 IPTABLES的设置情况

[root@tp ~]# iptables -L -n

Chain INPUT (policy ACCEPT)

target prot opt source destination

Chain FORWARD (policy ACCEPT)

target prot opt source destination

Chain OUTPUT (policy ACCEPT)

target prot opt source destination

Chain RH-Firewall-1-INPUT (0 references)

target prot opt source destination

ACCEPT all — 0.0.0.0/0 0.0.0.0/0

ACCEPT icmp — 0.0.0.0/0 0.0.0.0/0 icmp type 255

ACCEPT esp — 0.0.0.0/0 0.0.0.0/0

ACCEPT ah — 0.0.0.0/0 0.0.0.0/0

ACCEPT udp — 0.0.0.0/0 224.0.0.251 udp dpt:5353

ACCEPT udp — 0.0.0.0/0 0.0.0.0/0 udp dpt:631

ACCEPT all — 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED

ACCEPT tcp — 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22

ACCEPT tcp — 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:80

ACCEPT tcp — 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:25

REJECT all — 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited

可以看出我在安装linux时,选择了有防火墙,并且开放了22,80,25端口.

如果你在安装linux时没有选择启动防火墙,是这样的

[root@tp ~]# iptables -L -n

Chain INPUT (policy ACCEPT)

target prot opt source destination

Chain FORWARD (policy ACCEPT)

target prot opt source destination

Chain OUTPUT (policy ACCEPT)

target prot opt source destination

什么规则都没有.

2、清除原有规则.

注意:清楚规则之前,应该保留ssh的规则。不然清楚了所有的规则链,则ssh都连不上去了。

不管你在安装linux时是否启动了防火墙,如果你想配置属于自己的防火墙,那就清除现在filter的所有规则.

[root@tp ~]# iptables -F 清除预设表filter中的所有规则链的规则

[root@tp ~]# iptables -X 清除预设表filter中使用者自定链中的规则

我们在来看一下

[root@tp ~]# iptables -L -n

Chain INPUT (policy ACCEPT)

target prot opt source destination

Chain FORWARD (policy ACCEPT)

target prot opt source destination

Chain OUTPUT (policy ACCEPT)

target prot opt source destination

什么都没有了吧,和我们在安装linux时没有启动防火墙是一样的.(提前说一句, 这些配置就像用命令配置IP一样,重起就会失去作用),怎么保存.

[root@tp ~]# /etc/rc.d/init.d/iptables save

这样就可以写到/etc/sysconfig/iptables文件里了.写入后记得把防火墙重起一下,才能起作用.

[root@tp ~]# service iptables restart

现在IPTABLES配置表里什么配置都没有了,那我们开始我们的配置吧。

3、设定预设规则

注意:这里的 -p 应该是 -P ,p应该是大写,要不然会报错unknown protocol `input’ specified

[root@tp ~]# iptables -p INPUT DROP

[root@tp ~]# iptables -p OUTPUT ACCEPT

[root@tp ~]# iptables -p FORWARD DROP

上面的意思是,当超出了IPTABLES里filter表里的两个链规则 (INPUT,FORWARD)时,不在这两个规则里的数据包怎么处理呢,那就是DROP(放弃).应该说这样配置是很安全的.我们要控制流入数据包

而对于OUTPUT链,也就是流出的包我们不用做太多限制,而是采取ACCEPT, 也就是说,不在着个规则里的包怎么办呢,那就是通过.

可以看出INPUT,FORWARD两个链采用的是允许什么包通过,而OUTPUT 链采用的是不允许什么包通过.

这样设置还是挺合理的,当然你也可以三个链都DROP,但这样做我认为是没有必要的,而且要写的规则就会增加.但如果你只想要有限的几个规则是,如只做WEB服务器.还是推荐三个链都是DROP.

注:如果你是远程SSH登陆的话,当你输入第一个命令回车的时候就应该掉了.因为你没有设置任何规则.

怎么办,去本机操作呗!

4、添加规则.

首先添加INPUT链,INPUT链的默认规则是DROP,所以我们就写需要 ACCETP(通过)的链

为了能采用远程SSH登陆,我们要开启22端口.

注意:这里的–dport ,应该是 –dport ;下面的 –sport 也是一样;

[root@tp ~]# iptables -A INPUT -p tcp –dport 22 -j ACCEPT

[root@tp ~]# iptables -A OUTPUT -p tcp –sport 22 -j ACCEPT (注:这个规则,如果你把OUTPUT 设置成DROP的就要写上这一部,好多人都是望了写这一部规则导致,始终无法SSH.在远程一下,是不是好了.

其他的端口也一样,如果开启了web服务器,OUTPUT设置成DROP的话,同样也要添加一条链:

[root@tp ~]# iptables -A OUTPUT -p tcp –sport 80 -j ACCEPT ,其他同理.)

如果做了WEB服务器,开启80端口.

[root@tp ~]# iptables -A INPUT -p tcp –dport 80 -j ACCEPT

如果做了邮件服务器,开启25,110端口.

[root@tp ~]# iptables -A INPUT -p tcp –dport 110 -j ACCEPT

[root@tp ~]# iptables -A INPUT -p tcp –dport 25 -j ACCEPT

如果做了FTP服务器,开启21端口

[root@tp ~]# iptables -A INPUT -p tcp –dport 21 -j ACCEPT

[root@tp ~]# iptables -A INPUT -p tcp –dport 20 -j ACCEPT

如果做了DNS服务器,开启53端口

[root@tp ~]# iptables -A INPUT -p tcp –dport 53 -j ACCEPT

如果你还做了其他的服务器,需要开启哪个端口,照写就行了.

上面主要写的都是INPUT链,凡是不在上面的规则里的,都DROP

允许icmp包通过,也就是允许ping,

[root@tp ~]# iptables -A OUTPUT -p icmp -j ACCEPT (OUTPUT设置成DROP的话)

[root@tp ~]# iptables -A INPUT -p icmp -j ACCEPT (INPUT设置成DROP的话)

允许loopback!(不然会导致DNS无法正常关闭等问题)

IPTABLES -A INPUT -i lo -p all -j ACCEPT (如果是INPUT DROP)

IPTABLES -A OUTPUT -o lo -p all -j ACCEPT(如果是OUTPUT DROP)

下面写OUTPUT链,OUTPUT链默认规则是ACCEPT,所以我们就写需要 DROP(放弃)的链.

减少不安全的端口连接

[root@tp ~]# iptables -A OUTPUT -p tcp –sport 31337 -j DROP

[root@tp ~]# iptables -A OUTPUT -p tcp –dport 31337 -j DROP

有些些特洛伊木马会扫描端口31337到31340(即黑客语言中的 elite 端口)上的服务。既然合法服务都不使用这些非标准端口来通信,阻塞这些端口能够有效地减少你的网络上可能被感染的机器和它们的远程主服务器进行独立通信的机会

还有其他端口也一样,像:31335、27444、27665、20034 NetBus、9704、137-139(smb),2049(NFS)端口也应被禁止,我在这写的也不全,有兴趣的朋友应该去查一下相关资料.

当然出入更安全的考虑你也可以包OUTPUT链设置成DROP,那你添加的规则就多一些,就像上边添加

允许SSH登陆一样.照着写就行了.

下面写一下更加细致的规则,就是限制到某台机器

如:我们只允许192.168.0.3的机器进行SSH连接

[root@tp ~]# iptables -A INPUT -s 192.168.0.3 -p tcp –dport 22 -j ACCEPT

如果要允许,或限制一段IP地址可用 192.168.0.0/24 表示192.168.0.1-255端的所有IP.

24表示子网掩码数.但要记得把 /etc/sysconfig/iptables 里的这一行删了.

-A INPUT -p tcp -m tcp –dport 22 -j ACCEPT 因为它表示所有地址都可以登陆.

或采用命令方式:

[root@tp ~]# iptables -D INPUT -p tcp –dport 22 -j ACCEPT

然后保存,我再说一边,反是采用命令的方式,只在当时生效,如果想要重起后也起作用,那就要保存.写入到/etc/sysconfig/iptables文件里.

[root@tp ~]# /etc/rc.d/init.d/iptables save

这样写 !192.168.0.3 表示除了192.168.0.3的ip地址

其他的规则连接也一样这么设置.

在下面就是FORWARD链,FORWARD链的默认规则是DROP,所以我们就写需要ACCETP(通过)的链,对正在转发链的监控.

开启转发功能,(在做NAT时,FORWARD默认规则是DROP时,必须做)

[root@tp ~]# iptables -A FORWARD -i eth0 -o eth1 -m state –state RELATED,ESTABLISHED -j ACCEPT

[root@tp ~]# iptables -A FORWARD -i eth1 -o eh0 -j ACCEPT

丢弃坏的TCP包

[root@tp ~]#iptables -A FORWARD -p TCP ! –syn -m state –state NEW -j DROP

处理IP碎片数量,防止攻击,允许每秒100个

[root@tp ~]#iptables -A FORWARD -f -m limit –limit 100/s –limit-burst 100 -j ACCEPT

设置ICMP包过滤,允许每秒1个包,限制触发条件是10个包.

[root@tp ~]#iptables -A FORWARD -p icmp -m limit –limit 1/s –limit-burst 10 -j ACCEPT

我在前面只所以允许ICMP包通过,就是因为我在这里有限制。
配置一个NAT表放火墙

1、查看本机关于NAT的设置情况

[root@tp rc.d]# iptables -t nat -L

Chain PREROUTING (policy ACCEPT)

target prot opt source destination

Chain POSTROUTING (policy ACCEPT)

target prot opt source destination

SNAT all — 192.168.0.0/24 anywhere to:211.101.46.235

Chain OUTPUT (policy ACCEPT)

target prot opt source destination

我的NAT已经配置好了的(只是提供最简单的代理上网功能,还没有添加防火墙规则).关于怎么配置NAT,参考我的另一篇文章

当然你如果还没有配置NAT的话,你也不用清除规则,因为NAT在默认情况下是什么都没有的

如果你想清除,命令是

[root@tp ~]# iptables -F -t nat

[root@tp ~]# iptables -X -t nat

[root@tp ~]# iptables -Z -t nat

2、添加规则

添加基本的NAT地址转换,(关于如何配置NAT可以看我的另一篇文章),

添加规则,我们只添加DROP链.因为默认链全是ACCEPT.

防止外网用内网IP欺骗

[root@tp sysconfig]# iptables -t nat -A PREROUTING -i eth0 -s 10.0.0.0/8 -j DROP

[root@tp sysconfig]# iptables -t nat -A PREROUTING -i eth0 -s 172.16.0.0/12 -j DROP

[root@tp sysconfig]# iptables -t nat -A PREROUTING -i eth0 -s 192.168.0.0/16 -j DROP

如果我们想,比如阻止MSN,QQ,BT等的话,需要找到它们所用的端口或者IP, (个人认为没有太大必要)

例:

禁止与211.101.46.253的所有连接

[root@tp ~]# iptables -t nat -A PREROUTING -d 211.101.46.253 -j DROP

禁用FTP(21)端口

[root@tp ~]# iptables -t nat -A PREROUTING -p tcp –dport 21 -j DROP

这样写范围太大了,我们可以更精确的定义.

[root@tp ~]# iptables -t nat -A PREROUTING -p tcp –dport 21 -d 211.101.46.253 -j DROP

这样只禁用211.101.46.253地址的FTP连接,其他连接还可以.如 web(80端口)连接.

按照我写的,你只要找到QQ,MSN等其他软件的IP地址,和端口,以及基于什么协议,只要照着写就行了.

最后:

drop非法连接

[root@tp ~]# iptables -A INPUT -m state –state INVALID -j DROP

[root@tp ~]# iptables -A OUTPUT -m state –state INVALID -j DROP

[root@tp ~]# iptables-A FORWARD -m state –state INVALID -j DROP

允许所有已经建立的和相关的连接

[root@tp ~]# iptables-A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT

[root@tp ~]# iptables-A OUTPUT -m state –state ESTABLISHED,RELATED -j ACCEPT

[root@tp ~]# /etc/rc.d/init.d/iptables save

这样就可以写到/etc/sysconfig/iptables文件里了.写入后记得把防火墙重起一下,才能起作用.

[root@tp ~]# service iptables restart

别忘了保存,不行就写一部保存一次。你可以一边保存,一边做实验,看看是否达到你的要求,

【转】解决PHP使用json_encode函数中文转换的一些问题

原地址yuninglovekefan.blog.sohu.com/156824420.html

本文讲一下PHP中两个函数json_encode 和 json_decode,在使用json_encode 时中文无法转换的解决方案,本文假设文件所用的编码为gb2312;

先写出所需的数组

<?php
$json = array (
0 =>
array (
‘id’ => ’13’,
‘name’ => ‘乒乓球’,
),
1 =>
array (
‘id’ => ’17’,
‘name’ => ‘篮球’,
)
)
?> 

如果直接用PHP json_encode函数

<?php
echo json_encode($json);
?> 

结果为:

<?php
[{"id":"13","name":null}
,{"id":"13","name":null}]
?> 

可以看到汉字没有被转义都为null,这是因为json仅仅转义encoding编码(类似于:%B0%AE),故上面语句应该先转换编码

<?php
foreach ($ajax as $key=>$val)
{
$ajax[$key][‘name’] =
urlencode($val[‘name’]);
}
echo json_encode($json);
?> 

客户端js代码

<script type="text/javascript">
function getsort(obj)
{
$.ajax(
{
type : "GET",
url : "< ?=$this->baseUrl?>/index/getajax",
data : "c=" obj.value,
success : function(json)
{
var json=eval(json);
var html = ‘< select>’;
$.each(json, function(k)
{
html = ‘< option value="’
json[k][‘id’] ‘">’
decodeURI(json[k][‘name’]) ‘< /option>’;
});
html ="< /select>";
$(‘#sort’).html(html);
}
}
)
}
</script> 

用上面的代码js会报错 说编码不符合标准

原因是因为js 中decodeURI 仅仅支持utf8 转码。所以 ,PHP json_encode函数的代码应该为下面的代码

<?php
foreach ($ajax as $key=>$val)
{
$ajax[$key][‘name’] =
urlencode(iconv(‘gb2312’,
‘utf-8’,$val[‘name’]));
}
echo json_encode($json);
?> 

以上就是使用PHP json_encode函数在实际操作中出现问题的解决方法。

ps:

今天碰到的一问题。开始是为空,然后是乱码怎么转都不行,原来忽略了他人的网页编码是gb2312的。

php对js传递来的escape中文编码进行读取

原地址:www.laohucheng.com/blog/post/279/

据说js escape后的编码默认是utf-8 【所以如果你的页面是gb2312的,解码成功后记得iconv进行编码转换,不然中文还是乱码】。有些人可能会说了,那我直接不编码就传到目标页总可以 吧。如果是js拼凑地址后进行的访问,我测试了还是不行的,如果是表单提交或许可以,我没试。这里在页面编码保持一致的情况下,我们只能利用php写一个 功能恰似js中unescape的方法来进行处理了,方法如下:

//处理JS escape 过来的中文
function js_unescape($str)
{
$ret = ”;
$len = strlen($str); for ($i = 0; $i < $len; $i++)
{
if ($str[$i] == ‘%’ && $str[$i+1] == ‘u’)
{
$val = hexdec(substr($str, $i+2, 4));     if ($val < 0x7f) $ret .= chr($val);
else if($val < 0x800) $ret .= chr(0xc0|($val>>6)).chr(0x80|($val&0x3f));
else $ret .= chr(0xe0|($val>>12)).chr(0x80|(($val>>6)&0x3f)).chr(0x80|($val&0x3f));     $i += 5;
}
else if ($str[$i] == ‘%’)
{
$ret .= urldecode(substr($str, $i, 3));
$i += 2;
}
else $ret .= $str[$i];
}
return $ret;
}
// 这个函数就处理了js escape过来的中文编码,但是如果你是utf-8编码的,那么还是乱码,需要再进行下一步操作 $str=iconv(‘utf-8′,’gb2312’,$str)到这里才正真处理完成。现在你就可以试下了,效果绝对OK ,顺便提一下的几个方法,依次为中英文混合截字符串,判断是否中文,php模拟js escape方法。

// start 开始位置,从0开始
// long = 0 则从start 一直取到字符串尾
// ltor = true 时从左到右取字符,false 时到右到左取字符
// $cn_len 中文字符按字节取还是字数取,如果按字数取,则一个中文当一个字节计算

function csubstr(&$str, $start=0, $long=0, $ltor=true, $cn_len=2) {
if($long == 0) $long = strlen($str);
if($ltor == false) $str = cstrrev($str);
if($cn_len == 1) {
for($i=0, $fs=0; $i<$start; $fs++)
$i += (ord($str[$fs]) <= 0xa0) ? 1 : 0.5;
for($i=0, $fe=$fs; $i<$long; $fe++)
$i += (ord($str[$fe]) <= 0xa0) ? 1 : 0.5;
$long = $fe – $fs;
}
else {
$fs = (is_chinese($str, $start) == 1) ? $start – 1 : $start;
$fe = $long + $start – 1;
$end = ( is_chinese($str, $fe) == -1 ) ? $fe -1 : $fe;
$long = $end – $fs + 1;
}
$f_str = substr($str, $fs, $long);
if($ltor == false) $f_str = cstrrev($f_str);
return $f_str;
}

function is_chinese(&$str, $location) {
$ch = true;
$i = $location;
while(ord($str[$i])>0xa0 && $i >= 0) {
$ch = !$ch;
$i –;
}
if($i != $location) {
$f_str = $ch ? 1: -1;
}
else {
$f_str = false;
}
return $f_str;
}

//php模拟js的escape
function phpescape($str)
{
$sublen=strlen($str);
$retrunString="";
for ($i=0;$i<$sublen;$i++)
{
if(ord($str[$i])>=127)
{
$tmpString=bin2hex(iconv("gb2312","ucs-2",substr($str,$i,2)));
//$tmpString=substr($tmpString,2,2).substr($tmpString,0,2);window下可能要打开此项
$retrunString.="%u".$tmpString;
$i++;
} else {
$retrunString.="%".dechex(ord($str[$i]));
}
}
return $retrunString;
}

用 Json 来实现 PHP 与 JavaScript 间数据交换

原地址:www.nowamagic.net/php/php_UseJsonPassData.php

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。

简而论之,不管是xml还是json都是为了方便在客户端与服务器端交互数据的中转站,特别是用于对象型数据,比如最常见的数组。

下面将分别将数组从php传送给javascript,以及将数组从javascript传送给php 示例说明,例子比较简单,明白概念即可。不管从php传送给javascript,还是javascript传送给php,json在传送之前都会将对象 扁平化即一维化为字符串。

PHP 向 JavaScript 传值

PHP 文件 json.php

<?php
$arr = array(
'name' => '希亚',
'nick' => 'Gonn',
'contact' => array(
'email' => 'gonnsai@163.com',
'website' => 'http://www.nowamagic.net',
)
);
$json_string = json_encode($arr);
echo "getProfile($json_string)";
?>



光执行这个文件,其结果如下:

getProfile({"name":"\u5e0c\u4e9a","nick":"Gonn",
"contact":{"email":"gonnsai@163.com","website":"http:\/\/www.nowamagic.net"}})



json.php 是通过 json_encode 函数将数组扁平化,然后发送,相反有个 json_decode 函数。

那么在 JavaScript 如何调用呢?很简单,定义一个变量获取 PHP 传来的 Json,该 Json 具备对象的特性,我们可以用 array.name 这种方式来获取该 Json 的属性。

<script type="text/javascript">
function getProfile(str) {  
var arr = str;  
document.getElementById('name').innerHTML = arr.name;  
document.getElementById('nick').innerHTML = arr.nick;  
document.getElementById('email').innerHTML = arr.contact.email;
document.getElementById('website').innerHTML = arr.contact.website;
}  
</script>
<body>
<div id="name"></div>
<div id="nick"></div>
<div id="email"></div>
<div id="website"></div>
</body>
<script type="text/javascript" src="json.php"></script>



运行结果如下:

希亚
Gonn
gonnsai@163.com
http://www.nowamagic.net



JavaScript 向 PHP 传值

json_encode.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>json:From javascript To php</title>
<script src="json2.js" type="text/javascript"></script>
<script type="text/javascript">
function JSON_test(o)
{
var user = {
name:document.getElementById('txt_name').value,
email:document.getElementById('txt_email').value,
password:document.getElementById('txt_password').value
}
var json_string = JSON.stringify(user);
document.getElementById('txt_json').value=json_string;
alert("点击确定后将提交表单");
o.submit();
}
</script>
</head>

<body>

<form id="form1" name="form1" method="post" action="json_encode.php" onsubmit="JSON_test(this);return flase;">
<label for="txt_name">姓名</label>
<p><input type="text" name="txt_name" id="txt_name" /></p>
<label for="txt_email">邮箱</label>
<p><input type="text" name="txt_email" id="txt_email" /></p>
<p><label for="txt_password">密码</label></p>
<p><input type="text" name="txt_password" id="txt_password" /></p>
<p><input type="text" name="txt_json" id="txt_json" />
<label for="button"></label>
<input type="submit" name="button" id="button" value="JSON" />
</p>
</form>

</body>
</html>



这里javascript扁平化需要一个插件:http://www.json.org/json2.js,通过JSON.stringify(str)将对象扁平化然后传送给php。

注:另有一个http://www.json.org/json.js,对应的是toJSONString方法。

var last=obj.toJSONString(); //针对json.js
var last=JSON.stringify(obj); //针对json2.js



json_encode.php

<?php
header('Content-Type: text/html; charset=utf-8');
$json_string = $_POST["txt_json"];
//echo $json_string;
if(ini_get("magic_quotes_gpc")=="1")
{
$json_string=stripslashes($json_string);
}
$user = json_decode($json_string);

echo var_dump($user);

echo '<br /><br /><br /><br />';
echo $user->name.'<br />';
echo $user->email.'<br />';
echo $user->password.'<br />';
?>



这里就需要用到json_decode()这个函数,然后调用其中数据用 $obj->属性即可。

www.json.org/json.js     obj.toJSONString()  对 json.js
www.json.org/json2.js
   JSON.stringify(obj)  对 json2.js

failed to open stream: Permission denied in (php错误)

    今天,后台图片上传突然不行了。上传类也没什么错。就是在move_upload_file();文件移动这一步时,出了一个问题:failed to open stream: Permission denied in ; 意思就是文件夹权限不够。在一细看图片目的文件夹权限是755,于是百度查看了一下解决办法:把权限设置为757就好了。

根本原因是文件夹是用mkdir()创建时,没有对该目录进行权限设置。应加上这样一句@chmod($dir,0757); 就能保证生成的文件夹都是可写入权限了。

Forbidden关于无权限访问目录的问题

问题:You don’t have permission to access / on this server.

说法一:hi.baidu.com/%D0%C7%BC%CA%C0%CB%D7%D31988/blog/item/449a1cfc676f7389b801a026.html

<Files ~>
AllowOverride AuthConfig FileInfo Indexs Limit Options
Order allow ,deny
Deny from all—————–注意:就是这儿!!—>把这行去掉或注释掉就行!!!
</Files>

不过原httpd.conf文件中是没有这一段的。只有
<FilesMatch "^\.ht">   # 什么意思呢。匹配除.htt开头的文件?
Order allow,deny
Deny from all
</FilesMatch>

经查,这一段是属于服务器安全配置方面的。《php和mysql web开发》中写到:通过在httpd.conf中引入适当的指令,隐藏一些不希望被看到的文件。例如,要防止inc文件被看到,则:

<Files ~ “\.inc$”>
Order allow,deny
Deny from all
</Files>

上面文章还讲到怎么去解决错误的方法,值得借鉴。好了,继续说 403 forbidden

说法二:hi.baidu.com/hzw513/blog/item/ad85c0f56e5e0923bd310930.html

1、修改了httpd.conf中 documentRoot 的值;但没有修改下面不远处 <Directory "url"></Directory>中的url ;这个很好解决,直接改为一样,重启服务器就行了。

2、你没有访问这个目录的权限;不过这种情况windows下很少。一般多在linux下。 解决方法就是 chmod 701  /home/www ;如不行在参考其他情况。

不过以上都不是我遇到的情况。我的目录文件夹从ftp上下载下来。权限都是777的。所以没有这种情况。

说法三:hi.baidu.com/libk/blog/item/f9e32b34af4c90335ab5f5cd.html

经过以上验证后,确定不是以上问题。那么到底是什么原因呢。。。 忽然看到某个帖子的留言说“看apache日志”  忽然明白,到日志里面不就知道是什么问题了么! 说实话我挺笨的。
在 log/error.log中看到了
“Options FollowSymLinks or SymLinksIfOwnerMatch is off which implies that RewriteRule directive is forbidden: F:/www/”  
这样一段话,于是搜之;得到如上解答:

1. 如果没有启用mod_rewrite,可以用Options None 来保证安全性。

2. 如果启用了mod_rewrite, 那么Options就一定要启用FollowSymLinks或者SymLinksifOwnerMatch, 否则会出现Fobidden页面禁止访问的错误。
查看错误日志会有这样的出错信息:(Options FollowSymLinks or SymLinksIfOwnerMatch is off which implies that RewriteRule directive is forbidden: /location/to/your/rewrite/url)

查看 确认我的rewrite是打开的。可是options 却是 options indexes Multiviews  ;于是改为 fllowsymlinks ;重启,真的就行了!
不得不说原来如此。要多看看log啊。options具体选项详解参见这里

由apache重启错误引发的问题

某日,在安装好apache2.2.11 mysql5.0 php5.2.5 这些软件后,测试phpinfo正确显示信息。

但再重启apache过程中出现了问题。如:

于是使劲的搜apache重启错误。后实在是找不到原因了。又查看应用程序apache的具体错误信息,突然发现出现了一个系统级错误1067。于是再次搜apache 1067错误。终于找到原因了。
如:

说的是不能把某些程序当做正常的服务来启动。不过还是不太懂,到底是哪错了。于是把具体的apache信息“The Apache service named  reported the following error:
>>> httpd.exe: Could not reliably determine the server’s fully qualified domain name, using 192.168.1.1 for ServerName.”

再次baidu,找到某个问题也是如此。某牛解答说:

Module 模式运行 PHP,需要线程安全版本的 PHP,你下载的是 None Thread Safe 非线程安全版本的 PHP
如果必须要要使用 NTS 的 PHP,换成 CGI / FastCGI 安装模式即可
另外你的 ServerName 设置有问题,注释掉或者换成 localhost / IP 吧~

然后,就换了个php5.2.9的php包。于是再次试验。

按照配置php非安装版的步骤,一步一步的。

1、把php目录添加到系统环境变量path中,要记得用分号分隔。

2、创建新的php环境变量。名称:PHPRC   值: D:/wamp/php (即你的php目录)

3、修改php.ini文件。查找 extension_dir ,修改为 extension_dir = ‘D;/wamp/php/ext’;  添加Directory等。

4、让apache支持php。在httpd.conf 文件底部添加
LoadModule php5_module "D:/wamp/php/php2apache2_2.dll"
PHPIniDir "D:/wamp/php"

5、重启apache。

可是ff下一运行,居然phpInfo();函数直接出来了(在ie下运行,是直接弹出下载该文件的对话框) php没有被编译!发现没什么错的啊。一步一步的开始查找,还是没什么错。

第二天,到网上搜了,步骤大同小异,没什么多大区别。但是纠结啊。还是不知道。突然看到某个答案中有这样一句“在AddType application/x-gzip .gz .tgz的下一行加上AddType application/x-httpd-php .php

我想是不是因为掉了这一句呢。 于是加上。重启。真的就出来了!。。。

OMG 。忽略了这一句。 不太懂什么意思。我想应该是和iis中需要添加".php"后缀作为被编译的文件一个道理啊。

以下关于php执行方式及ISAPI/FastCGI的笔记。
====================================

只有在CGI/FastCGI模式下non-thread-safe才会工作。模块化安装方式不起作用,windows下web server大多是多线程的。

non-thread-safe意味着更好的性能,不过差异不大,php内部就已经很高效。无论是否值得这么做,带来的困惑却有很大争议。

从PHP5.2.10版本开始(现在有PHP5.2.10和5.3两个版本),有None-Thread Safe与Thread Safe两种版本的可供选择,这两种版本有何不同,作为使用者来说又应该如何选择呢?下面聚友将为您讲述。

先从字面 意思上理解,None-Thread Safe就是非线程安全,在执行时不进行线程(thread)安全检查;Thread Safe就是线程安全,执行时会进行线程(thread)安全检查,以防止有新要求就启动新线程的 CGI 执行方式耗尽系统资源。

再 来看PHP的两种执行方式:ISAPI和FastCGI。FastCGI执行方式是以单一线程来执行操作,所以不需要进行线程的安全检查,除去线程安全检 查的防护反而可以提高执行效率,所以,如果是以 FastCGI(无论搭配 IIS 6 或 IIS 7)执行 PHP ,都建议下载、执行 non-thread safe 的 PHP (PHP 的二進位檔有兩種包裝方式:msi 、zip ,請下載 zip 套件)。而线程安全检查正是为ISAPI方式的PHP准备的,因为有许多php模块都不是线程安全的,所以需要使用Thread Safe的PHP。

Non Thread Safe就是非线程安全,在执行时不进行线程(Thread)安全检查;
Thread Safe 是线程安全,执行时会进行线程(Thread)安全检查,以防止有新要求就启动新线程的 CGI 执行方式而耗尽系统资源;

Windows下的PHP 主要有两种执行方式:ISAPI 和 FastCGI。

      ISAPI 执行方式是以 DLL 动态库的形式使用,可以在被用户请求后执行,在处理完一个用户请求后不会马上消失,所以需要进行线程安全检查,这样来提高程序的执行效率,所以如果是以 ISAPI 来执行 PHP,建议选择 Thread Safe 版本;

      而 FastCGI 执行方式是以单一线程来执行操作,所以不需要进行线程的安全检查,除去线程安全检查的防护反而可以提高执行效率,所以,如果是以 FastCGI 来执行 PHP,建议选择 Non Thread Safe 版本。

      官方并不建议你将Non Thread Safe 应用于生产环境。

php线程安全与非线程安全的区别

原地址:koda.javaeye.com/blog/662034

   
Windows版的PHP从版本5.2.1开始有Thread Safe(线程安全)和None Thread Safe(NTS,非线程安全)之分,

这两者不同在于何处?到底应该用哪种?这里做一个简单的介绍。 从2000年10月20日发布的第一个Windows

版的PHP3.0.17开始的都是线程安全的版本,这是由于与Linux/Unix系统是采用多进程的工作方式不同的是

Windows系统是采用多线程的工作方式。如果在IIS下以CGI方式运行PHP会

非常慢,这是由于CGI模式是建立在多进程的基础之上的,而非多线程。一般我们会把PHP配置成以ISAPI的方

式来运行,ISAPI是多线程的方式,这样就快多了。但存在一个问题,很多常用的PHP扩展是以Linux/Unix的

多进程思想来开发的,这些扩展在ISAPI的方式运行时就会出错搞垮IIS。因此在IIS下CGI模式才是PHP运行的

最安全方式,但CGI模式对于每个HTTP请求都需要重新加载和卸载整个PHP环境,其消耗是巨大的。

  为了兼顾IIS下PHP的效率和安全,微软给出了FastCGI的解决方案。FastCGI可以让PHP的进程重复利用而

不是每一个新的请求就重开一个进程。同时FastCGI也可以允许几个进程同时执行。这样既解决了CGI进程模

式消耗太大的问题,又利用上了CGI进程模式不存在线程安全问题的优势。

  因此,如果是使用ISAPI的方式来运行PHP就必须用Thread Safe(线程安全)的版本;而用FastCGI模式运

行PHP的话就没有必要用线程安全检查了,用None Thread Safe(NTS,非线程安全)的版本能够更好的提高效

率。

php不支持重载

         首先很罪过的声明一下。搞php快一年了。居然还不知道原来php是不支持重载的(面向对象中广义的重载)。真的很罪过啊。。。以前只是知道php是面向对象等等的。但是自己没有具体的试验过。人云亦云啊。接下来就看看是怎么的不支持的。
代码测试:
<?php

class A{
function a(){
echo ‘this is a’;
}
function a($b){
echo ‘this is ‘.$b;
}
}

$a = new A();

?>
很不幸,在运行这段代码的时候,php就很干脆的甩出了:Fatal error: Cannot redeclare A::a() in  …   这样的错误。说的是不能重复声明方法a();   虽然有关php的书上都写明php支持重载。不过其实那是覆盖。是子类对父类方法或变量的重写。不能叫做重载。
看看网上的大虾们的讨论吧。
【1】
突然又想到了,这个问题,不要说我为什么老是用别人的标准来衡量它,道理很简单,因为我要用,最近在对zend framework做一次构架改造,遇到了需要覆盖成员和重载的难题,但是很可惜php是不支持的,只能写很多不同名方法,这看起来也不错,但是仔细想想 这样代码的冗余度是极高的也不利于接口应用。

说道这个问题,就要说说我很早以前发现的php bug,最后的结论php具有执行的不确定性,当它找不到默认构造的时候的时候(也就是写入一个参量不存在的php构造方法),这个时候php依然执行了它的默认无参数构造,而这在程序中会引起很大的问题。这个问题我当时从php的bug report得到的回答这是对的,我是错的,我不知道我对对象的理解是否有问题,我只知道它执行了一个我不期望的方法,但这被认为是对的,原因就是当在没 有重载概念时当然是对的,为什么不对?因为只要参数不违法就能执行,php似乎对参量控制都很松(这种松是我无法忍受的),php最大的问题就是 false是没有值,不是null就是空,这是一个很奇妙的问题,等于在php中机会不会出错的,这也就能解释为什么它不能重载,因为当他发现方法没有时他根本无法判断这到底是不存在还是类没有初始化,因为他们得到的结果都是一样的!而我不知道为什么这么一个愚蠢的问题为什么得不到修正,至少我知道的语言 里没有这样false不知道是啥的语言,php就是这样的。牢骚就不说了,写点难看的具有php特色的代码去。

原址:edwardpro.javaeye.com/blog/198288

php确实有点搞人。如构造函数中存在参数,如
class b{
__construct($a,$b){

}
}
但是实例化的时候,$b = new b(); 这样可以直接通过!且无任何错误。//错误
这里的构造函数如是这样写法 __construct($a,$b){} 则不会被编译通过。且会产生一个致命错误,Parse error: parse error, expecting `T_FUNCTION’ ;而如果是 function __construct($a,$b){}  然后实例化$b = new b(); 这里不会产生一个致命错误,而是出现两个Warning: Missing argument 1 for b::__construct() 警告;虽然程序还会继续往下运行,但是这样的程序不规范且参数的非必要性;所以还是避免这样的疏忽。再次谢谢网友jakey9826的指正。

【2】某牛答:
php不支持函数的重载,以后也不会支持
在oop中,函数的重载有两个条件
1、参数的个数不同——php支持参数缺省,无法用参数个数区别
2、参数的类型不同——php是弱类型语言,会根据上下文自动做类型转换
所以,php不可能支持函数的重载

解决方案:
同上面那个类A,做如下修改。
class A{
function a(){
$args = func_num_args();        //获取参数数量
switch($args){
case 0:
echo ‘没有参数’;
break;
case 1:
do something…
break;

default:
break;
}
}
}

php其实是提供重载的。不过并非是面向对象中的那个重载意思了。所以 忽忽。。。
php手册中:PHP所提供的"重载"(overloading)是指动态地"创建"类属性和方法。

php与cgi关系

很久都没搞明白这个cgi都底是干什么的。
属于孤陋寡闻的。cgi是 (common gateway interface)通用网关接口 。cgi通俗的说就是客户端与服务器

端的一个“桥梁”,把客户端收集的信息发送到服务器端;经过服务器端的处理后,把服务器端的信息返回到

客户端。

不过cgi又必须运行在网络服务器上,又怎么解释?

cgi作为一种标准,也作为一种编程语言(错了,不是一种编程语言)。即浏览器与服务器之间的“桥梁”!即

php、jsp、asp等编程语言也是一种cgi程序。且都是遵循cgi标准的。这也就是为什么cgi都必须在网络服务

器上运行的原因了。

CGI是外部应用程序(CGI程序)与Web服务器之间的接口标准,是在CGI程序和Web服务器之间传递信息的规程。

CGI规范允许Web服务器执行外部程序,并将它们的输出发送给Web浏览器。CGI将Web的一组简单的静态超媒体文

档变成一个完整的新的交互式媒体。

通常情况下,当web服务器接收到来自于浏览器的文件请求时,就把浏览器请求的文件发送给浏览器,并告

诉浏览器发送的文件的类型。但是,如果浏览器请求的不是一个文件,即URL指向的是一个程序(或脚本),则

Web服务器将首先执行这个程序,然后再将程序产生的输出结果像文件一样发送给浏览器。任何遵从CGI标准的、

由Web服务器执行的、能从Web服务器接收信息或发送信息给Web服务器的程序叫做CGI程序。CGI程序与所用的Web

服务器无关,在任何Web服务器上都可执行(任何特定的web服务器上都能执行)。

CGI是用来沟通HTML表单和服务器端程序的接口(interface)。说它是接口,也就是说CGI并不是一种语言,

而是可以被其他语言所应用的一个规范集。理论上讲,你可以用任何的程序语言来编写CGI程序,只要在编程

的时候符合CGI规范所定义的一些东西就可以了。由于C语言在平台无关性上表现不错(几乎在任何的系统平

台下都有其相应编译器),而且对大多数程序员而言都算得上很熟悉(不像Perl),因此,C是CGI编程的首

选语言之一。

事实上,现在的一些主流的服务器端脚本编程语言如ASP,PHP,JSP等,都基本上具备了CGI 编程的大部

分的功能,但他们在使用上的,确实是比无论用什么语言进行CGI编程都要容易的多。所以在进行服务器端编

程的时候,一般都会首先考虑使用这些脚本编程语言。只有当他们也解决不了,比如要进行一些更为底层的

编程的时候,才会用到CGI。