大众世界 world of demotic + 社区新动力

 找回密码
 注册会员
搜索
查看: 6376|回复: 3

[操作系统] IIS+php服务器里删除Temp里的sess_文件非常重要

[复制链接]
发表于 2014-7-12 19:17:50 | 显示全部楼层 |阅读模式
     我用的是windows2003服务器,里面可以同时运行IIS  ASP和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 *.*

删除所有文件 ,但不删除文件夹、

回复

使用道具 举报

 楼主| 发表于 2015-4-23 11:39:17 | 显示全部楼层
最近志文工作室所在的服务器经常宕机,而且重启后也总是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_path  string
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
回复

使用道具 举报

 楼主| 发表于 2015-4-23 11:47:36 | 显示全部楼层
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_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_name];
            然后去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[session_name()])) {
          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;
      }
回复

使用道具 举报

 楼主| 发表于 2015-4-23 11:48:04 | 显示全部楼层
彻底理解PHP的SESSION机制
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Archiver|手机版|小黑屋|Wod Inc. ( 蜀ICP备20000008号-8

GMT+8, 2024-5-10 11:53 , Processed in 0.123295 second(s), 33 queries .

Powered by Discuz! X3.5

Copyright © 2001-2023 Tencent Cloud.

快速回复 返回顶部 返回列表