php flushing stdout / stderr

时间:2012-05-30 05:37:03

标签: php stdout stderr

我有一个在我的ubunutu服务器上运行的php脚本。这个脚本在运行查询和收集统计信息的无限循环中运行......它是一些其他服务的监视器。每隔60秒,收集的统计信息将作为json对象转储到.js文件中。 .js文件在其他地方受到监控,对于我的问题而言并不重要。

当我运行脚本时,我将stdout和stderr重定向到日志文件。 在大多数情况下,没有输出标准或错误,因此日志将保持为空。

显然有时会有输出。我昨晚遇到的问题是脚本由于某种原因失败了,日志文件最终填满了整个分区,并且与服务器的稳定性相混淆。

我所做的...或试图做的是添加一个简单的检查,即每60秒(当转储统计信息时)脚本检查日志文件的大小..如果它大于X mb in大小,基本上清空文件并允许记录继续。目的是如果脚本确实再次遇到问题,则日志文件不会填满整个分区。

我可以成功检测到日志文件大小,当它达到我的设置大小时我可以成功清除它,但是下次有STDOUT或STDERR写入时,所有以前的数据都会一次性转储。

对此的任何帮助将不胜感激。


通过以下方式调用脚本:

php checker.php &> log

但已尝试

php checker.php > log 2>&1

并在脚本开头重定向流

close(STDOUT);
fclose(STDERR);
$STDOUT = fopen($LOG_FILE_LOCATION, 'wb');
$STDERR = fopen($LOG_FILE_LOCATION, 'wb');

每种方式产生相同的输出。

代码清除日志文件

function CheckLogFilesize($file)
{
    global $LOG_FILE_LOCATION;
    global $MAX_LOG_SIZE_MB;
    $max_log_size_bytes = $MAX_LOG_SIZE_MB * 1024 * 1024;

    $size = exec('stat -c %s ' . $file);

    // If log file size is too large.. reset it.
    if (intval($size) > $max_log_size_bytes)
    {
        flush();

        // Clear the log
        $fp = fopen($file, 'w');
        fwrite($fp, '');
        fclose($fp);
    }
}

由于

3 个答案:

答案 0 :(得分:1)

如果我必须这样做,我会检测日志文件大小,如果它大于阈值,则将文件移动到另一个文件名(例如old-log.txt)。在这种情况下,您将拥有最多2个日志文件,总大小为阈值的2倍。

优点是在达到阈值后仍然有一些旧的日志条目。如果您只是清除文件,您将看到您尝试在空文件中查找信息

编辑:

看看PHP中的ob_ *命令。它们可以帮助您清除缓冲区

ob_start()在评论中,您可以找到有关stdout

的更多信息
...
ob_start();
// keep writing log until done
ob_end_clean(); // or use ob_end_flush();

一些伪代码......

答案 1 :(得分:1)

如果您要将stdout重定向到日志文件中,您甚至可以尝试unlink()该文件,但它无效,因为您的stdout仍然与之相关联。

一种方法是在启动进程之前清除日志文件,并在文件超出特定大小时停止进程。然后让你的脚本在shell脚本循环中运行(只有在进程存在code = 0时终止,即没有错误);当脚本停止时,它会立即再次启动。

通常情况下,守护程序会打开自己的日志文件,因此您可以向它们发送HUP信号以重新打开其日志文件,从而避免完全重启。

答案 2 :(得分:1)

修改

想出来:

function get_log_size() {
    clearstatcache();
    return filesize("/tmp/log.log");
}

foreach (range(1, 1000000) as $interval) {
    echo $interval . "\n";
    usleep(10000);
    if ($interval % 50 == 0) {
        fwrite(STDERR, "mod 50 fail test");
    }
    $size = get_log_size();
    echo $size . " bytes\n";
    if ($size > 100) {
        $file = "/tmp/log.log";
        $fp = fopen($file, 'w');
        fclose($fp);
        print "Truncated\n";
    }

}

开始

php test.php >> /tmp/log.log 2>&1

请注意>> ,而不是> 。你必须使用追加模式

tail -f /tmp/log.log的输出示例:

λ ~/ tail -f /tmp/log.log

1
2 bytes
2
12 bytes
3
23 bytes
4
34 bytes
5
45 bytes
6
56 bytes
7
67 bytes
8
78 bytes
9
89 bytes
10
101 bytes
Truncated
11
13 bytes
12
25 bytes
13
37 bytes
14
49 bytes
15
61 bytes
16
73 bytes
17
85 bytes
18
97 bytes
19
109 bytes
Truncated
20
13 bytes
21
25 bytes
22
37 bytes
23
49 bytes
24
61 bytes
25
73 bytes
26
85 bytes
27
97 bytes
28
109 bytes
Truncated