Статьи

Веб-консоль с node.js

Продолжая мои эксперименты с node.js, на этот раз я хочу создать веб-консоль. Идея проста. Я хочу отправить несколько команд на сервер, и я отображаю вывод в браузере. Я могу сделать это полностью с помощью PHP, но я хочу отправить вывод в браузер так быстро, как они появляются, не дожидаясь окончания команды. Хорошо, мы можем сделать это, сбрасывая выходные данные на сервере, но это решение обычно дает сбой, если мы оставляем приложение открытым в течение длительного времени. WebSockets снова на помощь. Если нам нужна кросс-браузерная реализация, нам нужна библиотека socket.io . Давайте начнем:

Сервер узла — это простой сервер веб-сокетов. В этом примере мы запустим каждую команду с функцией spawn (require (‘child_process’). Spawn) и отправим вывод в веб-пакет. Просто и довольно просто.

var sys   = require('sys'),
http = require('http'),
url = require('url'),
spawn = require('child_process').spawn,
ws = require('./ws.js');

var availableComands = ['ls', 'ps', 'uptime', 'tail', 'cat'];
ws.createServer(function(websocket) {
websocket.on('connect', function(resource) {
var parsedUrl = url.parse(resource, true);
var rawCmd = parsedUrl.query.cmd;
var cmd = rawCmd.split(" ");
if (cmd[0] == 'help') {
websocket.write("Available comands: \n");
for (i=0;i<availableComands.length;i++) {
websocket.write(availableComands[i]);
if (i< availableComands.length - 1) {
websocket.write(", ");
}
}
websocket.write("\n");

websocket.end();
} else if (availableComands.indexOf(cmd[0]) >= 0) {
if (cmd.length > 1) {
options = cmd.slice(1);
} else {
options = [];
}

try {
var process = spawn(cmd[0], options);
} catch(err) {
console.log(err);
websocket.write("ERROR");
}

websocket.on('end', function() {
process.kill();
});

process.stdout.on('data', function(data) {
websocket.write(data);
});

process.stdout.on('end', function() {
websocket.end();
});
} else {
websocket.write("Comand not available. Type help for available comands\n");
websocket.end();
}
});

}).listen(8880, '127.0.0.1');

Веб-клиент похож на пример моего предыдущего поста

 

var timeout = 5000;
var wsServer = '127.0.0.1:8880';

var ws;

function cleanString(string) {
return string.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
}

function pad(n) {
return ("0" + n).slice(-2);
}

var cmdHistory = [];
function send(msg) {
if (msg == 'clear') {
$('#log').html('');
return;
}
try {
ws = new WebSocket('ws://' + wsServer + '?cmd=' + msg);
$('#toolbar').css('background', '#933');
$('#socketStatus').html("working ... [<a href="#" onClick='quit()'>X</a>]");
cmdHistory.push(msg);
$('#log').append("<div class='cmd'>" + msg + "</div>");
console.log("startWs:");
} catch (err) {
console.log(err);
setTimeout(startWs, timeout);
}

ws.onmessage = function(event) {
$('#log').append(util.toStaticHTML(event.data));
window.scrollBy(0, 100000000000000000);
};

ws.onclose = function(){
//console.log("ws.onclose");
$('#toolbar').css('background', '#65A33F');
$('#socketStatus').html('Type your comand:');
}
}

function quit() {
ws.close();
window.scrollBy(0, 100000000000000000);
}
util = {
urlRE: /https?:\/\/([-\w\.]+)+(:\d+)?(\/([^\s]*(\?\S+)?)?)?/g,

// html sanitizer
toStaticHTML: function(inputHtml) {
inputHtml = inputHtml.toString();
return inputHtml.replace(/&/g, "&")
.replace(/</g, "<")
.replace("/n", "<br/>")
.replace(/>/g, ">");
},

//pads n with zeros on the left,
//digits is minimum length of output
//zeroPad(3, 5); returns "005"
//zeroPad(2, 500); returns "500"
zeroPad: function (digits, n) {
n = n.toString();
while (n.length < digits)
n = '0' + n;
return n;
},

//it is almost 8 o'clock PM here
//timeString(new Date); returns "19:49"
timeString: function (date) {
var minutes = date.getMinutes().toString();
var hours = date.getHours().toString();
return this.zeroPad(2, hours) + ":" + this.zeroPad(2, minutes);
},

//does the argument only contain whitespace?
isBlank: function(text) {
var blank = /^\s*$/;
return (text.match(blank) !== null);
}
};
$(document).ready(function() {
//submit new messages when the user hits enter if the message isnt blank
$("#entry").keypress(function (e) {
console.log(e);
if (e.keyCode != 13 /* Return */) return;
var msg = $("#entry").attr("value").replace("\n", "");
if (!util.isBlank(msg)) send(msg);
$("#entry").attr("value", ""); // clear the entry field.
});
});

 

 

И это все. На самом деле нам не нужна никакая строка PHP для выполнения этой веб-консоли. В прошлом году я пытался сделать что-то подобное с PHP, но это было большим беспорядком. С узлом такие работы тривиальны. Я не знаю, является ли node.js будущим или просто шумихой, но это легко. И круто. Очень круто.

Вы можете увидеть полный код на Github здесь . В любом случае вы должны позаботиться о том, чтобы запустить это приложение на своем хосте. Вы позволяете пользователю выполнять необработанные команды Unix. Немного уровня безопасности будет необходимо.

 

От http://gonzalo123.wordpress.com/2011/05/16/web-console-with-node-js/