如何检测节点进程/脚本是否已在运行?

时间:2018-01-22 20:08:26

标签: javascript node.js multithreading thread-safety mutex

有没有办法以编程方式检测node.js进程(或脚本)是否已在计算机上运行?

我想从节点脚本本身实现这一点,而不是依赖于shell脚本或其他查询操作系统上的进程的方法。我知道这在许多编程语言中是可行的,例如Java和C#(例如使用Mutex类)。我正在寻找Node.js项目的等效解决方案。

3 个答案:

答案 0 :(得分:1)

有一些特定于操作系统的方法可以查看当前计算机上运行的所有进程,以便您可以使用它(通过将外部进程作为child_process运行)来查看您的服务器是否已在运行。

但是,对于跨平台机制,您可以将一个小http服务器(我称之为探测服务器)放入您的进程中,然后查看该服务器是否响应。如果是,那么您的应用程序已在运行。如果没有,那就不是。

所以,把它放到你的应用程序中:

// pick some port not already in use locally
const probePort = 8001;
const probePath = '/probe';
const http = require('http');
const rp = require('request-promise');

// see if our probe server is already running
rp({
    uri: `http://localhost:${probePort}${probePath}`,
    resolveWithFullResponse: true
}).then(res => {
   if (res.statusCode === 200) {
      console.log(`Our server already running in another process`);
      process.exit(1);
   } else {

      throw new Error(`statusCode ${res.statusCode}`)
   }
}).catch(err => {
    // our process is not already running
    // start our own copy of the probeServer
    const server = http.createServer((req, res) => {
        if (req.url === probePath) {
            res.statusCode = 200;
            res.end("ok");
        } else {
            res.statusCode = 404;
            res.end("err");
        }
    });
    server.listen(probePort);
    // make sure this server does not keep the process running
    server.unref();

    // proceed with the rest of your process initialization here
    console.log("Our server not already running, so we can now start ours");
    setInterval(() => {
        console.log("still running");
    }, 1000);
});

注意:如果您的应用中已经有一个http服务器,那么您可以在该服务器中创建一个特殊的probePath路由,该路由以200状态响应并测试而不是创建另一个http服务器。

答案 1 :(得分:0)

如果您正在寻找监控nodejs流程,那里有很多好的库,例如 foreverjs pm2 等。但是,要回答更直接地提出问题,你可以通过在节点脚本中有效地分配你的进程(另一个有效的进程)来做到这一点:

var exited = false;
var cp = require('child_process');
var superProcess = cp.fork('./my-super-process');

superProcess.on('exit', (code, signal) => {
  exited = true;
});

setInterval(function() {
   if (exited) {
      console.log('is gone :(')
   } else {
      console.log('still running ...')
   }
}, 1000);

答案 2 :(得分:0)

如果您能以某种方式知道目标PID的进程ID(PID)(例如,您的server.js可能始终将PID名称存储在server.pid文件中),则可以使用is-running包知道它是否正在运行。

var _ = require('underscore')
var sh = require('shelljs')
var isRunning = require('is-running')

if(! _.contains(sh.ls("."), 'server.pid')){ // If PID file does not exist
    console.log("PID file does not exist.")
} else { // PID file exists
    let pid = sh.cat('server.pid').stdout
    if(!isRunning(pid)){
        console.log("server.js is not running")
    } else {
        console.log("server.js is running")
    }
}

或者如果您针对任意过程,那么这个怎么样?

if(sh.exec('ps aux', {silent: true}).grep('npm').stdout != "\n"){
    console.log("some npm process is running")
}