查找开放会话数

时间:2009-03-24 23:25:17

标签: php session

我正在寻找一种简单(无数据库)的方法来列出网站上有多少用户活跃。我能想到的最简单的方法是计算开放会话的数量。

此代码应该有效:

$number_of_users = count(scandir(ini_get("session.save_path")));

当然它不会因为该目录的安全限制(因为应该有!!)。有没有人知道在不更改目录权限的情况下访问此号码的另一种方式。

注意:我正在寻找不涉及数据库或降低PHP会话安全性的选项。

结束注意:对于任何人来到这个问题,我最终使用了一个来自root的cronjob(每分钟运行一次),它做了类似的事情:

ls /var/lib/php5/ | wc -l > /var/www/sessioncount

确保apache用户可以读取/var/www/sessioncount文件。然后你可以用PHP读取文件:

$number_of_users = file_get_contents("/var/www/sessioncount");

4 个答案:

答案 0 :(得分:5)

<?
// you must set your own accessible session path atop every page.
session_save_path("/home/some/other/location/"); # SECURITY VIOLATION!!!
session_start();

function session_count() {
  $filter = "sess_";
  $files = scandir(session_save_path());
  $count = 0;
  foreach ($files as $file) {
    if(strpos($file,$filter)===0) {
      $count += 1;
    }
  }
  return $count;
}

echo session_count();
?>

答案 1 :(得分:4)

在这种情况下,Easy并不意味着没有数据库。还依靠会话来查看有多少用户是不可靠的。

如果你想走这条路,你可以每隔几分钟做一个由安全进程运行的cronjob,并将该数量保存到PHP读取的文件或数据库中。

但我建议你去数据库路线。

答案 2 :(得分:2)

为了解决这个问题,请点击此处。按顺序组装代码,并在途中使用指示。需要PHP的GD扩展。

在您的webroot中创建一个目录,确保Web守护程序可以写入它:

mkdir liveusers

touch 代码创建 PHP脚本(例如 vlive.php )(顺便说一句.touch是标准的* nix命令,使用system(),passthru()或exec()无论你想使用它,都可以使用它。让触摸该目录中的文件具有唯一的文件名,例如IP + SessionID连接在一起:

<?php 
exec("touch ". $_SERVER['DOCUMENT_ROOT']."/liveusers/". md5($_SERVER['REMOTE_ADDR'].session_id())); /* SECURITY RISK */

现在,在同一个文件中,我们需要输出一个JPEG,用正确的标题完成它()我把一个名为 pixel.jpg 的1x1像素输入到webroot的 / images / directory ,随意做其他事情:

$NewImage = imagecreatefromjpeg($_SERVER['DOCUMENT_ROOT']. "/images/pixel.jpg");
header("Content-type: image/jpeg");
imagejpeg($NewImage);
?>

保存PHP文件,然后在文档中放置标准HTML标记以使其有用:

<img src="/vlive.php" alt="Imagination!" />

使用纯粹的PHP然后缓存页面只会使实时用户文件几乎不能触摸'd。通过这样做,您仍然可以计算“实时”用户并在您的网站上使用整页缓存系统。

好的,现在访问者加载的每个页面都会触及他们的唯一文件,因此如果他们刚刚到达,则触摸命令将为该用户创建一个文件,如果他们也访问其他页面,它将编辑访问日期那个触摸命令。

这是有用的地方:

在另一个PHP脚本中(假设 readvlive.php ):

<?php 
$livenum = system("find ".$_SERVER['DOCUMENT_ROOT']."/liveusers/ -type f -amin +10 | wc -l");
echo "Live Visitors: ". $livenum;
?>

现在让我们将这个片段包含在您希望在其中看到的HTML元素中:

<?php include($_SERVER['DOCUMENT_ROOT']. "/readvlive.php"); ?>

好的,现在我们有一个文件,它会打印出仅在10分钟前更改访问时间的唯一文件数。这些是我们过去十分钟的实时用户......

现在我们可以在这里进行选择,如果您使用整页缓存,则可能会将缓存的实时号码冻结到这些文档中,从而使其变得相当恼人和无用。为此,我建议使用PrototypeJS(Google it),使用他们喜欢的AJAX工具,将它放在 <head></head>

之间
<script src="/js/prototype.js" type="text/javascript"></script>

然后将其置于 </body> 标记上方。

<span id="live_users_count">&nbsp;</span>


<script type="text/javascript">
    <!--
    Event.observe(window, 'load', function() {
        if($('live_users_count')) {
            new Ajax.Updater('live_users_count','/readvlive.php'); 
        }
   }
-->
</script>

应该没问题......不要太粗糙。如果您担心目录将运行该命令的程度,您可以使用APC或其他东西来缓存它。 此示例需要APC 3.1.4:

<?php
if(apc_exists('livenum')){
    $livenum = apc_fetch('livenum');echo $livenum;
} else {
    $livenum = system("find ".$_SERVER['DOCUMENT_ROOT']."/liveusers/ -type f -amin +10 | wc -l");
    apc_add('livenum',$livenum,30); 
}
?>

APC 3.0.13及以上:

<?php
if($livenum = apc_fetch('livenum')){
    echo $livenum;
} else {
    $livenum = system("find ".$_SERVER['DOCUMENT_ROOT']."/liveusers/ -type f -amin +10 | wc -l");
    apc_add('livenum',$livenum,30); 
}
?>

这些将使用APC缓存30秒显示最后10分钟的实时用户,将运行find命令每分钟计算两次。不错。 :P

可以使用crontab进行清理..

脚本( /root/deloverhead.sh ):

#!/bin/sh
find "/path/to/liveusers/ -type f -amin +60 -exec rm {} \;

Crontab条目(每小时):

0 * * * * /root/deloverhead.sh >/dev/null 2>&1

玩得开心,抱歉,我可能会解释一些奇怪的事情。 :P

答案 3 :(得分:0)

您不能从PHP脚本访问该目录而不会带来安全风险。

实现您想要的最简单方法是使用数据库。只需存储ip和时间戳,然后根据时间戳选择SELECT以获取您网站上的活跃用户数。