diff --git a/bin/foreverd b/bin/foreverd deleted file mode 100755 index e7015ba9..00000000 --- a/bin/foreverd +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env node - -require('../lib/forever/service/cli').startCLI(); - diff --git a/lib/forever.js b/lib/forever.js index 01e7a093..6a3a7964 100644 --- a/lib/forever.js +++ b/lib/forever.js @@ -60,13 +60,6 @@ forever.cli = require('./forever/cli'); // require('pkginfo')(module, 'version'); -// -// Expose the global forever service -// -forever.__defineGetter__('service', function () { - return require('./forever/service'); -}); - // // ### function getSockets (sockPath, callback) // #### @sockPath {string} Path in which to look for UNIX domain sockets @@ -196,7 +189,7 @@ function stopOrRestart(action, event, format, target) { if (err) { emitter.emit('error', err); } - + emitter.emit(event, forever.format(format, procs)); }); } @@ -418,16 +411,16 @@ forever.startDaemon = function (script, options) { }); monitor.send(JSON.stringify(options)); - + // close the ipc communication channel with the monitor - // otherwise the corresponding events listeners will prevent + // otherwise the corresponding events listeners will prevent // the exit of the current process (observed with node 0.11.9) monitor.disconnect(); - + // make sure the monitor is unref() and does not prevent the // exit of the current process monitor.unref(); - + return monitor; }; @@ -689,7 +682,7 @@ forever.format = function (format, procs) { columns = forever.config.get('columns'), rows = [[' '].concat(columns)], formatted; - + function mapColumns(prefix, mapFn) { return [prefix].concat(columns.map(mapFn)); } diff --git a/lib/forever/service/adapters/adapter.js b/lib/forever/service/adapters/adapter.js deleted file mode 100644 index bf234114..00000000 --- a/lib/forever/service/adapters/adapter.js +++ /dev/null @@ -1,96 +0,0 @@ -/* - * adapter.js: Abstract base class used by foreverd service adapters - * - * (C) 2010 Nodejitsu Inc. - * MIT LICENCE - * - */ - -var Adapter = module.exports = function Adapter(service) { - this.service = service; -}; - -// -// This should install assets to appropriate places for initialization, -// configuration, and storage -// -// The script will be used on startup to load Service -// -// Service should listen on something that the management events -// can respond to in full duplex -// -// The installed adapter should send the following events in nssocket protocol -// to the Service and invoke methods as appropriate -// -Adapter.prototype.install = function install() { - throw new Error('not implemented'); -}; - -// -// This should do a rollback of install completely except for logs -// -Adapter.prototype.uninstall = function uninstall() { - throw new Error('not implemented'); -}; - -// -// This should call back with an array of [{file:...,options:...},] to pass to Monitors -// this will be invoked when foreverd is created (not started) -// -Adapter.prototype.load = function load(callback) { - throw new Error('not implemented'); -}; - -// -// This should tell the OS to start the service -// this will not start any applications -// make sure the adapter is installed and sending events to foreverd's listener -// -Adapter.prototype.start = function start(monitors) { - throw new Error('not implemented'); -}; - -// -// This should tell the OS to start the service -// this will not stop any applications -// make sure the adapter is installed and sending events to foreverd's listener -// -Adapter.prototype.stop = function stop(monitors) { - throw new Error('not implemented'); -}; - -// -// This should tell the OS to reply with info about applications in the service -// this will not change any applications -// make sure the adapter is installed and sending events to foreverd's listener -// -Adapter.prototype.status = function status(monitors) { - throw new Error('not implemented'); -}; - -// -// This should tell the OS to restart the service -// this will not restart any applications -// make sure the adapter is installed and sending events to foreverd's listener -// -Adapter.prototype.restart = function restart(monitors) { - throw new Error('not implemented'); -}; - -// -// This should tell the OS to pause the service -// this will prevent any addition or removal of applications -// make sure the adapter is installed and sending events to foreverd's listener -// -Adapter.prototype.pause = function pause(monitors) { - throw new Error('not implemented'); -}; - -// -// This should tell the OS to resume the service -// this will enable any addition or removal of applications -// make sure the adapter is installed and sending events to foreverd's listener -// -Adapter.prototype.resume = function resume(monitors) { - throw new Error('not implemented'); -}; \ No newline at end of file diff --git a/lib/forever/service/adapters/initd/index.js b/lib/forever/service/adapters/initd/index.js deleted file mode 100644 index 1162d378..00000000 --- a/lib/forever/service/adapters/initd/index.js +++ /dev/null @@ -1,9 +0,0 @@ -/* - * index.js: Top-level include for the init.d foreverd service adapter. - * - * (C) 2010 Nodejitsu Inc. - * MIT LICENCE - * - */ - -module.exports = require('../systemv'); \ No newline at end of file diff --git a/lib/forever/service/adapters/systemv/foreverd b/lib/forever/service/adapters/systemv/foreverd deleted file mode 100644 index bdd9a5c9..00000000 --- a/lib/forever/service/adapters/systemv/foreverd +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash -# -# initd-example Node init.d -# -# chkconfig: 345 80 20 -# description: Node init.d example -# processname: node -# pidfile: /var/run/initd-example.pid -# logfile: /var/log/initd-example.log -# - -# Source function library. -. /lib/lsb/init-functions -PATH=$PATH:/usr/local/bin - -NAME=foreverd -pidfile=/var/run/$NAME.pid -logfile=/var/log/$NAME.log -forever_dir=/var/local/forever # Forever root directory. - -node=node -foreverd=`which foreverd` -awk=awk -sed=sed - -start() { - echo "Starting $NAME: " - - if [ "$id" = "" ]; then - # Launch the application - $foreverd -p $forever_dir run - else - echo "Instance already running" - fi - RETVAL=$? -} - -restart() { - echo -n "Restarting $NAME: " - if [ "$id" != "" ]; then - $foreverd -p $forever_dir restart - RETVAL=$? - else - start - fi -} - -stop() { - echo -n "Shutting down $NAME: " - if [ "$id" != "" ]; then - $foreverd -p $forever_dir stop - else - echo "Instance is not running"; - fi - RETVAL=$? -} - -getForeverId() { - local pid=$(pidofproc -p $pidfile) - $foreverd list -p $forever_dir | $sed -e 's/\x1b\[[0-9; ]*m//g' | $awk "\$4 == \"$pid]\" { gsub(/[\[\]]/, \"\", \$1); print \$1; }" -} -id=$(getForeverId) - -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - $foreverd -p $forever_dir list - ;; - restart) - restart - ;; - *) - echo "Usage: {start|stop|status|restart}" - exit 1 - ;; -esac -exit $RETVAL diff --git a/lib/forever/service/adapters/systemv/index.js b/lib/forever/service/adapters/systemv/index.js deleted file mode 100644 index 2877b772..00000000 --- a/lib/forever/service/adapters/systemv/index.js +++ /dev/null @@ -1,199 +0,0 @@ -/* - * index.js: Top-level include for the systemv foreverd service adapter - * - * (C) 2010 Nodejitsu Inc. - * MIT LICENCE - * - */ - -var fs = require('fs'), - util = require('util'), - path = require('path'), - spawn = require('child_process').spawn, - nssocket = require('nssocket'), - forever = require('../../../../forever'), - Adapter = require('../adapter'); - -// -// Classic init.d script adapter -// Sometimes called inittab, but its origin is called systemv -// -var SystemVAdapter = module.exports = function SystemVAdapter(service) { - Adapter.call(this, service); - this.daemonized = false; -}; - -util.inherits(SystemVAdapter, Adapter); - -SystemVAdapter.prototype.install = function install(callback) { - // - // Copy the init.d script to the right location - // TODO Distribution fixes? - // - forever.config.set('root', path.join('/var', 'local', 'foreverd')); - var initdPath = path.join('/etc', 'init.d', 'foreverd'), - script, - target; - - try { - fs.mkdirSync(forever.config.get('root'), '0777'); - fs.mkdirSync(path.join(forever.config.get('root'), 'services'), '0777'); - } - catch (e) { - if (e.code !== 'EEXIST') { - return callback && callback(e); - } - } - - try { - script = fs.createReadStream(path.join(__dirname, 'foreverd')); - target = fs.createWriteStream(initdPath, { flags: 'w', mode: '0777' }); - - script.pipe(target); - script.on('end', function () { - var directories = fs.readdirSync('/etc'); - directories.forEach(function (directory) { - var match = directory.match(/^rc(\d+)\.d$/), - killOrStart; - - if (match) { - killOrStart = { 0: true, 1: true, 6: true }[match[1]] ? 'K' : 'S'; - - try { - fs.symlinkSync(initdPath, path.join('/etc', directory, killOrStart + '20foreverd')); - } - catch (e) { - if (e.code !== 'EEXIST') { - return callback && callback(e); - } - } - } - }); - - return callback && callback(); - }); - } - catch (e) { - if (e.code !== 'EEXIST') { - return callback && callback(e); - } - } -}; - -// -// -// -SystemVAdapter.prototype.load = function load(callback) { - forever.config.set('root', path.join('/var', 'local', 'foreverd')); - var serviceFiles = fs.readdirSync(path.join(forever.config.get('root'), 'services')), - services = []; - - if (serviceFiles.length !== 0) { - serviceFiles.forEach(function loadServiceFiles(serviceFile, index) { - var serviceFilePath = path.join(forever.config.get('root'), 'services', serviceFile), - service = JSON.parse(fs.readFileSync(serviceFilePath)), - file = service.file, - options = service.options; - - options.minUptime = 200; - services.push({ - file: service.file, - options: service.options - }); - }); - } - - callback(services); -}; - -SystemVAdapter.prototype.start = function start(callback) { - spawn('/etc/init.d/foreverd', ['start']); - return callback && callback(); -}; - -SystemVAdapter.prototype.run = function run(callback) { - if (this.daemonized) { - return callback(); - } - - var self = this, - pidFilePath = path.join('/var', 'run', 'foreverd.pid'), - logFilePath = path.join('/var', 'log', 'foreverd'); - - process.on('exit', function removePIDFile() { - try { - fs.unlinkSync(pidFilePath); - } - catch (err) { - // we are exiting anyway. this may have some noexist error already - } - }); - - fs.open(logFilePath, 'w+', function serviceLogOpened(err, logFile) { - if (err) { - throw err; - } - - self.service.startServer(function () { - try { - // - // TODO: Create a pseudo-daemon to replace this. - // - // daemon.start(logFile); - // daemon.lock(pidFilePath); - self.daemonized = true; - return callback && callback(); - } - catch (err) { - console.error(err); - return callback && callback(err); - } - }); - }); -}; - -SystemVAdapter.prototype.add = function add(file, options, callback) { - forever.config.set('root', path.join('/var', 'local', 'foreverd')); - // - // Add descriptor to our service list - // this is just a json file in $root/services/*.json - // - var filePath, service = { - file: file, - options: options || {} - }; - - options.appendLog = true; - filePath = path.join(forever.config.get('root'), 'services', options.uid + '.json'); - - fs.writeFile(filePath, JSON.stringify(service), function (err) { - return callback && callback(err); - }); -}; - -SystemVAdapter.prototype.list = function list(callback) { - forever.config.set('root', path.join('/var', 'local', 'foreverd')); - - var sockPath = path.join(forever.config.get('root'), 'foreverd.sock'), - client; - - client = dnode.connect(sockPath, function onConnect(remote, client) { - if (callback) { - callback(false, remote.applications); - } - - client.end(); - }); - - client.on('error', function onError(err) { - if (err.code === 'ECONNREFUSED') { - try { - fs.unlinkSync(fullPath); - } - catch (ex) { } - return callback && callback(false, []); - } - - return callback && callback(err); - }); -}; \ No newline at end of file diff --git a/lib/forever/service/cli.js b/lib/forever/service/cli.js deleted file mode 100644 index 674e15b4..00000000 --- a/lib/forever/service/cli.js +++ /dev/null @@ -1,102 +0,0 @@ -/* - * cli.js: Handlers for the foreverd CLI commands. - * - * (C) 2010 Nodejitsu Inc. - * MIT LICENCE - * - */ - -var utile = require('utile'), - flatiron = require('flatiron'), - optimist = require('optimist'), - forever = require('../../forever'), - Service = require('./service'), - argv; - -var cli = exports; - -var app = flatiron.app; - -app.use(flatiron.plugins.cli, { - usage: forever.cli.usage -}); - -app.config.argv().env(); - -var service = new Service({ - adapter: optimist.argv.adapter -}); - -app.cmd('install', cli.install = function () { - service.install(function onInstall(err) { - if (err) { - forever.log.error(err); - } - else { - forever.log.info('foreverd installed'); - } - }); -}); - -//TODO -app.cmd('run', cli.run = function () { - service.load(function () { - service.run(); - }); -}); - -app.cmd('uninstall', cli.uninstall = function () { - service.uninstall(); -}); - -app.cmd(/add (.*)/, cli.add = function (file) { - service.add(file, forever.cli.getOptions(file)); -}); - -//TODO -app.cmd(/remove (.*)/, cli.remove = function (file) { - service.remove(file, forever.cli.getOptions(file)); -}); - -app.cmd('start', cli.start = function () { - service.start(); -}); - -//TODO -app.cmd('stop', cli.stop = function () { - service.stop(); -}); - -app.cmd('restart', cli.restart = function () { - service.restart(); -}); - -app.cmd('list', cli.list = function () { - service.list(function (err, applications) { - if (err) { - app.log.error('Error running command: ' + 'list'.magenta); - app.log.error(err.message); - err.stack && err.stack.split('\n').forEach(function (line) { - app.log.error(line); - }) - return; - } - - applications.forEach(function printApplication(application) { - console.log(application.monitor.uid, application.monitor.command, application.file, application.monitor.child.pid, application.monitor.logFile, application.monitor.pidFile); - }); - }); -}); - -app.cmd('pause', cli.pause = function () { - service.pause(); -}); - -app.cmd('resume', cli.resume = function () { - service.resume(); -}); - -cli.startCLI = function () { - app.start(); -}; - diff --git a/lib/forever/service/index.js b/lib/forever/service/index.js deleted file mode 100644 index 5addced3..00000000 --- a/lib/forever/service/index.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * index.js: Top-level include for the `forever.service` module. - * - * (C) 2010 Nodejitsu Inc. - * MIT LICENCE - * - */ - -var fs = require('fs'), - path = require('path'); - -var service = exports; - -service.Service = require('./service'); -service.adapters = {}; - -fs.readdirSync(path.join(__dirname, 'adapters')).forEach(function (file) { - file = file.replace(/\.js/, ''); - service.adapters.__defineGetter__(file, function () { - return require(__dirname + '/adapters/' + file); - }); -}); diff --git a/lib/forever/service/service.js b/lib/forever/service/service.js deleted file mode 100644 index 2cc878dd..00000000 --- a/lib/forever/service/service.js +++ /dev/null @@ -1,268 +0,0 @@ -/* - * service.js: Object responsible for managing the foreverd daemon. - * - * (C) 2010 Nodejitsu Inc. - * MIT LICENCE - * - */ - -var fs = require('fs'), - path = require('path'), - util = require('util'), - events = require('events'), - forever = require('../../forever'), - SystemVAdapter = require('./adapters/systemv'); - -// options -// directories {log, pid, conf, run, local} -var Service = module.exports = function Service(options) { - events.EventEmitter.call(this); - options = options || {}; - - var self = this, - AdapterType; - - this.applications = [ - //{ - //file: - //options: - //monitor: - //} - ]; - - this.servers = []; - if (typeof options.adapter === 'string') { - options.adapter = Service.adapter[options.adapter]; - } - - AdapterType = options.adapter || SystemVAdapter; - this.adapter = new AdapterType(this); -}; - -util.inherits(Service, events.EventEmitter); - -Service.prototype.startServer = function startServer(callback) { - var socket = path.join(forever.config.get('sockPath'), 'forever.sock'), - monitors = [], - self = this, - server; - - server = dnode(this); - server.on('error', function onServerError() { - // - // TODO: This is really bad. - // - }); - - server.on('ready', function onServerReady(err) { - self.listen(server); - if (callback) { - if (err) { - callback(err); - } - else { - callback(null, server, socket); - } - } - }); - - server.listen(socket); - - return this; -}; - -Service.prototype.listen = function listen(server) { - var dnodeServer = dnode(this); - - this.servers.push(dnodeServer); - dnodeServer.listen(server); - - return this; -}; - -Service.prototype.load = function load() { - var self = this; - this.adapter.load(function onLoaded(applications) { - applications.forEach(function startApplication(application, index) { - var monitor = application.monitor = new forever.Monitor(application.file, application.options); - - monitor.start(); - self.applications.push(application); - - if (index === applications.length - 1) { - self.listen(path.join(forever.config.get('root'), 'foreverd.sock')); - } - - self.emit('foreverd::loaded'); - }); - }); - return this; -}; - -// -// Function add(file, options) -// add the application to the service manager -// DOES NOT START THE APPLICATION -// call's the service manager's add method -// -Service.prototype.add = function add(file, options, callback) { - if (this.paused) { - return callback && callback(new Error('foreverd is paused')); - } - - this.adapter.add(file, options, callback); -}; - -// -// Function remove(file, options) -// remove the application from the service manager -// call's the service manager's remove method -// -Service.prototype.remove = function remove(file, options, callback) { - if (this.paused) { - return callback(new Error('foreverd is paused')); - } - - var applicationsToRemove = this.applications, - self = this, - optionStr, - fileStr; - - if (file) { - fileStr = JSON.stringify(file); - applicationsToRemove = applicationsToRemove.filter(function compareFile(application) { - return fileStr !== JSON.stringify(application.file); - }); - } - - if (options) { - optionStr = JSON.stringify(options); - applicationsToRemove = applicationsToRemove.filter(function compareOptions(application) { - return optionStr !== JSON.stringify(application.options); - }); - } - - applicationsToRemove.forEach(function removeApplication(application) { - if (application.monitor) { - application.monitor.stop(); - } - - self.applications.splice(self.applications.indexOf(application), 1); - }); - - if (callback) { - callback(); - } - - return this; -}; - -// -// Function install() -// installs all the required to run foreverd -// call's the service manager's install(options) -// -Service.prototype.install = function install(callback) { - this.adapter.install(callback); - return this; -}; - -// -// Function uninstall(options) -// uninstalls all the required to run foreverd -// call's the service manager's uninstall(options) -// -Service.prototype.uninstall = function uninstall(callback) { - this.adapter.uninstall(callback); - return this; -}; - -// -// Function start() -// calls the appropriate OS functionality to start this service -// -Service.prototype.start = function start(callback) { - this.adapter.start(callback); - return this; -}; - -// -// Function run() -// creates monitors for all the services -// -Service.prototype.run = function run(callback) { - var self = this; - this.adapter.run(function adapterStarted() { - self.applications.forEach(function startApplication(application) { - application.monitor = new forever.Monitor(application.file, application.options); - application.monitor.start(); - }); - - return callback && callback(); - }); - - return this; -}; - -// -// Function stop(monitors) -// -Service.prototype.stop = function stop(callback) { - var self = this; - this.adapter.start(function adapterStopped() { - self.applications.forEach(function stopApplication(application) { - application.monitor.stop(); - }); - - return callback && callback(); - }); - - return this; -}; - -// -// Function restart() -// -Service.prototype.restart = function restart(callback) { - var self = this; - this.adapter.start(function adapterRestarted() { - self.applications.forEach(function restartApplication(application) { - application.monitor.restart(); - }); - - return callback && callback(); - }); - - return this; -}; - -// -// Function pause() -// disables adding / removing applications -// -Service.prototype.pause = function pause(callback) { - this.paused = true; - if (callback) { - callback(); - } - - return this; -}; - -// -// Function resume() -// reenables adding / removing applications -// -Service.prototype.resume = function resume(callback) { - this.paused = false; - if (callback) { - callback(); - } - - return this; -}; - -Service.prototype.list = function list(callback) { - this.adapter.list(callback); - return this; -}; \ No newline at end of file diff --git a/test/service/simple-test.js b/test/service/simple-test.js deleted file mode 100644 index 5f58fad5..00000000 --- a/test/service/simple-test.js +++ /dev/null @@ -1,25 +0,0 @@ -/* - * service-test.js: Tests for the forever.service module - * - * (C) 2010 Nodejitsu Inc. - * MIT LICENCE - * - */ - -var assert = require('assert'), - path = require('path'), - vows = require('vows'), - forever = require('../../lib/forever'); - -vows.describe('forever/service/simple').addBatch({ - "When using forever": { - "the service module": { - "should have the correct exports": function () { - assert.isObject(forever.service); - assert.isFunction(forever.service.Service); - assert.isObject(forever.service.adapters); - assert.isFunction(forever.service.adapters.initd); - } - } - } -}).export(module);