npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

daemonize3

v1.0.2

Published

A lightweight module to daemonize nodeJS applications easily

Readme

daemonize3

daemonize3 is a NodeJS module, which lets one turn a normal node application (app) into a daemon easily, so that it detaches from the controlling terminal and continues to in the background. Furthermore if needed, one may even run it in the foreground by just setting the corresponding option, which makes troubleshooting much easier (e.g. if the app doesn't start properly).

The 'Runner' does this by spawning a wrapper, which in turn just runs the given app (more or less like require("app.js")) and redirects per default its output to /dev/null, however, it can be configured to redirect its stdout and/or stderr to a stream of your choice by just setting the appropriate option(s). Also the wrapper feeds information about the clients state back to its 'Runner', so that it knows, that the client is actually running (or not) and can exit with the exit code obtained via wrapper's feedback and thus e.g. follows the simple fork-exec-model prefered by the Solaris service management facilities (SMF).

Dueto the async nature of most apps the wrapper can't really tell from its perspective, whether the app is finally runnning or still in its "starting/configure" phase. The app may help it by just emmitting a 'daemon_running' event (optional with a short info message attached), e.g. when the app's http listener actually started listening for http requests. If it doesn't do it, a timer fires this event after the configured period of time. On this event the wrapper sends the corresponding notification incl. the process.exitCode currently set to its runner and closes all additional communication channels, removes related listeners.

To customize the wrappers start as needed, the following options are supported:

| option | type | decription | | :--------- | :-----------: | :--------- | | main | string | The name of the JS file, which contains the app to run as daemon. Needs to be in the ${CWD} or resolvable via node's module lookup algorithm. | | name | string | The short name of the application, which can be used as title as well. Default: daemon | | pidfile | string | Pidfile to use. Only required, if you wanna use the runner for stopping it as well. Default: autogenerated if started on tty, none otherwise. | | umask | number | umask to set for the daemon. Default: inherit | | timeout | number | timeout to use to wait for a feedback of the app after it has been started (seconds). Default: 30 | | foreground | boolean | Don't start the app as daemon but in foreground. Offen useful for troubleshooting, to see why the daemon does not start properly. Default: false | | execArgv | array | Same as for ChildProcess.spawn(...), i.e. options to the node binary itself. Default: inherit | | args | array | Same as for ChildProcess.spawn(...), i.e. options and operands for the main app itself. Default: inherit | | cwd | string | Same as for ChildProcess.spawn(...). Default: inherit | | env | array | Same as for ChildProcess.spawn(...). Default: inherit | | stdout | string,stream | The stdin parameter for the stdio vector of the options object for ChildProcess.spawn(...). Should be 'ignore' aka /dev/null or a stream, otherwise the runner may notwork as expected. Default: 'ignore' | | stderr | string,stream | The stdout parameter for the stdio vector of the options object for ChildProcess.spawn(...). Should be 'ignore' aka /dev/null or a stream, otherwise the runner may notwork as expected. Default: 'ignore' | | uid | number | The uid the daemon should use. Note that this requires add. privileges - see Process.setuid(). Default: inherit | | gid | number | The gid the daemon should use. Note that this requires add. privileges - see Process.setgid(). Default: inherit | | detached | boolean | If true, make the daemon a process leader w/o a controlling terminal, i.e. call setsid(2). Otherwise honored on Windows only: makes sure, that the daemon gets killed with its parent aka runner. Ignored. Default: !foreground |

Example

application.js (the main application as is):

var port = process.argv[2] || 3000;
var server = require('http').createServer((req, res) => {
	res.writeHead(200, {'Content-Type': 'text/plain'});
	res.end('okay');
});
server.on('error', function(e) {
	if (e.code == 'EADDRINUSE') {
		console.error('Unable to listen on port %d (port already in use)',port);
		process.exitCode = 95;
	} else if (e.code == 'EACCES') {
		console.error('Unable to listen on port %d (permission denied)',port);
		process.exitCode = 100;
	} else {
		console.error('An unexpected error occured (%s)', e.code);
		process.exitCode = 94;
	}
});
server.on('listening', function() {
	console.log('Listening on port ' + port);
	process.emit('daemon_running', 'Listening on port ' + port);
});
server.on('close', function() {
	console.log('Stopping service on port %d ...', port);
});
server.listen(port);

run.js (the little, trivial helper to run the daemon):

#!/usr/bin/env node

var arg = process.argv[2];
 
runner = new require('daemonize3').Runner({
	name: 'My http service',
	main: 'application.js',
	args: [ (!!arg) && arg.search(/^[0-9]+$/) != -1 ? arg : 52768 ],
	foreground: (!!arg) && typeof arg !== 'number'
});

if (arg == 'stop') {
	runner.stop();
} else {
	runner.startDaemon();
}

So you may try out the following commands to explore the example further:

  • test start/stop

    • run.js
    • run.js stop
  • force an error on the 2nd invocation

    • run.js
    • run.js
    • run.js stop
  • force a permission denied error

    • run.js 80
  • run the app not as a daemon

    • run.js fg
  • last but not least, comment out the process.emit(....) line in application.js and watch out, what happens now (the timeout is used to draw the assumption, that the app is running, if no error occures).