【问题标题】:How to forcibly keep a Node.js process from terminating?如何强制阻止 Node.js 进程终止?
【发布时间】:2026-02-18 04:15:01
【问题描述】:

TL;DR

强制保持 Node.js 进程运行的最佳方法是什么,即防止其事件循环运行为空,从而防止进程终止?我能想到的最佳解决方案是:

const SOME_HUGE_INTERVAL = 1 << 30;
setInterval(() => {}, SOME_HUGE_INTERVAL);

如果您将间隔时间保持足够长,这将保持间隔运行而不会造成太多干扰。

有没有更好的方法?

问题的长版

我有一个 Node.js 脚本,它使用 Edge.js 注册回调函数,以便可以从 .NET 中的 DLL 内部调用它。该函数将每秒调用 1 次,发送一个简单的序列号,该序列号应打印到控制台。

Edge.js 部分很好,一切正常。我唯一的问题是我的 Node.js 进程执行它的脚本,然后它用完了要处理的事件。它的事件循环为空,它只是终止,忽略了它应该一直运行以便能够接收来自 DLL 的回调的事实。

我的 Node.js 脚本:

var
    edge = require('edge');

var foo = edge.func({
    assemblyFile: 'cs.dll',
    typeName: 'cs.MyClass',
    methodName: 'Foo'
});

// The callback function that will be called from C# code:
function callback(sequence) {
    console.info('Sequence:', sequence);
}

// Register for a callback:
foo({ callback: callback }, true);

// My hack to keep the process alive:
setInterval(function() {}, 60000);

我的 C# 代码(DLL):

public class MyClass
{
    Func<object, Task<object>> Callback;

    void Bar()
    {
        int sequence = 1;

        while (true)
        {
            Callback(sequence++);
            Thread.Sleep(1000);
        }
    }

    public async Task<object> Foo(dynamic input)
    {
        // Receives the callback function that will be used:
        Callback = (Func<object, Task<object>>)input.callback;

        // Starts a new thread that will call back periodically:
        (new Thread(Bar)).Start();

        return new object { };
    }
}

我能想出的唯一解决方案是注册一个间隔很长的计时器来调用一个空函数,只是为了让调度程序保持忙碌并避免让事件循环为空,从而使进程永远运行。

有没有比我做得更好的方法?即,保持进程运行而不不必使用这种“hack”?

【问题讨论】:

  • 您可以在节点端的套接字上启动一个虚假侦听器以保持您的进程处于活动状态。
  • JXcore(一个 node.js 发行版)有 process.keepAlive 和 process.release 。您可以先调用 process.keepAlive(),然后在需要关闭应用程序时调用 process.release()。
  • 谢谢,@NurayAltin。我现在不打算迁移到 JXCore,但很高兴知道它有一个 API 可以做到这一点。
  • 除非我弄错了,否则您正在寻找Number.POSITIVE_INFINITY 或只是Infinity 全局。我不相信全局 Math 对象中有 POSITIVE_INFINITY 属性。
  • 你是对的,@richremer。刚刚修好了,谢谢。

标签: node.js edge.js


【解决方案1】:

您可以使用setTimeout(function() {""},1000000000000000000); 命令使您的脚本保持活动状态而不会超载。

【讨论】:

    【解决方案2】:

    最简单、干扰最小的解决方案

    老实说,我认为我的方法是侵入性最小的方法:

    setInterval(() => {}, 1 << 30);
    

    这将设置一个无害的间隔,大约每 12 天触发一次,实际上什么都不做,但保持进程运行。

    最初,我的解决方案使用 Number.POSITIVE_INFINITY 作为句点,因此计时器实际上永远不会触发,但这种行为最近被 API 更改,现在它不接受大于 2147483647 的任何值(即 @ 987654326@)。请参阅文档 herehere


    对其他解决方案的评论

    作为参考,这里是到目前为止给出的另外两个答案:

    乔的(从那时起被删除,但完全有效):

    require('net').createServer().listen();
    

    将创建一个“虚假侦听器”,正如他所说。一个小缺点是我们会为此分配一个端口。

    雅各的:

    process.stdin.resume();
    

    或等价物:

    process.stdin.on("data", () => {});
    

    stdin 置于“旧”模式,这是 Node.js 中仍然存在的已弃用功能,以便与在 Node.js v0.10 (reference) 之前编写的脚本兼容。

    我建议不要这样做。它不仅已被弃用,而且还不必要地与标准输入混淆。

    【讨论】:

    • 请注意,虽然 setInterval “侵入性较小”,但它确实需要将 SIGINT 发送到进程。标准输入解决方案允许您通过简单地通过 ctrl+d 发送 EOF 来正常退出。
    • 你确定吗?原因 AFAIK setInterval 由 libuv 在内部处理。无论如何都不需要外部信号来处理定时器。
    • 我假设没有编写任何代码来清除计时器。这意味着大多数用户停止程序的方式是 ctrl+c,它会发送 SIGINT。
    • 对,但我们可能在谈论不同的事情。我的问题是关于防止 Node 的事件循环运行为空,从而完成该过程。如果用户决定以任何方式终止进程,那会很好。我只是不希望进程自行终止。
    【解决方案3】:

    我会再添加一个技巧。以下是使用Promise 的方法:

    new Promise(_ => null);
    

    把它放在.js 文件的底部,它应该永远运行。

    【讨论】:

    • 这是不正确的; explanation.
    • 不幸的是,这不起作用。该过程立即退出。
    【解决方案4】:

    使用"old" Streams mode 来监听永远不会出现的标准输入:

    // Start reading from stdin so we don't exit.
    process.stdin.resume();
    

    【讨论】: