IIS+php服务器里删除Temp里的sess_文件非常重要
我用的是windows2003服务器,里面可以同时运行IISASP和PHP+mysql,前段日子,一直发现服务器越来越慢,网站动不动就不能访问,有时,连得自己的服务器远程都进不去了。只能让机房人员给我重启动。开始,我一直怀疑是服务器同时在线人数太多的原因,于是对服务器进行了一次大规模的各种优化各种,也开启了GZIP等功能,结果,网站访问速度是非常明显地加快了。但是,还是会有服务器压力超重的感觉。于是,打开 c:\windows\php.ini文件,一步步地仔细检查各种设置。发现 session.save_path = "E:/host/php/Temp" 和upload_tmp_dir =E:/host/php/Temp 这二条同时设置在同一个临时文件夹里。想去检查这个文件夹的属性,老半天都没有打开,系统还几次差点死机,我似乎明白了什么了,一定是文件太多太大了。我点击这个属性后,下线睡觉了,到第二天打开服务器才发现,属性文件终于打开了。(晕吧?系统自己打了一夜才开~~)一看吓了一跳,几面文件数量上百万个,占用空间8个G。用CMD里的del命令删除了2天都没有完全删除掉,还时不时地导致系统死机。没办法,我就在E盘下新建立了一个文件夹:E:\Temp。同时在php.ini里修改了上述的二个文件指向。建立新文件时,必须要指定此文件夹的属性里赋予user读写文件的权力。因为,系统自己建立的sess_xxxxxx文件,按道理,php在一定的时间里,是会自动删除的。我检查了原来用的那个Temp文件夹属性,发现没有给予 user删除的权力。所以,系统自动生成的sess_文件会越积越多,最后导致系统为了寻找客户资料,大量地消耗了内存和CPU。造成的后果也就不言而喻了!
自从我这么处理开始,我连续观察了4天。发现这个新建立的Temp文件夹里,系统只保存当天的sess_xxxxxxxx文件,也就是说,它自动地删除了旧文件了。现在我的服务器一切正常了!
说了这么多,就是为了给碰到相同问题的同行站长提个醒,让大家少走弯路。使用 Apache 的用户,可以利用自己的FTP软件在网站根目录里去定时地删除 sess_ xxxxxx文件。
del /s /q *.*
删除所有文件 ,但不删除文件夹、
最近志文工作室所在的服务器经常宕机,而且重启后也总是cpu占用率非常高,而一旦关闭iis则恢复正常。于是进行了仔细地排查。当在清理垃圾文件时,发现c:\windows\temp文件夹中存在超级多以sess_开头的文件,此类文件之多使得无法正常的打开temp文件夹和删除清理
通过搜查找到了问题所在并进行了解决,在此详细记录以供参考。
一、 temp文件夹大量文件的删除
以sess开头的存在于temp系统临时文件夹的文件,是php的session保存文件,由于php建立了session却在过期后没有成功删除,于是导致大量文件的积累。
清理方法很简单,新建批处理文件del_temp.bat,其中写入如下命令:
复制代码 代码如下:
del %TEMP% /s /q *.*
保存后双击运行,即开始进行删除处理(也可直接在cmd命令行中输入执行)
你也可以将其加入开机启动项,以使得每次重启系统后即执行一次删除处理。
提示:
1. 如果这里执行一直显示无法进行(志文工作室最先遇到的情况即如此),则可能是temp文件夹及其中部分文件正处于使用状态,那么你可以在同目录下新建一个文件夹tmp,然后修改系统环境变量temp和tmp的位置为此,接着重启系统使得新的临时目录生效,此时即可对temp文件任意删改了。
2. 志文工作室的服务器temp文件夹内存在数十万这样的文件,清理了若干小时才完成。故在进行处理前应停止iis:
net stop iisadmin 关闭iis服务
net start iisadmin 开启iis服务
3. 当然,你不希望在处理的过程中让网站关闭如此之久,所以你应依次进行的操作是:
1>. 关闭iis
2>. 更改php保存session的默认路径(参考后面内容)
3>. 开启iis,检查服务器所有站点是否正常
4>. 执行del_temp.bat进行清理
二、修改php的Session保存路径session.save_path
1. 打开php.ini文件,查找到
“;session.save_path = "/tmp"”
将其修改为指定的位置用于存储session,例如,志文工作室将其改为:
session.save_path = "c:/tmp/phpsession"
当然你也可以使用分级目录的方式,比如改为这样:
session.save_path="5;c:/tmp/phpsession"
关于session的分级目录存放请参考后续内容详解
2. 新建文件夹路径:c:/tmp/phpsession
3. 添加该路径(即phpsession文件夹)的internet来宾账户修改和写入权限,注意最好不要给予执行权限。
4. 启动iis,观察该目录是否会有新的session文件产生。
三、php的session多级目录存放解决大量临时文件效率问题
session多级存放可以缓解一个目录下session文件过多带来的读写效率问题。
php.net上针对sesstion配置相关的说明:http://cn.php.net/manual/zh/ref.session.php
session.save_pathstring
session.save_path 定义了传递给存储处理器的参数。如果选择了默认的 files 文件处理器,则此值是创建文件的路径。默认为 /tmp。参见 session_save_path()。
此指令还有一个可选的 N 参数来决定会话文件分布的目录深度。例如,设定为 '5;/tmp' 将使创建的会话文件和路径类似于
/tmp/4/b/1/e/3 /sess_4b1e384ad74619bd212e236e52a5a174If
要使用 N 参数,必须在使用前先创建好这些目录。在 ext/session 目录下有个小的 shell 脚本名叫 mod_files.sh 可以用来做这件事。此外注意如果使用了 N 参数并且 N 大于 0,那么将不会执行自动垃圾回收,更多信息见 php.ini。
另外如果用了 N 参数,要确保将 session.save_path 的值用双引号 “quotes” 括起来,因为分隔符分号( ;)在 php.ini 中也是注释符号。
参考以上说明,在定义session.save_path中可以定义多级存放的路径,于是我们可以修改php.ini中的session.save_path为:
session.save_path = “2;/data/session_tmp”
如此将session文件分成两级存放,即类似于
/data/session_tmp/4/b/sess_4b1e384ad74619bd212e236e52a5a174If
取session的前两位字符作为二级目录索引,但是php并不生成目录,需要自己手工生成,这里提供一个php脚本来生成初始的目录。
复制代码 代码如下:
<?php
$string = '0123456789abcdefghijklmnopqrstuvwxyz';
$length = strlen($string);
function makeDir($param)
{
if(!file_exists($param)) {
echo "mkdir ".$param."\n”;
exec("mkdir ".$param);
}
}
for($i = 0; $i < $length; $i++) {
for($j = 0; $j < $length; $j++) {
makeDir('/data/session_tmp/'.$string[$i].'/'.$string[$j]);
}
}
?>
session目录分级处理之后,IO处理值增加,http进程降低,web处理效率明显好转
相关参考
session.save_path目录大量session临时文件带来的服务器效率问题
http://wenku.baidu.com/view/b3921d8ea0116c175f0e484e.html
IIS PHP环境Temp文件夹的权限问题引起的网站故障
http://www.jb51.net/article/34301.htm 1.session.save_handler = files
* 1. session_start()
1. session_start()是session机制的开始,它有一定概率开启垃圾回收,因为session是存放在文件中,
PHP自身的垃圾回收是无效的,SESSION的回收是要删文件的,这个概率是根据php.ini的配置决定的,
但是有的系统是 session.gc_probability = 0,这也就是说概率是0,而是通过cron脚本来实现垃圾回收。
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440//过期时间 默认24分钟
//概率是 session.gc_probability/session.gc_divisor 结果 1/1000,
//不建议设置过小,因为session的垃圾回收,是需要检查每个文件是否过期的。
session.save_path = //好像不同的系统默认不一样,有一种设置是 "N;/path"
//这是随机分级存储,这个样的话,垃圾回收将不起作用,需要自己写脚本
2. session会判断当前是否有$_COOKIE;session_name()返回保存session_id的COOKIE键值,
这个值可以从php.ini找到
session.name = PHPSESSID //默认值PHPSESSID
3. 如果不存在会生成一个session_id,然后把生成的session_id作为COOKIE的值传递到客户端.
相当于执行了下面COOKIE 操作,注意的是,这一步执行了setcookie()操作,COOKIE是在header头中发送的,
这之前是不能有输出的,PHP有另外一个函数 session_regenerate_id() 如果使用这个函数,这之前也是不能有输出的。
setcookie(session_name(),
session_id(),
session.cookie_lifetime,//默认0
session.cookie_path,//默认'/'当前程序跟目录下都有效
session.cookie_domain,//默认为空
)
4. 如果存在那么session_id = $_COOKIE;
然后去session.save_path指定的文件夹里去找名字为'SESS_' . session_id()的文件.
读取文件的内容反序列化,然后放到$_SESSION中
* 2. 为$_SESSION赋值
比如新添加一个值$_SESSION['test'] = 'blah'; 那么这个$_SESSION只会维护在内存中,当脚本执行结束的时候,
用把$_SESSION的值写入到session_id指定的文件夹中,然后关闭相关资源. 这个阶段有可能执行更改session_id的操作,
比如销毁一个旧的的session_id,生成一个全新的session_id.一半用在自定义 session操作,角色的转换上,
比如Drupal.Drupal的匿名用户有一个SESSION的,当它登录后需要换用新的session_id
if (isset($_COOKIE)) {
setcookie(session_name(), '', time() - 42000, '/');//旧session cookie过期
}
session_regenerate_id();//这一步会生成新的session_id
//session_id()返回的是新的值
3.写入SESSION操作
在脚本结束的时候会执行SESSION写入操作,把$_SESSION中值写入到session_id命名的文件中,可能已经存在,
可能需要创建新的文件。
* 4. 销毁SESSION
SESSION发出去的COOKIE一般属于即时COOKIE,保存在内存中,当浏览器关闭后,才会过期,假如需要人为强制过期,
比如 退出登录,而不是关闭浏览器,那么就需要在代码里销毁SESSION,方法有很多,
o 1. setcookie(session_name(), session_id(), time() - 8000000, ..);//退出登录前执行
o 2. usset($_SESSION);//这会删除所有的$_SESSION数据,刷新后,有COOKIE传过来,但是没有数据。
o 3. session_destroy();//这个作用更彻底,删除$_SESSION 删除session文件,和session_id
当不关闭浏览器的情况下,再次刷新,2和3都会有COOKIE传过来,但是找不到数据
2.session.save_handler = user
用户自定义session处理机制,更加直观
* session_set_save_handler('open', 'close', 'read', 'write', 'destroy', 'gc');
1.session_start(),
执行open($save_path, $session_name)打开session操作句柄
$save_path 在session.save_handler = files的情况下它就是session.save_path,
但是如果用户自定的话,这个两个参数都用不上,直接返回TRUE
执行read($id)从中读取数据.//这个参数是自动传递的就是session_id(),可以通过这个值进行操作。
* 2.脚本执行结束
执行write($id, $sess_data) //两个参数,很简单
* 3.假如用户需要session_destroy()
先执行destroy.在执行第2步
一个实际例子:
//SESSION初始化的时候调用
function open($save_path, $session_name)
{
global $sess_save_path;
$sess_save_path = $save_path;
return(true);
}
//关闭的时候调用
function close()
{
return(true);
}
function read($id)
{
global $sess_save_path;
$sess_file = "$sess_save_path/sess_$id";
return (string) @file_get_contents($sess_file);
}
//脚本执行结束之前,执行写入操作
function write($id, $sess_data)
{
echo "sdfsf";
global $sess_save_path;
$sess_file = "$sess_save_path/sess_$id";
if ($fp = @fopen($sess_file, "w")) {
$return = fwrite($fp, $sess_data);
fclose($fp);
return $return;
} else {
return(false);
}
}
function destroy($id)
{
global $sess_save_path;
$sess_file = "$sess_save_path/sess_$id";
return(@unlink($sess_file));
}
function gc($maxlifetime)
{
global $sess_save_path;
foreach (glob("$sess_save_path/sess_*") as $filename) {
if (filemtime($filename) + $maxlifetime < time()) {
@unlink($filename);
}
}
return true;
} 彻底理解PHP的SESSION机制
页:
[1]