【问题标题】:Find Number of Open Sessions查找打开的会话数
【发布时间】:2010-10-15 08:17:39
【问题描述】:

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

这段代码应该可以工作:

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

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

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

结束说明:对于提出这个问题的任何人,我最终都从 root 使用了一个 cronjob(每分钟运行一次),它做了类似的事情:

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

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

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

【问题讨论】:

    标签: php session


    【解决方案1】:
    <?
    // 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();
    ?>
    

    【讨论】:

    • 好的,这涉及打开一个巨大的安全风险,所以不是我正在寻找的答案。不过还是谢谢。
    • 嗯,为什么这是一个安全问题? (或者你的意思是在 webroot 中)
    【解决方案2】:

    在这种情况下,简单并不意味着没有数据库。同样依靠会话来查看有多少用户处于活动状态也是不可靠的。

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

    但我建议走数据库路线。

    【讨论】:

    • 数据库方法是任何 Web 应用程序最慢和最大的节流阀。我的目标是将数据库查询的数量减少到最低限度。我喜欢 cronjob 的想法,或者至少是一个正在运行的进程。
    【解决方案3】:

    为了其他人解决这个问题,在这里。按顺序组装代码,并在途中使用说明。需要 PHP 的 GD 扩展。

    在你的 webroot 中创建一个目录,确保 web 守护进程可以写入:

    mkdir liveusers
    

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

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

    现在,在 同一个文件中,我们需要输出一个 JPEG 并使用适当的 header() 来完成它,我将一个名为 pixel.jpg 的 1x1 像素放入webroot 的 /images/ 目录,随意做点别的:

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

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

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

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

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

    这就是它有用的地方:

    在不同的 PHP 脚本中(比如 readvlive.php):

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

    现在让我们将这个 sn-p 包含到您希望在其中看到它的 HTML 元素中:

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

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

    现在我们在这里有了一个选择,同样,如果您使用整页缓存,您可能会将缓存的实时号码冻结到这些文档中,从而使其相当烦人且无用。为此,我建议 PrototypeJS (Google it),你使用他们花哨的 AJAX 工具,将其放在 &lt;head&gt;&lt;/head&gt;

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

    然后将其放在 &lt;/body&gt; 标记上方。

    <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>
    

    应该没问题..不要太粗糙。如果你担心你的目录将运行多少 find 命令,你可以使用 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

    【讨论】:

      【解决方案4】:

      如果不构成安全风险,您无法从 PHP 脚本访问该目录。

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

      【讨论】:

      • 我想要一个没有数据库的方法。谢谢
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多