iDigLiveMusic
iDigLiveMusic

Reputation: 1

display /var/log/messages in html/php output?

I am trying to display the output of /var/log/messages or similar (../secure for instance) in a webpage that I access through a webserver on the same host.

Should I use bash to tail -f >> the messages file to a new output file and display that text file in the html page, or is there a better way to do this?

Thanks! idiglivemusic

Upvotes: 0

Views: 2791

Answers (5)

iDigLiveMusic
iDigLiveMusic

Reputation: 1

<!DOCTYPE html>
<html>
 <head>
  <title>toyLogs</title>
 </head>
 <body>
  <div><p><?php include('/var/www/html/accesslog.txt'); ?></p></div>
 </body>
</html>

Upvotes: -1

sjsam
sjsam

Reputation: 21955

Method 1

In one of your base directories, create a symbolic link

ln -s /var/log/messages messages

If the directory belonged to say, test.web, access the log with unmesh http://test.web/messages

Method 2

If you're looking for a php script then, first create the link as mentioned in method 1. Then, create a new file, say, readlog.php in the base directory of test.web with the below content :

<?php
readfile(“$DOCUMENT_ROOT/messages”);
?>

Access the readlog.php like :

http://test.web/readlog.php

Requirement:

Read access should be enabled for all users for /var/log/messages.

Note:

Setting read option for /var/log/messages for the whole world is NOT a good idea.

Upvotes: 0

Ruslan Osmanov
Ruslan Osmanov

Reputation: 21492

If you're looking for a way to display actual file contents online without the need to reload the page, then you should setup a WebSocket server.

You can build a WebSocket server using a framework such as phpDaemon, ReactPHP, Ratchet, icicle, or implement your own server with the help of PHP extensions wrapping asynchronous libraries: event, ev, or similar.

I've chosen a random framework from the list above: Ratchet. Ratchet is based on ReactPHP. ReactPHP chooses a backend for the event loop from the following list: - libevent extension, - libev extension, - event extension, - or an internal class based on the built-in stream_select() function.

As a maintainer of the event extension, I've chosen event.

I've written a "quick" example just to give you idea of how it might be implemented. You'll most likely have to work out your own version, maybe using different tools. But the code should give you an impulse.

src/MyApp/Server.php

<?php
namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class Server implements MessageComponentInterface {
  protected $clients;

  public function __construct() {
    $this->clients = new \SplObjectStorage;
  }

  public function onOpen(ConnectionInterface $conn) {
    $this->clients->attach($conn);
    echo "New connection! ({$conn->resourceId})\n";
  }

  public function onMessage(ConnectionInterface $from, $msg) {
    $numRecv = count($this->clients) - 1;
    printf("Connection %d sending '%s' to %d other connection%s\n",
      $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');

    foreach ($this->clients as $client) {
      if ($from !== $client) {
        $client->send($msg);
      }
    }
  }

  public function onClose(ConnectionInterface $conn) {
    $this->clients->detach($conn);
    echo "Connection {$conn->resourceId} has disconnected\n";
  }

  public function onError(ConnectionInterface $conn, \Exception $e) {
    echo "An error has occurred: {$e->getMessage()}\n";
    $conn->close();
  }

  public function broadcast($msg) {
    foreach ($this->clients as $client) {
      $client->send($msg);
    }
  }
}

server.php

<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Server;

require __DIR__ . '/vendor/autoload.php';

$server = IoServer::factory(
  new HttpServer(
    new WsServer(
      $my_app_server = new Server()
    )
  ),
  9989
);

$loop = $server->loop;
$filename = '/var/log/messages';

$loop->addPeriodicTimer(5, function ()
  use ($filename, $my_app_server)
  {
    static $stat_info;

    if ($stat_info == null) {
      clearstatcache(true, $filename);
      $stat_info = stat($filename);
    }

    clearstatcache(true, $filename);
    $st = stat($filename);

    $size_diff = $st['size'] - $stat_info['size'];
    echo "Diff = $size_diff bytes\n";

    if ($size_diff > 0) {
      $offset = $stat_info['size'];
      $bytes = $size_diff;
    } elseif ($size_diff < 0) {
      // The file is likely truncated by `logrotate` or similar utility
      $offset = 0;
      $bytes = $st['size'];
    } else {
      $bytes = 0;
    }

    $stat_info = $st;

    if ($bytes) {
      if (! $fp = fopen($filename, 'r')) {
        fprintf(STDERR, "Failed to open file $filename\n");
        return;
      }
      if ($offset > 0) {
        fseek($fp, $offset);
      }
      if ($msg = fread($fp, $bytes)) {
        $my_app_server->broadcast($msg);
      }
      fclose($fp);
    }
  }
);

$server->run();

test.html

<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <title>Test</title>
</head>
<body>
  <script>
  var conn = new WebSocket('ws://localhost:9989');
  conn.onopen = function(e) {
    console.log("Connection established!");
  };
  conn.onmessage = function(e) {
    console.log("Msg from server", e.data);
  };
  </script>
</body>
</html>

I'll skip the steps required to setup a basic test environment using Composer. Assuming you have successfully configured the test environment for the files above, you'll be able to run the server with the following command:

php server.php

Check, if the user has permissions to read /var/log/messages. On my system only root can read the file. So you might need to run the above-mentioned command with sudo(root permissions).

Now you can open test.html in a browser and look at the console output. Then trigger some event which is normally logged to the messages file. For instance, you can invoke sudo with a wrong password. The server should detect the changes within interval of 5 seconds, then send it to the WebSocket clients.

Upvotes: 2

Walter A
Walter A

Reputation: 19982

Make sure that your html-server has rights to access the page and read the page (with something like cat, tail, grep). In <html> put the output between <pre> and </pre>.

Upvotes: 0

Sergey Brodin
Sergey Brodin

Reputation: 361

If you're using tail -f, that means that you'll be continuously getting data from the file while it grows as the command runs. You can use cat or tail -n. Also, of course, you can access files directly by creating a symbolic or hard link to them (ln source-file link-file, ln -s source-file link-file) - but make sure, that your web-server has enough rights to access them.

Upvotes: 1

Related Questions