Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
if (isset($_GET['seek'])) {
$seek = $_GET['seek'];
$lines = [];
$handle = fopen('error_log', 'rb');
if ($seek > 0) {
fseek($handle, $seek);
while (($line = fgets($handle, 4096)) !== false) {
$lines[] = $line;
$seek = ftell($handle);
header("Content-Type: application/json");
echo json_encode(['seek' => $seek, 'lines' => $lines]);
?><!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<style type="text/css">
body {
margin: 0;
padding: 0;
#app {
font-family: monospace;
font-size: 12px;
white-space: pre-wrap;
color: #333;
<div id="app">
<div v-for="line in lines">{{ line }}</div>
<script src=""></script>
<script src=""></script>
const app = new Vue({
el: '#app',
data: {
lines: [],
seek: 0
mounted () {
setInterval(this.load, 3000);
methods: {
load () {
.then(response => {
this.lines = [, ...this.lines]; =;

This comment has been minimized.

Copy link

@divinity76 divinity76 commented May 2, 2017

don't hardcode the name logs.php , make the code name-independent, replace line 60 with axios.get(`?seek=${}`), and the browser will fill in the blanks, wether it be logs.php or php-tail-log.php (as is the name of this paste), or anythingelse.php.

furthermore, don't use setInterval for this - if you're on a slow connection, and use setInterval, it will start downloading several copies of the same logs simultaneously! (if its slow enough, will keep doing this until you reach the browser's max socket limit!) - call it once to start it, and have it make a setTimeout() for itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment