最近有服务器不时出现的CPU使用率超高,内存几乎被吃光,系统甚至自动kill掉一些进程,如sshd,vsftpd等。用top查看,PHP-CGI进程高挂不下,如下是解决方案:
一、进程跟踪
# top //找出CPU使用率高的进程PID
# strace -p PID //跟踪进程
# ll /proc/PID/fd //查看该进程在处理哪些文件
将有可疑的PHP代码修改之,如:file_get_contents没有设置超时时间。
二、内存分配
如果进程跟踪无法找到问题所在,再从系统方面找原因,会不会有可能内存不够用?据说一个较为干净的PHP-CGI打开大概20M-30M左右的内存,决定于PHP模块开启多少。
通过pmap指令查看PHP-CGI进程的内存使用情况
# pmap $(pgrep php-cgi |head -1)
按输出的结果,结合系统的内存大小,配置PHP-CGI的进程数(max_children)。
三、监控
最后,还可以通过监控与自动恢复的脚本保证服务的正常运转。下面是我用到的一些脚本:
只要一个php-cgi进程占用的内存超过 %1 就把它kill掉
#!/bin/sh
PIDS=`ps aux|grep php-cgi|grep -v grep|awk’{if($4>=1)print $2}’`
for PID in $PIDS
do
echo `date +%F….%T`>>/data/logs/phpkill.log
echo $PID >> /data/logs/phpkill.log
kill -9 $PID
done
检测php-fpm进程
#!/bin/bash
netstat -tnlp | grep “php-cgi” >> /dev/null #2&> /data/logs/php_fasle.log
if [ "$?" -eq "1" ];then #&& [ `netstat -tnlp | grep 9000 | awk '{ print $4}' | awk -F ":" '{print $2}'` -eq "1" ];then
/usr/local/webserver/php/sbin/php-fpm start
echo `date +%F….%T` “System memory OOM.Kill php-cgi. php-fpm service start. ” >> /data/logs/php_monitor.log
fi
通过http检测php执行
#!/bin/bash
status=`curl -s –head “http://127.0.0.1:8080/chk.php” | awk ‘/HTTP/ {print $2}’`
if [ $status != "200" -a $status != "304" ]; then
/usr/local/webserver/php/sbin/php-fpm restart
echo `date +%F….%T` “php-fpm service restart” >> /data/logs/php_monitor.log
fi
数据库设计规范是个技术含量相对低的话题,只需要对标准和规范的坚持即可做到。当系统越来越庞大,严格控制数据库的设计人员,并且有一份规范书供执行参考。在程序框架中,也有一份强制性的约定,当不遵守规范时报错误。
以下20个条款是我从一个超过1000个数据库表的大型ERP系统中提炼出来的设计约定,供参考。
1 所有的表的第一个字段是记录编号Recnum,用于数据维护
[Recnum] [decimal] (8, 0) NOT NULL IDENTITY(1, 1)
在进行数据维护的时候,我们可以直接这样写:
UPDATE Company SET Code='FLEX' WHERE Recnum=23
2 每个表增加4个必备字段,用于记录该笔数据的创建时间,创建人,最后修改人,最后修改时间
[CreatedDate] [datetime] NULL, [CreatedBy] [nvarchar] (10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [RevisedDate] [datetime] NULL, [RevisedBy] [nvarchar] (10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
框架程序中会强制读取这几个字段,默认写入值。
3 主从表的主外键设计
主表用参考编号RefNo作为主键,从表用RefNo,EntryNo作为主键。RefNo是字符串类型,可用于单据编码功能中自动填写单据流水号,从表的EntryNo是行号,LineNo是SQL Server 的关键字,所以用EntryNo作为行号。
如果是三层表,则第三层表的主键依次是RefNo,EntryNo,DetailEntryNo,第三个主键用于自动增长行号。
4 设计单据状态字段
| 字段 | 含义 |
| Posted | 过帐,已确认 |
| Closed | 已完成 |
| Cancelled | 已取消 |
| Approved | 已批核 |
| Issued | 已发料 |
| Finished | 已完成 |
| Suspended | 已取消 |
5 字段含义相近,把相同的单词调成前缀。
比如工作单中的成本核算,人工成本,机器成本,能源成本,用英文表示为LaborCost,MachineCost,EnergyCost
但是为了方便规组,我们把Cost调到字段的前面,于是上面三个字段命名为CostLabor,CostMachine,CostEnergy。
可读性后者要比前者好一点,Visual Studio或SQL Prompt智能感知也可帮助提高字段输入的准确率。
6 单据引用键命名 SourceRefNo SourceEntryNo
销售送货Shipment会引用到是送哪张销售单据的,可以添加如下引用键SourceRefNo,SourceEntryNo,表示送货单引用的销售单的参考编号和行号。Source开头的字段一般用于单据引用关联。
7 数据字典键设计
比如员工主档界面的员工性别Gender,我的方法是在源代码中用枚举定义。性别枚举定义如下:
public enum Gender
{
[StringValue("M")]
[DisplayText("Male")]
Male,
[StringValue("F")]
[DisplayText("Female")]
Female
}
在代码中调用枚举的通用方法,读取枚举的StringValue写入到数据库中,读取枚举的DisplayText显示在界面中。
经过这一层设计,数据库中有关字典方面的设计就规范起来了,避免了数据字典的项的增减给系统带来的问题。
8 数值类型字段长度设计
Price/Qty 数量/单价 6个小数位 nnnnnnnnnn.nnnnnn 格式 (10.6)
Amount 金额 2个小数位 nnnnnnnnnnnn.nn 格式(12.2)
Total Amt 总金额 2个小数位 nnnnnnnnnnnnnn.nn 格式(14.2)
参考编号默认16个字符长度,不够用的情况下增加到30个字符,再不够用增加到60个字符。这样可以保证每张单据的第一个参考编号输入控件看起来都是一样长度。
除非特别需求,一般而言,界面中控件的长度取自映射的数据库中字段的定义长度。
9 每个单据表头和明细各增加10个自定义字段,基础资料表增加20个自定义字段
参考供应商主档的自定义字段,自定义字段的名称统一用UserDefinedField。
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_1] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_2] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_3] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_4] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_5] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_6] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_7] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_8] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_9] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_10] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_11] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_12] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_13] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_14] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_15] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_16] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_17] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_18] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_19] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_20] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
10 多货币(本位币)转换字段的设计
金额或单价默认是以日记帐中的货币为记录,当默认货币与本位币不同时需要同时记录下本位币的值。
销售单销售金额 SalesAmount或SalesAmt,本位币字段定义为SalesAmountLocal或SalesAmtLocal
通常是在原来的字段后面加Local表示本位币的值。
11 各种日期字段的设计
| 字段名称 | 含义 |
| TranDate | 日期帐日期 Tran是Transaction的简写 |
| PostedDate | 过帐日期 |
| ClosedDate | 完成日期 |
| InvoiceDate | 开发票日期 |
| DueDate | 截止日期 |
| ScheduleDate | 计划日期,这个字段用在不同的单据含义不同。比如销售单是指送货日期,采购单是指收货日期。 |
| OrderDate | 订单日期 |
| PayDate | 付款日期 |
| CreatedDate | 创建日期 |
| RevisedDate | 修改日期 |
| SettleDate | 付款日期 |
| IssueDate | 发出日期 |
| ReceiptDate | 收货日期 |
| ExpireDate | 过期时间 |
12 财务有关的单据包含三个标准字段
FiscalYear 财年,PeriodNo 会计期间,Period 前面二个的组合。以国外的财年为例子,FiscalYear是2015,PeriodNo是4,Period是2015/04。
欧美会计期间是从每年的4月份开始,需要注意的是会计期间与时间没有必然的联系,看到会计期间是2015/04,不一定是表示2015的4月份,它只是说这是2015财年的第四期,具体在哪个时间段需要看会计期间定义。
13 单据自动生成 DirectEntry
有些单据是由其它单据生成过来的,逻辑上应该不支持编辑。比如销售送货Shipment单会产生出仓单,出仓单应该不支持编辑,只能做过帐扣减库存操作。这时需要DirectEntry标准字段来表示。当手工创建一张出仓单时,将DirectEntry设为true,表示可编辑单据中的字段值,当由其它单据传递产生过来产生的出仓单,将DirectEntry设为false,表示不能编辑此单据。这种情况还发生在业务单据产生记帐凭证(Voucher)的功能中,如果可以修改由原始单据传递过来的数量金额等字段,则会导致与源单不匹配,给系统对帐产生困扰。
14 百分比值字段的设计
Percentage百分比值,用于折扣率,损耗率等相关比率设定的地方。推荐用数值类型表示,用脚本表示是
[ScrapRate] [decimal] (5, 2) NULL
预留两位小数,整数部分支持1-999三位数。常常是整数部分2位就可以,用3位也是为了支持一些特殊行业(物料损耗率超过100)的要求。
15 日志表记录编号LogNo字段设计
LogNo字段的设计有些巧妙,以出仓单为例子,一张出仓单有5行物料明细,每一行物料出仓都会扣减库存,再写物料进出日记帐,因为这五行物料出仓来自同一个出仓单,于是将这五行物料的日记帐中的LogNo都设为同一个值。于在查询数据时,以这个字段分组即可看到哪些物料是在同一个时间点上出仓的,对快速查询有很重要的作用。
16 基础资料表增加名称,名称长写,代用名称三个字段
比如供应商Vendor表,给它加以下三个字段:
Description 供应商名称,比如微软公司。
ExtDescription 供应商名称长写,比如电气行业的南网的全名是南方国家电网有限公司。
AltDescription 供应商名称替代名称,用在报表或是其它单据引用中。比如采购单中的供应商是用微软,还是用代用名称Microsoft,由参数(是否用代用名称)控制。
17 文件类表增加MD5 Hash字段
比如产品数据管理系统要读取图纸,单据功能中增加的附件文件,这类涉及文件读写引用的地方,考虑存放文件的MD5哈希值。文件的MD5相当于文件的唯一识别身份,在网上下载文件时,网站常常会放出文件的MD5值,以方便对比核对。当下载到本机的文件的MD5值与网站上给出的值不一致时,有可能这个文件被第三方程序修改过,不可信任。
18 数据表的主键用字符串而不是数字
比如销售单中的货币字段,是存放货币表的货币字符串值RMB/HKD/USD,还是存放货币表的数字键,1/2/3。
存放前者对于报表制作相对容易,但是修改起来相对麻烦。存放后者对修改数据容易,但对报表类或查询类操作都需要增加一个左右连接来看数字代表的货币。金蝶使用的是后者,它的BOS系统也不允许数据表之间有直接的关联,而是间接通过Id值来关联表。
在我看到的系统中,只有一个会计期间功能(财年Fiscal Year)用到数字值作主键,其余的单据全部是字符串做主键。
19 使用约定俗成的简写
模块Module 简写
| 简写 | 全名 |
| SL | Sales 销售 |
| PU | Purchasing 采购 |
| IC | Inventory 仓库 |
| AR | Account Receivable 应收 |
| AP | Account Payable 应付 |
| GL | General Ledger 总帐 |
| PR | Production 生产 |
名称Name 简写
| 简写 | 全名 |
| Uom | Unit of Measure 单位 |
| Ccy | Currency 货币 |
| Amt | Amount 金额 |
| Qty | Quantity 数量 |
| Qty Per | Quantity Per 用量 |
| Std Output | Standard Output 标准产量 |
| ETA | Estimated Time of Arrival 预定到达时间 |
| ETD | Estimated Time of Departure 预定出发时间 |
| COD | Cash On Delivery 货到付款 |
| SO | Sales Order 销售单 |
| PO | Purchase Order 采购单 |
20 库存单据数量状态
Qty On Hand 在手量
Qty Available 可用量
Qty On Inspect 在验数量
Qty On Commited 提交数量
Qty Reserved 预留数量
以上每个字段都有标准和行业约定的含义,不可随意修改取数方法。
今天算是长见识了,项目发布到服务器上面了,但是客户在使用的时候发现,只要进入新增页面和修改页面。再进行操作就会自动跳转到登陆页面(我设置了session保存用户登陆信息),而别的页面就不会出现这个问题。从下午开始找个问题,开始以为不知道只有这两个页面有问题,以为全部都是这样的问题,是IIS的设置问题。我将session的超时时间设置了3个小时,发现还是会跳转到登陆页面。也在web.config文件里面设置了超时时间。但是效果还是一样的。自己测试了一下午,发现只有新增页面和修改页面会出现这样的问题(本机测试没问题/测试服务器上测试也没问题)。经过几次实验,发现确实只有这两个页面会有问题,那就可以断定:不是IIS设置问题,也不是web.config的问题。本地调试也不出现这样的情况,没办法,只能等客户下班之后,没人用了才到正式服务器上去慢慢的调试,最后想个笨办法,将其中一个页面的.cs文件里面的代码一句一句的删掉,可没想到我都将cs文件里面的代码全部删除了,还是会出现这样的情况,我当时就纳闷了。不是事件的问题,难道是HTML页面出了问题???
既然耐着性子删了cs文件的代码。我就继续删!将aspx页面里面的HTML代码和JS代码也一个一个的删掉,一个一个控件删掉测试,从下午上班一直测试到晚上11点,眼睛都看花了,终于,在我将aspx页面的其中几个控件删除之后发现问题了!页面不跳转了!这下来劲了,肯定是这几个控件的原因,于是乎,我就一个一个控件还原回去,不跳转!继续还原!!当我还原到<img src="" >这个控件的时候测试,发现问题了!只要我一加上<img src="">这个标签!页面就跳转到登陆页面了。问题肯定出在这了!但是我又想不通了,为什么就这个HTML标签一加上就会出问题,这应该不关session什么事啊,怎么会加上这个标签页面就直接跳转了呢?
在网上找了下资料,没找到相关的资料,后来试着将img 标签的src=""加上图片,src="imges/001.jpg" 再测试,发现页面不跳转了!!原来问题出现在这里!
src=""为空的情况下,可能导致session丢失!跟经理说了下这个情况,他也很惊奇还没见过一个HTML标签会导致session丢失的情况,因为在本地和测试服务器上测试的时候都没这样的情况,后来猜测了下,可能是IIS的问题,可能是IIS解析的时候解析到src=""这个地方解析不了,导致程序出问题。但这只是个人猜测,正式服务器上我也没权力当时去打补丁,一个大公司的正式服务器,我要打补丁去了,那他们别的网站和系统不全当机了?所以就只要想了个办法,将src=""里面加上图片,幸好这个img标签是隐藏起来的,加了也不影响界面。呵呵。。。
最让人郁闷的是我测试的时候是用Symantec pcAnywhere这个软件远程连接到的正式服务器上。反应慢得可以,简直比电脑没装显卡驱动还慢...唉,不过累也累了,以后碰到这样的情况就有经验了。
我不知道网上有没有人碰到过跟我一样的情况;如果碰到了,希望能给你带来点灵感。哇哈哈。。。
下载最新的免费CodeHighlighter组件 http://www.CodeHighlighter.com
1。确保web.config中的languages节点的.xml文件路径正确。
2。可以在insertCode.aspx更改编辑的默认设置,如checkbox的check等。(或在项目中搜索相关代码)
DotNetTextBox 已集成CodeHighlighter,我的修改如下:
将 Windows\Temp 目录的权限 Network Service 帐户赋予了完全控制的权限
出错快照:
“/”应用程序中的服务器错误。
编译错误
说明: 在编译向该请求提供服务所需资源的过程中出现错误。请检查下列特定错误详细信息并适当地修改源代码。
编译器错误消息: CS0016: Could not write to output file 'c:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\138641eb\e8d016c8\App_Web_default.aspx.bb4e7940.re_hlwux.dll' -- '拒绝访问。 '
2000/XP/2003 下 IIS+PHP+MySQL+Zend Optimizer+GD库+phpMyAdmin安装配置
(假设 C:\ 为你现在所使用操作系统的系统盘,如果你目前操作系统不是安装在 C:\ ,请自行修改。)
一、安装 IIS(Windows2003只要安装“应用程序服务器(IIS,ASP.NET)”即可跳过此步):
(1)插入系统盘;
(2)进入控制面板-》添加或删除程序-》添加/删除Windows组件-》在“Internet信息服务(IIS)打勾-》下一步安装。
(3)安装完成后在浏览器地址栏输入 htt://127.0.0.1 检查是否安装正常。
如果没有系统盘,那么下载 IIS 5.1 的安装包(for XP),重复上述步骤,安装时指定路径即可。
IIS下载地址:http://soft.mumayi.net/downinfo/2597.html
二、安装 PHP:
(1)官方下载:http://www.php.net/downloads.php。
(2)下载后得到 php 的 zip 压缩包,解压至 C:\php(这个路径可以随意,下面要是用到这个路径,请相应修改);
(3)将 C:\php\libmysql.dll 和 C:\php\ext\php_mysql.dll 复制到 C:\Windows\system32 下;
将 C:\php\php.ini-recommended 复制到 C:\Windows (Windows 2000 下为 C:\WINNT)并将改名为php.ini,
然后用记事本打开,利用记事本的查找功能搜索:
搜索“; Windows Extensions”并仅打开需要的模块以节省内存(去掉每个模块前的;号即可):
extension=php_gd2.dll
GD库支持,支持水印。
extension=php_mbstring.dll
支持phpMyAdmin
extension=php_mysql.dll
支持MySQL。
(4)配置 IIS 使其支持 PHP
在“控制面板”的“管理工具”中选择“Internet 服务管理器”,
然后在左侧选择你需要支持 PHP 的 Web 站点上单击右键选择“属性”,
在打开的“Web 站点属性”窗口的“ISAPI 筛选器”标签里找到并点击“添加”按钮,在弹出的“筛选器属性”窗口中的“筛选器名称”栏中输入:PHP,再将可执行文件指向 php5isapi.dll 所在路径,如:C:\php\php5isapi.dll。
打开“Web 站点属性”窗口的“主目录”标签,找到并点击“配置”按钮,在弹出的“应用程序配置”窗口中找到并点击“添加”按钮,在弹出的窗口中新增一个扩展名映射,扩展名为 .php ,单击“浏览”将可执行文件指向 php5isapi.dll 所在路径,如:C:\php\php5isapi.dll,然后一路确定即可。
再打开“Web 站点属性”窗口的“文档”标签,找到并点击“添加”按钮,向默认的 Web 站点启动文档列表中添加 index.php 项。您可以将 index.php 升到最高优先级,这样,访问站点时就会首先自动寻找并打开 index.php 文档。
确定 Web 目录的应用程序设置和执行许可中选择为纯脚本,然后关闭 Internet 信息服务管理器。
2003系统配置:在“Internet 服务管理器”左边的“WEB服务扩展”中设置:
ISAPI 扩展允许
开始-》运行-》输入“iisreset”,重启IIS。
在 IIS 根目录下新建一个 phpinfo.php,内容如下:
<?php
phpinfo();
?>
打开浏览器,输入:http://127.0.0.1/phpinfo.php,将显示当前服务器所支持 PHP 的全部信息。
三、安装 MySQL:
(1)官方下载:http://dev.mysql.com/downloads/mysql/5.2.html
custom
安装
Skip Sign-Up
Finish
Next
Standard Comfiguration
设置数据库密码
(重要)重新启动电脑!
四、安装 Zend Optimizer :(有需要时安装)
(1)官方下载:http://www.zend.com/products/zend_optimizer
(2)安装时只需选择Web服务器为iis,指定php.ini路径即可。
五、安装 phpMyAdmin:(用于管理MYSQL数据库,可选择)
下载 http://www.phpmyadmin.net,将其解压到站点根目录,
找到 ./libraties/config.default.php,做以下修改:
方案一:
搜索 $cfg['Servers'][$i]['auth_type'] 设置为config
搜索 $cfg['Servers'][$i]['user'] 用户名一般为root
搜索 $cfg['Servers'][$i]['password'] 设置MySQL的密码
打开浏览器,输入:http://127.0.0.1/phpMyAdmin/ ,若 IIS 和 MySQL 均已启动,即可浏览数据库内容。
(此设置允许任何人通过以上路径登录管理数据库,安全性极低)
方案二:
搜索 $cfg['Servers'][$i]['auth_type'] 设置为cookie
搜索 $cfg['Servers'][$i]['user'] 用户名一般为root
搜索 $cfg['PmaAbsoluteUri'] 访问路径,设置为http://127.0.0.1/phpmyadmin/
搜索 $cfg['blowfish_secret'] 这是cookie作用域,设置为127.0.0.1
(此设置只允许本机上登录,并且需要输入用户名密码才能登录,安全性极高)
-----------------------------------------------------------------------------------
至此所有安装完毕。以上配置在所有老版本软件中不一定有效,强烈推荐下载最新版本的软件。
简单安装过程:请各位注意安装顺序
----------------------------------------------------
(一)Apache:
装在默认目录。安装-自定义-全部选中。
----------------------------------------------------
(二)PHP:
第一步:压缩C:\php5目录下。
第二步:(将PHP目录添加到PATH环境变量中)开始 -> 控制面板 -> 系统 -> 高级 -> 环境变量 -> 系统变量 -> Path -> 双击 -> 加入“;C:\php5”
第三步:将C:\php5\php.ini-recommended 重命名为 php.ini 。
用记事本打开 php.ini ,查找register_globals = Off,把off改成On (有二处)
查找short_open_tag = Off,把off改成On 有一处
查找extension_dir = "./" 改为 extension_dir = "C:\php5\ext"
查找;extension=php_mbstring.dll,把下面几句前面的分号去掉
extension=php_mbstring.dll
extension=php_dba.dll
extension=php_dbase.dll
extension=php_filepro.dll
extension=php_gd2.dll
extension=php_imap.dll
extension=php_ldap.dll
extension=php_mysql.dll
修改了一些文件上传以及内存使用最大限制:
memory_limit = 20M 内存容量
post_max_size = 20M 闪存容量
upload_max_filesize = 20M 附件容量
保存退出。
第四步:(使php.ini文件在Windows下被PHP所用)
开始 -> 控制面板 -> 系统 -> 高级 -> 环境变量 -> 系统变量 -> 新建 -> 输入“PHPRC” -> 在“变量值”中输入 php.ini文件所在的目录(例如:C:\php5)
点击“确定”
Microsoft Windows 下的 Apache 2.0.x
先停止Apache
用记事本打开C:\Apache2\conf(可能在C:\Program Files\Apache Group\Apache2\conf)下的httpd.conf
这个文件我改了几个地方:
把PHP直接作为apache的一个模块运行,我在里面加了两句:
查找到 #LoadModule ssl_module modules/mod_ssl.so 在它的下面一行加上
LoadModule php5_module "C:/PHP5/php5apache2.dll"
AddType application/x-httpd-php .php 注意点前面有个空格滴,大家最好用复制粘贴
(新版apache2.2的php5apache2_2.dll在外面,放上去同理用)
我在D盘下建立了一个www的目录用于存放我的站点文件,在http.conf里改了这样一句话:
把
DocumentRoot "C:/Program Files/Apache Group/Apache2/htdocs"
改成了
DocumentRoot "D:/www"
所有
Apache2.0.x于1.3.x相比2.0.x默认不能直接列目录,如需,就改:
把DocumentRoot "E:/www"这句下的如下语句
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
改为:
<Directory />
Options Indexes FollowSymLinks
AllowOverride None
</Directory>
修改目录的默认首页:
如:DirectoryIndex index.htm index.html index.php index.html index.html.var
别的就没再动什么地方,保存后退出。
注意一点的是,要使以上所有这些配置生效需要重新启动电脑
最后我们来测试PHP是否正常载入。打开记事本,输入
<?php
phpinfo();
?>
保存,在弹出的窗口中,文件类型选所有文件,文件名为phpinfo.php,保存位置为网站目录下。如(E:\www\phpinfo.php)
打开IE浏览器输入:http://localhost/phpinfo.php 如果能正常显示就OK了。
-------------------------------------------------------
(三)Zend:
先停止Apache
安装Zend Optimizer也很简单,安装中它会两处提示其一:选择那种服务器?请选择Apache。其二:PHP.ini的路径?请选择C:\PHP5。其它的按默认配置安装就行了。OK安装完后我的Zend目录就是C:\Zend。
-------------------------------------------------------
(四)Mysql:
CatalogEdit.aspx
<asp:ListBox ID="ListBox1" runat="server" DataSourceID="SqlDataSource1" DataTextField="catalog" DataValueField="ID" Rows="10"></asp:ListBox> <asp:LinkButton ID="LinkButton_up" runat="server" OnClick="LinkButton_up_Click">上移</asp:LinkButton> <asp:LinkButton ID="LinkButton_down" runat="server" OnClick="LinkButton_down_Click">下移</asp:LinkButton> <asp:LinkButton ID="LinkButton_del" runat="server" OnClick="LinkButton_del_Click">删除</asp:LinkButton> <asp:Label ID="Label_alert" runat="server" ForeColor="Red" Text="Label"></asp:Label><br /> <asp:TextBox ID="TextBox_newCatalog" runat="server"></asp:TextBox> <asp:LinkButton ID="LinkButton_add" runat="server" OnClick="LinkButton_add_Click">新增</asp:LinkButton> <asp:LinkButton ID="LinkButton_edit" runat="server" OnClick="LinkButton_edit_Click">修改</asp:LinkButton> <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionStringLink %>" DeleteCommand="DELETE FROM [xLinkCategory] WHERE [ID] = ?" InsertCommand="INSERT INTO [xLinkCategory] ([username],[catalog],[order]) VALUES (?,?,0)" ProviderName="<%$ ConnectionStrings:ConnectionStringLink.ProviderName %>" SelectCommand="SELECT [ID], [catalog] FROM [xLinkCategory] WHERE ([username] = ?) ORDER BY [order],[ID] desc" UpdateCommand="UPDATE [xLinkCategory] SET [catalog] = ? WHERE [ID] = ?"> <DeleteParameters> <asp:Parameter Name="ID" Type="Int32" /> </DeleteParameters> <UpdateParameters> <asp:Parameter Name="catalog" Type="String" /> <asp:Parameter Name="ID" Type="Int32" /> </UpdateParameters> <SelectParameters> <asp:SessionParameter Name="username" SessionField="username" Type="String" /> </SelectParameters> <InsertParameters> <asp:SessionParameter Name="username" SessionField="username" Type="String" /> <asp:Parameter Name="catalog" Type="String" /> </InsertParameters> </asp:SqlDataSource>
CatalogEdit.aspx.cs
/**//// <summary>
/// 上移
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void LinkButton_up_Click(object sender, EventArgs e)
{
if (ListBox1.SelectedItem != null && ListBox1.SelectedIndex > 0)
{
string tempValue = ListBox1.SelectedValue;
string tempText = ListBox1.SelectedItem.Text;
int index = ListBox1.SelectedIndex;
ListBox1.SelectedItem.Value = ListBox1.Items[index - 1].Value;
ListBox1.SelectedItem.Text = ListBox1.Items[index - 1].Text;
ListBox1.Items[index - 1].Value = tempValue;
ListBox1.Items[index - 1].Text = tempText;
ListBox1.SelectedIndex--;
operateDB_move();
}
}
/**//// <summary>
/// 下移
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void LinkButton_down_Click(object sender, EventArgs e)
{
if (ListBox1.SelectedItem != null && ListBox1.SelectedIndex < ListBox1.Items.Count - 1)
{
string tempValue = ListBox1.SelectedValue;
string tempText = ListBox1.SelectedItem.Text;
int index = ListBox1.SelectedIndex;
ListBox1.SelectedItem.Value = ListBox1.Items[index + 1].Value;
ListBox1.SelectedItem.Text = ListBox1.Items[index + 1].Text;
ListBox1.Items[index + 1].Value = tempValue;
ListBox1.Items[index + 1].Text = tempText;
ListBox1.SelectedIndex++;
operateDB_move();
}
}
/**//// <summary>
/// 添加
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void LinkButton_add_Click(object sender, EventArgs e)
{
if (TextBox_newCatalog.Text != "")
{
//检查同名
bool goon = true;
foreach (ListItem li in ListBox1.Items)
{
if (li.Text == TextBox_newCatalog.Text)
{
goon = false;
}
}
if (goon)
{
//操作
SqlDataSource1.InsertParameters["catalog"].DefaultValue = TextBox_newCatalog.Text;
SqlDataSource1.Insert();
//设置selected
if (ListBox1.Items.Count > 0)
{
ListBox1.SelectedIndex = 0;
}
}
else
{
Label_alert.Text = "已存在";
}
}
}
/**//// <summary>
/// 修改
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void LinkButton_edit_Click(object sender, EventArgs e)
{
if (TextBox_newCatalog.Text != "" && ListBox1.SelectedItem != null)
{
int index = ListBox1.SelectedIndex;
//检查同名
bool goon = true;
foreach (ListItem li in ListBox1.Items)
{
if (li.Text == TextBox_newCatalog.Text)
{
goon = false;
}
}
if (goon)
{
//操作
SqlDataSource1.UpdateParameters["catalog"].DefaultValue = TextBox_newCatalog.Text;
SqlDataSource1.UpdateParameters["ID"].DefaultValue = ListBox1.SelectedItem.Value;
SqlDataSource1.Update();
//设置selected
ListBox1.SelectedIndex = index;
}
else
{
Label_alert.Text = "已存在";
}
}
}
/**//// <summary>
/// 删除
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void LinkButton_del_Click(object sender, EventArgs e)
{
if (ListBox1.SelectedItem != null)
{
int index = ListBox1.SelectedIndex;
int count = ListBox1.Items.Count;
//检查该 Catalog 下是否有 Link
bool goon = true;
goon = !checkSubLink(ListBox1.SelectedValue); //下有 Link 则返回真,注意前面有个"!",有则不继续
if (goon)
{
//操作
SqlDataSource1.DeleteParameters["ID"].DefaultValue = ListBox1.SelectedItem.Value;
SqlDataSource1.Delete();
//设置selected
if (index < count - 1) //删的不是最末项
{
ListBox1.SelectedIndex = index;
}
if (index == count - 1 && index != 0) //删的是最末项,并且不是最首项
{
ListBox1.SelectedIndex = index - 1;
}
if (index == count - 1 && index == 0) //删的是最末项,并且是最首项
{
//不设索引
}
}
else
{
Label_alert.Text = "该节点下面存在Link(s),请删除后再删除该节点!";
}
}
}
许多情况下,asp.net 在 Page_Load 事件中需要动态生成控件,这对于一些新手,包括我在内,会因为回传控件消失,或重复叠加控件等原因搞得头大,经过我翻阅资料和自己的实践,以博客评论页为例,把整个框架写在下面,仅供参考。
<asp:Panel>
<asp:Panel 记录索引 3 >
<asp:Label 昵称 /> <asp:Label 时间 /> <asp:LinkButton 支持按钮_3 /> <asp:LinkButton 删除按钮_3 /> 1楼
</asp:Panel>
<asp:Panel 记录索引 5 >
<asp:Label 昵称 /> <asp:Label 时间 /> <asp:LinkButton 支持按钮_5 /> <asp:LinkButton 删除按钮_5 /> 2楼
</asp:Panel>
</asp:Panel>
记录索引是指数据库中的自动编号。
支持按钮触发事件 LinkButton_support_Click(object sender, EventArgs e)
删除按钮触发事件 LinkButton_del_Click(object sender, EventArgs e)
所有子 Panel 和内部的所有控件都是在 Page_Load 事件中动态创建的,并且不能被嵌套在 if(!IsPostBack)
“点支持累计点击数”和“点删除删除一条记录”都是需要操作数据库的,我以前的做法是操作完数据库后 .Clear() 掉所有控件,再重新生成一次,这样既浪费服务器资源,又容易出现界面上的混乱,譬如显示了两遍该文章的评论。
其实上面代码中 Panel 套 Panel 的好处就是可以根据索引直接删除相应控件,然后直接在页面呈现,而省去上述烦恼。至于累计支持数就更简单了,下面的代码可以轻松解决问题:
string n = ((Label)Panel_commentLists.FindControl("Label_against_" + id)).Text;
n = (Convert.ToInt32(n) + 1).ToString();
((Label)Panel_commentLists.FindControl("Label_against_" + id)).Text = n;
如果有修改和添加评论操作,同样道理,不要重复地全部 .Controls.Add 一次。为了添加时追加一个子 Panel 方便,建议在 Page_Load 的地方传参使用方法来做。
补充:在现在的开发中,我更喜欢用动态生成TableRow,TableCell来操作。