0

I have a node.js application in development, and as I have been testing I found that I accidentally ran two instances of the same app, which has led to some adverse consequence.

How to prevent this from happening? Perhaps there is a way to check if my app is already running, and if so throw an error and shut down?..

Much appreciate your help!

Anonymous
  • 4,692
  • 8
  • 61
  • 91
  • it should throw you an error if you are using the same port twice. listen EADDRINUSE. Which port are you running on? – andrewgi Dec 22 '17 at 16:54
  • well, I use python as a server where node.js is a client – Anonymous Dec 22 '17 at 16:56
  • https://stackoverflow.com/questions/171213/how-to-block-running-two-instances-of-the-same-program#171220, this is a generic solution. – Malice Dec 22 '17 at 17:43
  • Does this answer your question? [Ensuring that only a single instance of a nodejs application is running](https://stackoverflow.com/questions/33460338/ensuring-that-only-a-single-instance-of-a-nodejs-application-is-running) – Jason C Jul 20 '22 at 16:25

1 Answers1

1

Here's one simple cross platform scheme that just creates a local server on a known port and then any future instances will try to create the same server and fail because another instance is already running.

One advantage to using a server like this is that the OS will automatically close and cleanup the server if the process dies for any reason so you don't ever get a "stuck" resource like can happen when using some other techniques (like lock files).

const http = require('http');

// create Sentinel server
let server = http.createServer(function(req, res) {
    res.send("ok");
});
// make sure this server doesn't keep the process running
server.unref();

server.on('error', function(e) {
    if (e.code === "EADDRINUSE") {
        console.log("Sentinel server already running - can't run more than one instance");
        process.exit(1);
    } else {
        console.log(e);
    }
});

server.listen(8399, function() {
   console.log("Sentinel server running")   
});

Other schemes that can be used:

  1. Search list of running processes
  2. Use a lock file
  3. Use add-ons like find-process

You can also use a named pipe instead of a port like this (code below works on Windows) or a domain socket on *nix:

const http = require('http');
const path = require('path');

// create Sentinel server
let server = http.createServer(function(req, res) {
    res.send("ok");
});
// make sure this server doesn't keep the process running
server.unref();

server.on('error', function(e) {
    if (e.code === "EADDRINUSE") {
        console.log("Sentinel server already running - can't run more than one instance");
        process.exit(1);
    } else {
        console.log(e);
    }
});

server.listen(path.join('\\\\?\\pipe', 'myUniqueServerPipeName'), function() {
   console.log("Sentinel server running")   
});
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Why do you need TCP here? What if that port is taken by some other app? Node.js supports local domain sockets and named pipes (on Windows). Thus you can use https://nodejs.org/api/net.html#net_server_listen_path_backlog_callback – c-smile Dec 22 '17 at 18:08
  • @c-smile - You don't have to use TCP - it's just the most interoperable. – jfriend00 Dec 22 '17 at 18:09
  • How about if node shut down forcefully, could it possibly hang the socket so that it would appear to be in use? A lock file seems like a good idea though. – Anonymous Dec 22 '17 at 18:19
  • @Anonymous - What makes a socket better than a lock file is that the OS will automatically clean up the socket if/when the process dies. That is not necessarily true with lock files. They often get stuck and have to be manually removed. That's why I prefer the socket option. It's just one socket resource, very lightweight. – jfriend00 Dec 22 '17 at 18:23
  • @jfriend00 There is another problem with use of TCP for that purposes: at least on Windows with active firewall ("on" by default) you will get warning message box window asking for access to network. – c-smile Dec 22 '17 at 18:35
  • @c-smile - Yeah, that is true. I added a named pipe example that works on Windows. – jfriend00 Dec 22 '17 at 18:53