You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取日志中用户登录失败次数及日期?PHP代码故障排查

解决PHP读取登录失败日志时跨行读取的问题

你遇到的问题根源很明确:在每次循环里调用了两次$file->fgetcsv("|"),这个方法每次执行都会读取文件的下一行内容。第一次调用拿到第一行数据,第二次调用直接跳到第二行,自然就把第一行的用户名和第二行的日期拼在一起了,完全不符合预期。

咱们先看你的原始日志格式,每一行都是用|分隔的字段,结构是:用户名|日期|IP|主机|Failed(少数行日期格式不同,但不影响提取)。接下来我会帮你修正代码,同时实现你真正需要的「统计用户登录失败次数及对应日期详情」的需求:

修正后的完整代码

<?php
// 初始化统计数组,键是用户名,值是包含次数和日期列表的数组
$loginFailStats = [];

$file = new SplFileObject("failed.log", "r");
// 设置CSV的分隔符为|
$file->setCsvControl("|");

while (!$file->eof()) {
    // 只调用一次fgetcsv,获取当前行的所有字段
    $row = $file->fgetcsv();
    // 跳过空行或者格式不正确的行
    if (empty($row) || count($row) < 5) {
        continue;
    }
    
    $username = trim($row[0]);
    $date = trim($row[1]);
    
    // 统计逻辑
    if (!isset($loginFailStats[$username])) {
        $loginFailStats[$username] = [
            'count' => 0,
            'dates' => []
        ];
    }
    $loginFailStats[$username]['count']++;
    $loginFailStats[$username]['dates'][] = $date;
}

// 输出统计结果
echo "登录失败统计结果:\n";
foreach ($loginFailStats as $user => $stats) {
    echo "- 用户 *{$user}* 登录失败 {$stats['count']} 次,失败日期:\n";
    foreach ($stats['dates'] as $date) {
        echo "  - {$date}\n";
    }
}
?>

代码说明

  • 用$file->setCsvControl("|")提前设置CSV分隔符,调用fgetcsv()时无需重复传参,代码更规范。
  • 每次循环只调用一次fgetcsv(),确保拿到当前行的完整数据,彻底避免跨行读取的问题。
  • 加入了空行和无效行的判断,防止日志里的异常行导致程序出错。
  • 用关联数组$loginFailStats存储每个用户的失败次数和日期列表,完美匹配你的统计需求。

预期输出

运行这段代码后,你会得到清晰的统计结果,类似这样:

登录失败统计结果:

  • 用户 John 登录失败 1 次,失败日期:
    • 26:Dec:2017:16:09:45
  • 用户 cena 登录失败 1 次,失败日期:
    • 26:Dec:2017:16:15:27
  • 用户 Abc 登录失败 2 次,失败日期:
    • 27:Dec:2017:09:25:25
    • 04/Jan/2018 15:54:35
  • 用户 Bhumi 登录失败 2 次,失败日期:
    • 29:Dec:2017:09:39:45
    • 29:Dec:2017:10:19:28
  • 用户 Avccc 登录失败 1 次,失败日期:
    • 29/Dec/2017 14:15:41

这样就完全解决了你之前的跨行读取问题,同时满足了统计需求。

内容的提问来源于stack exchange,提问作者Shivu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:26:18