Skip to content

Instantly share code, notes, and snippets.

@lbussy
Last active March 20, 2023 16:05
Show Gist options
  • Save lbussy/5b7f5818de797284ff134cf9d5b22112 to your computer and use it in GitHub Desktop.
Save lbussy/5b7f5818de797284ff134cf9d5b22112 to your computer and use it in GitHub Desktop.
Single File PHP Log file Tail/View
<!--
PHP Log Tail
by Lee C. Bussy
A single-page log file viewer with "tail -f" capabilities.
Pass the name of the log file to be viewed as a URL parameter:
log_tail.php?logFile=my.log
For safety and to prevent breakouts, the path to the log file
is hard-coded as $logDir. This is compared to the concatenated
path before reading to eliminate any "../.." shenanigans.
The page will send a second request to itself with:
log_tail.php?getLog=True
The getLog parameter will cause the page to feed the log file
into the original page.
-->
<?php
$logDir = "/var/log"; // Prepend this path (no trailing slash)
$shortName = $_GET['logFile']; // Log file to get = ?logFile={foo}
$logPath = $logDir . "/" . $shortName;
if (isset($_GET['getLog'])) {
$thisDirName = dirname(realpath($logPath));
if ($thisDirName == $logDir) {
if (is_file($logPath)) {
echo file_get_contents($logPath);
} else {
echo "No log found.";
}
} else {
echo "Error: Illegal input - path name.";
}
} else {
?>
<!DOCTYPE html>
<html lang="en">
<title>Log Viewer</title>
<link rel="stylesheet" href="logstyle.css">
<script
src="https://code.jquery.com/jquery-3.6.4.min.js"
integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8="
crossorigin="anonymous">
</script>
<script>
let thisPage = window.location.pathname;
let interval = 1000;
var scrollLock = true;
var readingFile = false;
// Get logfilename from ?logFile={foo}
const params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
});
let thisLog = params.logFile;
$(document).ready(function(){
$('.disableScrollLock').click(function(){
$("html,body").clearQueue()
$(".disableScrollLock").hide();
$(".enableScrollLock").show();
scrollLock = false;
});
$('.enableScrollLock').click(function(){
$("html,body").clearQueue()
$(".enableScrollLock").hide();
$(".disableScrollLock").show();
scrollLock = true;
});
setInterval(readLogFile, interval);
});
function readLogFile() {
// Singleton trap
if (! readingFile) {
readingFile = true;
$.get(thisPage, { getLog : "true", logFile : thisLog }, function(data) {
data = data.replace(new RegExp("\n", "g"), "<br />");
$("#log").html(data);
if(scrollLock == true) { $('html,body').animate({scrollTop: $("#scrollLock").offset().top}, interval) };
})
.fail(function() {
alert( "GET error (this should not be possible.)" );
})
.always(function() {
readingFile = false;
});
}
}
</script>
<body>
<h4><?php echo "Following: " . $shortName; ?></h4>
<div id="log"></div>
<div id="scrollLock"> <input class="disableScrollLock" type="button" value="Disable Scroll Lock"> <input class="enableScrollLock" style="display: none;" type="button" value="Enable Scroll Lock"></div>
</body>
</html>
<?php
}
?>
@import url(http://fonts.googleapis.com/css?family=Ubuntu);
body {
background-color: black;
color: white;
font-family: 'Ubuntu', sans-serif;
font-size: 16px;
line-height: 20px;
}
h4 {
background-color: black;
color: white;
font-size: 18px;
line-height: 80px;
}
#log {
position: relative;
top: -34px;
}
#scrollLock {
width: 2px;
height: 2px;
overflow: visible;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment