CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-daemon

Unix daemon creation library for Node.js processes

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

Daemon

Daemon is a Node.js library that provides simple and reliable Unix daemon creation capabilities. The library allows you to transform a running Node.js process into a daemon process by forking and detaching from the parent process, or spawn any script as a daemon with configurable options.

Package Information

  • Package Name: daemon
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install daemon

Core Imports

const daemon = require("daemon");

For ES modules:

import daemon from "daemon";

Basic Usage

const daemon = require("daemon");

// Turn current process into a daemon
console.log("Before daemon:", process.pid);
daemon();
console.log("After daemon:", process.pid); // Different PID in daemon process

// Spawn another script as a daemon
const child = daemon.daemon("./worker.js", ["arg1", "arg2"], {
  stdout: process.stdout,
  stderr: process.stderr
});
console.log("Daemon child PID:", child.pid);

Capabilities

Self-Daemonization

Transform the current Node.js process into a daemon by re-spawning as a detached background process.

/**
 * Transform current process into daemon by re-spawning as detached process
 * @param {Object} [opt] - Configuration options
 * @param {Object} [opt.env] - Environment variables for daemon process (default: process.env)  
 * @param {string|Stream} [opt.stdout] - File descriptor or stream for stdout (default: 'ignore')
 * @param {string|Stream} [opt.stderr] - File descriptor or stream for stderr (default: 'ignore')
 * @param {string} [opt.cwd] - Current working directory for daemon (default: process.cwd())
 * @returns {number|void} - Process PID if already daemon, exits parent process otherwise
 */
function daemon(opt)

Usage Example:

const daemon = require("daemon");

// Basic daemonization
daemon();

// Daemonization with output redirection
daemon({
  stdout: require("fs").openSync("/var/log/myapp.log", "a"),
  stderr: require("fs").openSync("/var/log/myapp-error.log", "a")
});

// Daemonization with custom environment
daemon({
  env: { ...process.env, NODE_ENV: "production" },
  cwd: "/var/lib/myapp"
});

Script Daemonization

Spawn any Node.js script as a daemon process with full configuration control.

/**
 * Spawn a script as daemon process with configurable options
 * @param {string} script - Path to the script to run as daemon
 * @param {Array} args - Arguments to pass to the script
 * @param {Object} [opt] - Configuration options
 * @param {string|Stream} [opt.stdout] - File descriptor or stream for stdout (default: 'ignore')
 * @param {string|Stream} [opt.stderr] - File descriptor or stream for stderr (default: 'ignore')
 * @param {Object} [opt.env] - Environment variables for daemon process (default: process.env)
 * @param {string} [opt.cwd] - Current working directory for daemon (default: process.cwd())
 * @returns {ChildProcess} - Node.js ChildProcess object representing the daemon
 */
daemon.daemon = function(script, args, opt)

Usage Examples:

const daemon = require("daemon");
const fs = require("fs");

// Basic script daemonization
const child = daemon.daemon("./worker.js", ["--port", "3000"]);
console.log("Daemon started with PID:", child.pid);

// Script daemonization with output capture
const child2 = daemon.daemon("./server.js", [], {
  stdout: fs.openSync("/var/log/server.log", "a"),
  stderr: fs.openSync("/var/log/server-error.log", "a"),
  env: { ...process.env, PORT: "8080" },
  cwd: "/opt/myapp"
});

// The child process is detached and will continue running
// even after the parent process exits

Cluster Integration Example:

const daemon = require("daemon");
const cluster = require("cluster");
const numCPUs = require("os").cpus().length;

if (cluster.isMaster) {
  // Set up cluster workers
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
  
  cluster.on('exit', (worker) => {
    console.log(`Worker ${worker.process.pid} died`);
    cluster.fork(); // Restart worker
  });
  
  // Daemonize after cluster setup
  return daemon();
}

// Worker process code
const http = require("http");
http.createServer((req, res) => {
  res.writeHead(200);
  res.end(`Process: ${process.pid}`);
}).listen(8000);

Types

/**
 * Configuration options for daemon processes
 */
interface DaemonOptions {
  /** File descriptor or stream for stdout output (default: 'ignore') */
  stdout?: string | Stream;
  /** File descriptor or stream for stderr output (default: 'ignore') */  
  stderr?: string | Stream;
  /** Environment variables for daemon process (default: process.env) */
  env?: Object;
  /** Current working directory for daemon (default: process.cwd()) */
  cwd?: string;
}

/**
 * Node.js ChildProcess object returned by daemon.daemon()
 * For complete interface, see Node.js child_process documentation
 */
interface ChildProcess {
  /** Process ID of the daemon child */
  pid: number;
  /** Disconnect from the child process IPC channel */
  unref(): void;
  /** Event listeners for process lifecycle events */
  on(event: 'error' | 'exit' | 'close', callback: Function): ChildProcess;
  /** Kill the child process with optional signal */
  kill(signal?: string): boolean;
}

Implementation Notes

Process Forking Behavior

  • Self-daemonization: The daemon() function re-spawns the current script as a new process. The original process exits after spawning the daemon child.
  • Double execution: Code before daemon() runs twice - once in the original process and once in the daemon child.
  • Process identification: Daemon processes have the __daemon environment variable set to true.

Process Management

  • Detached processes: All daemon processes are spawned with detached: true, making them independent of the parent.
  • Process cleanup: The parent process calls child.unref() to allow it to exit without waiting for the child.
  • Signal handling: Daemon processes must handle their own signals and cleanup.

Output Handling

  • Default behavior: By default, daemon processes ignore stdin, stdout, and stderr ('ignore' option).
  • Output redirection: Use file descriptors or streams to capture daemon output to files.
  • Log rotation: Consider implementing log rotation for long-running daemons with file output.

Error Handling

The daemon library relies on Node.js's child_process.spawn() for process creation. Common errors include:

  • ENOENT: Script file not found or not executable
  • EACCES: Permission denied accessing script or working directory
  • EMFILE: Too many open files (system limit reached)

Error handling should be implemented around the child_process events:

const child = daemon.daemon("./worker.js", []);

child.on('error', (err) => {
  console.error('Failed to start daemon:', err);
});

child.on('exit', (code, signal) => {
  console.log('Daemon exited with code:', code, 'signal:', signal);
});

Install with Tessl CLI

npx tessl i tessl/npm-daemon
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/daemon@1.1.x
Publish Source
CLI
Badge
tessl/npm-daemon badge