I’ve been playing with Node.js and decided to see if I could create a service that could be run out of xinetd. Running a service out of xinetd requires that it use stdin (fd 0) for it’s connection. To accomplish this I subclassed from http.Server adding a connectFD method to be able to set the file descriptor for the server to use.
var sys = require('sys'),
net = require('net'),
http = require('http');
var Server = function (listener) {
http.Server.call(this, listener);
};
sys.inherits(Server, http.Server);
exports.Server = Server;
Server.prototype.connectFD = function (fd) {
var s = new net.Stream(fd);
s.type = this.type;
s.server = this;
s.resume();
this.emit('connection', s);
}
I named this xhttp.js.
You need a service configuration file in /etc/xinetd.d to specify the port and command similar to:
# default: on
# description: node.js based service
#
service xnode
{
disable = no
port = 49000
socket_type = stream
protocol = tcp
wait = no
user = root
server = <path of node executable>
server_args = <path of services js file>
env = NODE_PATH=<path to xhttp.js file>
}
Don’t forget to set the required path names.
For my service I decided to have a little fun and have it run commands on the server and return the output.
var sys = require('sys'),
xhttp = require('xhttp'),
url = require('url'),
exec = require('child_process').exec;
var requestHandler = function (req, res) {
var cmd = url.parse(req.url).pathname;
cmd = cmd.substring(1);
qstr = url.parse(req.url, true).query
for (key in qstr) {
cmd = cmd + " " + qstr[key];
}
var child = exec(cmd,
function (error, stdout, stderr) {
res.writeHead(200, {'Content-Type': 'text/plain'});
if (error !== null) {
res.write(stderr);
}
else {
res.write(stdout);
}
res.end();
});
}
var s = new xhttp.Server(requestHandler);
s.connectFD(0);
After adding the xinetd configuration file to /etc/xinetd.d restart xinetd and try something like :
it was very interesting to read.
I want to quote your post in my blog. It can?
And you et an account on Twitter?
Sure, you can quote it.