From ce9cb139f42df4a77d0b64f9d5b190ae990cf8ab Mon Sep 17 00:00:00 2001 From: DanBUK Date: Tue, 26 Jul 2011 12:56:28 +0100 Subject: [PATCH] Interim logging solution until streams are setup. --- lib/app.js | 41 ++++----- scripts/chroot_runner.js | 183 +++++++++++++++++++++++---------------- 2 files changed, 131 insertions(+), 93 deletions(-) diff --git a/lib/app.js b/lib/app.js index d741a33a..8583aeed 100644 --- a/lib/app.js +++ b/lib/app.js @@ -14,29 +14,30 @@ module.exports = { var appname = req.appname; var user = req.user; var app = req.app; - var app_error_log = path.join(config.opt.apps_home_dir, user._id, app.repo_id + '_rw', 'app', 'error.log'); - fs.readFile(app_error_log, function(err, body) { - var code = 200, - resp; - if (err) { - code = 500; - resp = { - success: false, - error: "Failed to read error log." - }; - } else { - var lines = body.toString().split("\n"); - lines = lines.slice(-100); - resp = { + var app_error_log_sock = path.join(config.opt.apps_home_dir, user._id, app.repo_id + '_chroot', '.nodester', 'logs.sock'); + var net = require('net'); + var app_handler = net.createConnection(app_error_log_sock); + app_handler.once('connect', function () { + var buff = ''; + app_handler.on('data', function (data) { + buff += data.toString(); + }); + app_handler.once('end', function () { + try { + var logs_strs = JSON.parse(buff); + } catch (e) { + var logs_strs = {stdout: 'no logs', stderr: ''}; + } + var lines = ('stdout:\n' + logs_strs['stdout'] + '\nstderr:\n' + logs_strs['stderr']).toString().split('\n'); + res.writeHead(200, { + 'Content-Type': 'application/json' + }); + res.write(JSON.stringify({ success: true, lines: lines - }; - } - res.writeHead(code, { - 'Content-Type': 'application/json' + }) + '\n'); + res.end(); }); - res.write(JSON.stringify(resp) + '\n'); - res.end(); }); }, gitreset: function(req, res, next) { diff --git a/scripts/chroot_runner.js b/scripts/chroot_runner.js index 80a173e4..13a668c1 100755 --- a/scripts/chroot_runner.js +++ b/scripts/chroot_runner.js @@ -3,10 +3,10 @@ require.paths.unshift('/usr/lib/node_modules'); var spawn = require('child_process').spawn; -var daemon = require('daemon'); +var daemon = require('daemon.js'); var fs = require('fs'); var path = require('path'); - +var net = require('net'); var config = JSON.parse(fs.readFileSync(path.join('.nodester', 'config.json'), encoding='utf8')); @@ -17,16 +17,45 @@ var run_count = 0; var LOG_STDOUT = 1; var LOG_STDERR = 2; -var error_log_fd = null; +// var error_log_fd = null; var pre_shutdown = function () { - if (typeof error_log_fd != 'null') fs.closeSync(error_log_fd); + // if (typeof error_log_fd != 'null') fs.closeSync(error_log_fd); +}; + +var log_lines_stdout = new Array(); +var log_lines_stderr = new Array(); + +var log_listen = function (p, cb) { + var srv = net.createServer(function (conn) { + var logs = JSON.stringify({ + stdout: log_lines_stdout.join('\n'), + stderr: log_lines_stderr.join('\n') + }); + conn.write(logs); + conn.end(); + }); + srv.listen(p, cb); }; var log_line = function (line, stdout) { if (typeof this == 'string') { - line = this + line; + switch (this) { + case 'chroot_runner': + log_lines_stderr.push(this + ': ' + line); + if (log_lines_stderr.length > 10) log_lines_stderr.shift(); + break; + case 'stdout': + log_lines_stdout.push(line); + if (log_lines_stdout.length > 10) log_lines_stdout.shift(); + break; + case 'stderr': + log_lines_stderr.push(line); + if (log_lines_stderr.length > 10) log_lines_stderr.shift(); + break; + } } + /* if (typeof stdout != 'undefined') { if (stdout == LOG_STDOUT) { console.log(line); @@ -34,7 +63,9 @@ var log_line = function (line, stdout) { console.error(line); } } - if (error_log_fd !== null) fs.write(error_log_fd, line + '\n'); + */ + // if (error_log_fd !== null) fs.write(error_log_fd, line + '\n'); + }; var env = { @@ -49,76 +80,82 @@ if (config.env) { env.app_port = parseInt(config.port, 10); env.app_host = config.ip; var args = ['/app/' + config.start]; - -var chroot_res = daemon.chroot(config.appchroot); -if (chroot_res !== true) { - log_line('chroot_runner: ', 'Failed to chroot to ' + config.apphome, LOG_STDERR); - pre_shutdown(); - process.exit(1); -} -var ch_uid = daemon.setreuid(config.userid); -if (ch_uid !== true) { - log_line.call('chroot_runner: ', 'Failed to change user to ' + config.userid, LOG_STDERR); - pre_shutdown(); - process.exit(2); -} -var child = null; -var child_watcher_time = null; - -var myPid = daemon.start(); -log_line.call('chroot_runner: ', 'New PID: ' + myPid.toString()); -if (path.existsSync('/.nodester/pids/runner.pid')) fs.unlinkSync('/.nodester/pids/runner.pid'); -fs.writeFileSync('/.nodester/pids/runner.pid', myPid.toString()); - -process.on('SIGINT', function () { - log_line.call('chroot_runner: ', 'SIGINT recieved, sending SIGTERM to children.'); - if (child !== null) { - log_line.call('chroot_runner: ', 'Child PID: ' + child.pid.toString()); - process.kill(child.pid, 'SIGTERM'); - process.exit(); - } else { - process.exit(); +var log_sock_path = path.join(config.appchroot, '.nodester', 'logs.sock'); +log_listen(log_sock_path, function () { + try { + fs.chmodSync(log_sock_path, '0777'); + } catch (e) { + log_line('chroot_runner', 'Failed to chmod logs.sock', LOG_STDERR); } -}); - -process.on('SIGTERM', function () { - log_line.call('chroot_runner: ', 'SIGTERM recieved, sending SIGTERM to children.'); - if (child !== null) { - log_line.call('chroot_runner: ', 'Child PID: ' + child.pid.toString()); - process.kill(child.pid, 'SIGTERM'); - process.exit(); - } else { - process.exit(); + log_line('chroot_runner', 'log_listen\'ing', LOG_STDERR); + var chroot_res = daemon.chroot(config.appchroot); + if (chroot_res !== true) { + log_line('chroot_runner', 'Failed to chroot to ' + config.apphome, LOG_STDERR); + pre_shutdown(); + process.exit(1); } -}); + var ch_uid = daemon.setreuid(config.userid); + if (ch_uid !== true) { + log_line.call('chroot_runner', 'Failed to change user to ' + config.userid, LOG_STDERR); + pre_shutdown(); + process.exit(2); + } + var child = null; + var child_watcher_time = null; + + var myPid = daemon.start(); + log_line.call('chroot_runner', 'New PID: ' + myPid.toString()); + if (path.existsSync('/.nodester/pids/runner.pid')) fs.unlinkSync('/.nodester/pids/runner.pid'); + fs.writeFileSync('/.nodester/pids/runner.pid', myPid.toString()); -var start_child = function () { - child = spawn('/usr/bin/node', args, { env: env }); - child.stdout.on('data', log_line.bind('stdout: ')); - child.stderr.on('data', log_line.bind('stderr: ')); - child.on('exit', function (code) { - if (code > 0 && run_count > run_max) { - log_line.call('Watcher: ', 'Error: Restarted too many times, bailing.', LOG_STDERR); - clearInterval(child_watcher_timer); - pre_shutdown(); - process.exit(3); - } else if (code > 0) { - log_line.call('Watcher: ', 'Process died with exit code ' + code + '. Restarting...', LOG_STDERR); - child = null; + process.on('SIGINT', function () { + log_line.call('chroot_runner', 'SIGINT recieved, sending SIGTERM to children.'); + if (child !== null) { + log_line.call('chroot_runner', 'Child PID: ' + child.pid.toString()); + process.kill(child.pid, 'SIGTERM'); + process.exit(); } else { - log_line.call('Watcher: ', 'Process exited cleanly. Dieing.', LOG_STDERR); - clearInterval(child_watcher_timer); - pre_shutdown(); - process.exit(0); + process.exit(); } }); -}; -var child_watcher = function () { - if (child === null) { - start_child(); - run_count++; - } -}; -if (path.existsSync('/app/error.log')) fs.unlinkSync('/app/error.log'); -error_log_fd = fs.openSync('/app/error.log', 'w', '0777'); -child_watcher_timer = setInterval(child_watcher, 750); + + process.on('SIGTERM', function () { + log_line.call('chroot_runner', 'SIGTERM recieved, sending SIGTERM to children.'); + if (child !== null) { + log_line.call('chroot_runner', 'Child PID: ' + child.pid.toString()); + process.kill(child.pid, 'SIGTERM'); + process.exit(); + } else { + process.exit(); + } + }); + + var start_child = function () { + child = spawn('/usr/bin/node', args, { env: env }); + child.stdout.on('data', log_line.bind('stdout')); + child.stderr.on('data', log_line.bind('stderr')); + child.on('exit', function (code) { + if (code > 0 && run_count > run_max) { + log_line.call('Watcher', 'Error: Restarted too many times, bailing.', LOG_STDERR); + clearInterval(child_watcher_timer); + pre_shutdown(); + process.exit(3); + } else if (code > 0) { + log_line.call('Watcher', 'Process died with exit code ' + code + '. Restarting...', LOG_STDERR); + child = null; + } else { + log_line.call('Watcher', 'Process exited cleanly. Dieing.', LOG_STDERR); + clearInterval(child_watcher_timer); + pre_shutdown(); + process.exit(0); + } + }); + }; + var child_watcher = function () { + if (child === null) { + start_child(); + run_count++; + } + }; + child_watcher_timer = setInterval(child_watcher, 750); +}); \ No newline at end of file