Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nodejs spawn remote tail and socket-io to client

I'm fairly new to Nodejs and I'm building an app that ssh to a remote machine and get a tail -f of a log file.

The lines of the log file I'm receiving I'm sending to the client via socket-io (ver. 2.0.3)

Now I'm facing a problem that when a second browser tries to tail a different log, the new log is sent to both of the browsers instead of only the one who made the request. I'm not sure if it's a problem with my socket-io code or the child_process.

Here's the server:

const express = require('express'),
    app = express(),
    path = require('path'),
    bodyParser = require('body-parser'),
    logger = require('morgan'),
    server = require('http').Server(app),
    io = require('socket.io')(server),
    spawn = require('child_process').spawn,
    events = require('events'),
    eventEmitter = new events.EventEmitter();


// Fix body of requests
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());

// Log the requests
app.use(logger('dev'));

// Serve static files
app.use(express.static(path.join(__dirname, '.')));

// Add a basic route – index page
app.get('/', function (req, res) {
    res.sendFile(path.join(__dirname, 'index.html'));
});

io.on('connection', (socket) => {
    console.log(`client connected ${socket.client.id}`);
    eventEmitter.on('tail', (data) => {
        socket.tail = spawn('ssh', ['root@' + 'quality-p.company.com', 'tail -f', data.service], { shell: true });
        socket.tail.stdout.on('data', (data) => {
            console.log(`got new data ${data.toString()}`);
            socket.emit('newLine', {line: data.toString().replace(/\n/g, '<br />')});
        });
    });
});

app.get('/tail', (req, res) => {
    eventEmitter.emit('tail', req.query);
    res.sendStatus(200);
});

// Bind to a port
server.listen(3005, () => {
    console.log('running on localhost:' + 3005);
});

Client:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="./node_modules/socket.io-client/dist/socket.io.js"></script>
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <script>
        $(() => {
            let socket = io();
            socket.on('connect', () => {
                console.log('connected');
            });
            socket.on('newLine', (data) => {
                console.log(`new data: ${data.line}`);
                $("#tailing").append(data.line);
            });
            $('#tail').click(() => {
                $.get('/tail', {
                    service: $('#service').val()
                });
            });
        });
    </script>
    <title>Title</title>
</head>
<body>
<select id="service">
    <option id="tnet" value="/var/log/tnet">tnet</option>
    <option id="consul" value="/var/log/consul">consul</option>
</select>
<button id="tail">tail</button>
<div id="tailing" style="background-color: antiquewhite;">
</div>
</body>
</html>
like image 916
Moshe Avatar asked Sep 26 '26 20:09

Moshe


1 Answers

Server

const express = require('express'),
    app = express(),
    path = require('path'),
    bodyParser = require('body-parser'),
    logger = require('morgan'),
    server = require('http').Server(app),
    io = require('socket.io')(server),
    spawn = require('child_process').spawn;


// Fix body of requests
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

// Log the requests
app.use(logger('dev'));

// Serve static files
app.use(express.static(path.join(__dirname, '.')));

// Add a basic route – index page
app.get('/', function(req, res) {
    res.sendFile(path.join(__dirname, 'index.html'));
});

var tails = {};

io.on('connection', (socket) => {
    console.log(`client connected ${socket.client.id}`);
    socket.on('tail', (data) => {
        socket.join(data.service);
        if (typeof tails[data.service] == "undefined") {
            tails[data.service] = spawn('ssh', ['root@' + 'quality-p.company.com', 'tail -f', data.service], {
                shell: true
            });
            tails[data.service].stdout.on('data', (data) => {
                console.log(`got new data ${data.toString()}`);
                io.to(data.service).emit('newLine', {
                    line: data.toString().replace(/\n/g, '<br />')
                });
            });
        }
    });
});


// Bind to a port
server.listen(3005, () => {
    console.log('running on localhost:' + 3005);
});

Client

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <script src="./node_modules/socket.io-client/dist/socket.io.js"></script>
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <script>
        $(() => {
            let socket = io();
            socket.on('connect', () => {
                console.log('connected');
            });
            socket.on('newLine', (data) => {
                console.log(`new data: ${data.line}`);
                $("#tailing").append(data.line);
            });
            $('#tail').click(() => {
                socket.emit('tail', {
                    service: $('#service').val()
                });
            });
        });
    </script>
    <title>Title</title>
</head>

<body>
    <select id="service">
    <option id="tnet" value="/var/log/tnet">tnet</option>
    <option id="consul" value="/var/log/consul">consul</option>
</select>
    <button id="tail">tail</button>
    <div id="tailing" style="background-color: antiquewhite;">
    </div>
</body>

</html>

Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!