如何在超时情况下运行 npm 脚本(如果花费的时间超过一定时间,则终止进程)?

问题描述 投票:0回答:2

我有一个 Angular 的 npm 构建脚本:

"build": "ng build my-project-name"

此脚本经常挂起(在我们的构建管道内和本地)。我想设置一个时间限制,之后进程将被终止并重新启动。我尝试使用带有

spawn
spawnSync
的节点脚本来运行
npm.cmd run build
并显式使用超时或在返回的句柄上调用
.kill()
,看起来进程已被终止,但随后它的输出继续击中终端并且必须手动终止终端。

是否有任何通用方法来运行 NPM 脚本,该脚本将在给定时间后被终止?

node.js npm build timeout kill
2个回答
3
投票

这是我最终使用的。

制作一个js脚本

timeout.js
,如下所示:

setTimeout(() => process.exit(1), 20000);

安装节点包

concurrently

像这样制作 NPM 脚本:

{
"build:with-timeout": "concurrently -k \"node timeout.js\" \"npm run build\""
}

使用

-k
标志
concurrently
将在其中一个进程终止时向所有其他进程发送
SIGTERM
信号。在我的具体情况下,我选择通过构建进程监控 CPU 使用情况,如果其活动在 2 分钟内降至接近 0,则终止。


0
投票

如果脚本生成像笑话这样的子进程,您可以使用以下方法来监视进程并使用 grep 杀死进程。

process-gaurd.js

import args from "command-line-args";
import { execa } from "execa";
import chalk from "chalk";

const optionDefinitions = [
  { name: "timeout", alias: "t", type: Number },
  { name: "process", alias: "p", type: String },
  { name: "killgrep", alias: "k", type: String }
];

const options = args(optionDefinitions);
const timeout = options.timeout;
const process = options.process;
const killGrep = options.killgrep;
const killCommand = killGrep
  ? `ps aux | grep -E '${killGrep}' | awk '{print $2}' | xargs kill -9`
  : "";

const forceKillProcesses = killCommand !== "";

console.log(
  chalk.yellow(
    `setting ${timeout}s auto kill timeout for running command ${chalk.green(`'${process}'`)}`
  )
);

const abortController = new AbortController();

setTimeout(() => {
  console.log(
    chalk.red(
      `timeout exceeded running command ${chalk.bold(`'${process}'`)}. exiting...`
    )
  );
  if (forceKillProcesses) {
    console.log(
      chalk.red(
        `killing all the process associated with it by runniing ${killCommand}`
      )
    );
    execa({
      shell: true,
      stdio: "inherit",
      verbose: "full",
      timeout: 2000,
      detached: false,
      forceKillAfterDelay: true,
      cleanup: true
    })`${killCommand}`;
  }
  abortController.abort();
}, timeout * 1000);

try {
  execa({
    shell: true,
    stdio: "inherit",
    verbose: "full",
    timeout: timeout * 1000,
    detached: false,
    killSignal: "SIGTERM",
    forceKillAfterDelay: true,
    cancelSignal: forceKillProcesses ? undefined : abortController,
    cleanup: true
  })`${process}`;
} catch (err) {
  console.log(chalk.red(err));
}

然后运行脚本

node process-gaurd.js -t 600 -p 'npm run test' -k 'react-app-rewired/scripts/test.js|jest'
© www.soinside.com 2019 - 2024. All rights reserved.