process.kill 后清理

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

我有一个脚本,它创建一个临时文件,然后做一些其他事情,当脚本退出时,它会删除临时文件。

  • 当脚本正常退出(0)时,临时文件被删除。
  • 当我在脚本运行时按
    control
    +
    C
    时,临时文件将被删除。

但是当我在另一个 NodeJS 脚本中运行此脚本并使用

process.kill(pid)
终止它时,临时文件将不会被删除。即使脚本被
process.kill
subProcess.kill
终止,如何确保删除临时文件?

注意:脚本在windows环境下运行时会出现这个问题(我使用的是Windows 11,通过git bash、powershell运行)。但是当脚本在linux上运行时不会出现这种情况。(我使用WSL2,ubuntu)。

我想这可能与此信号事件有关:

Windows 不支持信号,因此没有相当于通过信号终止的功能,但 Node.js 提供了一些对 process.kill() 和 subprocess.kill() 的模拟:

有什么解决办法吗?

另一个注意事项:这个脚本被传递给lint-staged,如果我没记错的话,当任务失败时,其他并发运行的任务将被process.kill杀死。我无法控制是否使用

process.kill

import fs from "fs";

const tmpFile = "foo.txt";
fs.writeFileSync(tmpFile, "randomContent");

// Attach cleanup handlers
let didCleanup = false;
for (const signal of ["exit", "SIGHUP", "SIGINT", "SIGTERM"] as const) {
    process.on(signal, () => {
        if (!didCleanup) {
            didCleanup = true;
            fs.unlinkSync(tmpFile);
        }

        if (signal !== "exit") {
            let exitCode: number;
            switch (signal) {
                case "SIGHUP":
                    exitCode = 129;
                    break;
                case "SIGINT":
                    exitCode = 130;
                    break;
                case "SIGTERM":
                    exitCode = 143;
                    break;
            }
            process.exit(exitCode);
        }
    });
}

// some other tasks that interact with the temp file...

node.js process signals
1个回答
0
投票

经过一番研究,这就是我解决问题的方法。

为了确保即使进程终止也执行清理,您可以创建一个守护进程

从技术上来说,与类Unix系统相比,Windows对进程信号的支持有限,特别是当

process.kill
用于终止进程时,信号不会被进程捕获,因此即使你在这些信号上注册事件
process.on("SIGINT") 
process.on("SIGTERM")
..,它不会激发听众。请参阅信号事件

要在 NodeJS 中创建守护进程,可以使用 “double-forking”,以下是一个简化的示例,如果您需要更多详细信息,可以查看此包:tscw-config

// main.js
if (process.platform === "win32") {
  // Create a daemon by double-forking.
  const intermediate = spawn(
    process.argv[0],
    [
      path.relative(process.cwd(), path.join(__dirname, "./intermediate.js")),
      // pass down all args that cleanup function needs.
      process.pid.toString(),
      tmpTsconfig,
    ],
    {
      detached: true,
      stdio: "ignore",
    },
  );
  intermediate.unref();
}

// intermediate.js
const parentPid = parseInt(process.argv[2], 10).toString();
const tmpTsconfig = process.argv[3];

// spawn the cleanup function then exit immediately, this will make the cleanup process an orphan process.
const sub = spawn(
  process.argv[0],
  [path.relative(process.cwd(), path.join(__dirname, "./cleanupMonitor.js")), parentPid, tmpTsconfig],
  {
    detached: true,
    stdio: "ignore",
  },
);

sub.unref();
exit(0);

// cleanupMonitor.js
const parentPid = parseInt(process.argv[2], 10);
const tmpTsconfig = process.argv[3];

// Check every second if the parent process is still running
setInterval(() => {
    if (!isRunning(parentPid)) {
        if (fs.existsSync(tmpTsconfig)) {
            fs.unlinkSync(tmpTsconfig);
        }
        exit(0);
    }
}, 1000);
© www.soinside.com 2019 - 2024. All rights reserved.