Node.js如何通过进程名称检查进程是否正在运行?

35
我在Linux上运行Node.js,从Node.js如何通过进程名称检查进程是否正在运行? 如果最坏的情况下需要使用child_process,但想知道是否有更好的方法?
谢谢!
7个回答

23
你可以使用ps-node软件包。 https://www.npmjs.com/package/ps-node
var ps = require('ps-node');

// A simple pid lookup 
ps.lookup({
    command: 'node',
    psargs: 'ux'
    }, function(err, resultList ) {
    if (err) {
        throw new Error( err );
    }

    resultList.forEach(function( process ){
        if( process ){
            console.log( 'PID: %s, COMMAND: %s, ARGUMENTS: %s', process.pid, process.command, process.arguments );
        }
    });
});

我相信你将会看到这个例子。查看一下网站,它们还有很多其他用途。试一试吧。

如果你不局限于使用nodejs,你也可以在Linux命令行中执行ps -ef | grep "YOUR_PROCESS_NAME_e.g._nodejs"来检查正在运行的进程。


这在Windows上如何运作?我认为它会在Windows上出现错误。 - Shyam
@Shyam 如在 ps-node 主页上所宣传的那样。它“应该”可以在 Windows 上运行。如果不能,那么也许值得在 GitHub 上提出问题。 - Samuel Toh
注意:此模块需要安装其他软件。这可能无法在未安装正确工具的系统或容器中运行。 - Rahly
目前它完全不工作,至少在Linux上。版本:0.1.6 https://github.com/neekey/ps/issues/84 - Onkeltem

21

这是由d_scalzi所回答的代码的一点改进。它使用的是带回调函数的函数,而不是承诺,只有一个变量查询,并且使用开关而不是if/else。

const exec = require('child_process').exec;

const isRunning = (query, cb) => {
    let platform = process.platform;
    let cmd = '';
    switch (platform) {
        case 'win32' : cmd = `tasklist`; break;
        case 'darwin' : cmd = `ps -ax | grep ${query}`; break;
        case 'linux' : cmd = `ps -A`; break;
        default: break;
    }
    exec(cmd, (err, stdout, stderr) => {
        cb(stdout.toLowerCase().indexOf(query.toLowerCase()) > -1);
    });
}

isRunning('chrome.exe', (status) => {
    console.log(status); // true|false
})

这个在所有平台上都像魔法一样工作。谢谢! - Or Assayag
3
被踩了。因为在 Mac 上会有一个名为 'px -ax | grep {query}‘ 的进程,所以此函数将始终返回 true。 - MMhunter
在Linux平台上,我如何检查名为chrome.exe的软件是否正在运行中,以及它的isRunning函数? - Mijanur Rahman

18
以下代码应该有效。将生成基于操作系统的进程列表,并解析所需程序的输出结果。该函数接受三个参数,每个参数只是相应操作系统上预期的进程名称。
根据我的经验,ps-node需要太多的内存和时间来搜索进程。如果您计划经常检查进程,则此解决方案更好。

const exec = require('child_process').exec

function isRunning(win, mac, linux){
    return new Promise(function(resolve, reject){
        const plat = process.platform
        const cmd = plat == 'win32' ? 'tasklist' : (plat == 'darwin' ? 'ps -ax | grep ' + mac : (plat == 'linux' ? 'ps -A' : ''))
        const proc = plat == 'win32' ? win : (plat == 'darwin' ? mac : (plat == 'linux' ? linux : ''))
        if(cmd === '' || proc === ''){
            resolve(false)
        }
        exec(cmd, function(err, stdout, stderr) {
            resolve(stdout.toLowerCase().indexOf(proc.toLowerCase()) > -1)
        })
    })
}

isRunning('myprocess.exe', 'myprocess', 'myprocess').then((v) => console.log(v))


11

以下是 TypeScript 和 promises 的另一个答案版本:

export async function isProcessRunning(processName: string): Promise<boolean> {
  const cmd = (() => {
    switch (process.platform) {
      case 'win32': return `tasklist`
      case 'darwin': return `ps -ax | grep ${processName}`
      case 'linux': return `ps -A`
      default: return false
    }
  })()

  if( ! cmd ) {
    return false;
  }

  return new Promise((resolve, reject) => {
    require('child_process').exec(cmd, (err: Error | null, stdout: string, stderr: string) => {
      if (err) reject(err)

      resolve(stdout.toLowerCase().indexOf(processName.toLowerCase()) > -1)
    })
  })
}

const running: boolean = await isProcessRunning('myProcess')

4

针对相关主题,以下是一些最佳软件包:

通过 pid、名称模式和不同手段搜索软件包:

仅通过pid检查

使用 find-process 的示例

按名称搜索

const processesList = await findProcess(
    'name',
    /.*?\/kidoAgent\/Broker\/process.js.*/ // regex pattern
);

console.log({ processesList });

if (processesList.length === 0) {
     /**
      * No process
      * (create it)
      */
     // ......
}

它返回一个以数组形式找到的进程列表!

当运行时,对于 console.log({ processesList });,它显示:

{
  processesList: [
    {
      pid: 7415,
      ppid: 2451,
      uid: 1000,
      gid: 1000,
      name: 'node',
      bin: '/opt/node-v12.4.0-linux-x64/bin/node',
      cmd: '/opt/node-v12.4.0-linux-x64/bin/node ' +
        '/home/coderhero/Dev/.../build/.../kidoAgent/Broker/process.js'
    }
  ]
}

检查模块的所有选项和方法!


1
is-running 是这里最好的模块,因为它不需要安装外部程序就可以工作。 - Rahly
如果您只需要通过进程ID进行检查 - Mohamed Allal

2

对@musatin方案的另一个改进是使用自调用的switch语句,而不是重新分配let;

/**
 * 
 * @param {string} processName The executable name to check
 * @param {function} cb The callback function
 * @returns {boolean} True: Process running, else false
 */
  isProcessRunning(processName, cb){
      const cmd = (()=>{
          switch (process.platform) {
              case 'win32' : return `tasklist`;
              case 'darwin' : return `ps -ax | grep ${processName}`;
              case 'linux' : return `ps -A`;
              default: return false;
          }
      })();
      require('child_process').exec(cmd, (err, stdout, stderr) => {
          cb(stdout.toLowerCase().indexOf(processName.toLowerCase()) > -1);
      });
  }

cmd 将被分配为 switch 语句的结果,这将使代码更易于阅读(特别是涉及更复杂的代码时,自调用 switch 语句意味着您只创建所需的变量,而不需要在脑海中跟踪它们可能的值)。


0
这是一个改进版的answer,由musatin提供,以便代码也可以在macOS和Linux上运行。更改是更新“check”命令以正确检测运行中的进程。
/**
 * Find running process(es) by name
 * @param {string} query Name of the process to find (e.g., "Notepad.exe")
 * @param {function} cb Callback function
 * @returns {boolean} True if at least one such process is running, false otherwise
 */
const isProcessRunning = (query, cb) => {
  let platform = process.platform
  let cmd = ''
  switch (platform) {
    case 'win32':
      cmd = `tasklist`
      break
    case 'darwin':
      cmd = `pgrep -l ${query} | awk '{ print $2 }'`
      break
    case 'linux':
      cmd = `pgrep -l ${query} | awk '{ print $2 }'`
      break
    default:
      break
  }
  require('child_process').exec(cmd, (err, stdout) => {
    cb(stdout.toLowerCase().indexOf(query.toLowerCase()) > -1)
  })
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接