Winston: 调用process.exit(0)时记录到文件失败

创建于 2013-03-25  ·  87评论  ·  资料来源: winstonjs/winston

将winston配置为登录到文件并在代码中调用process.exit(0)时,winston永远不会最终创建日志文件并将日志消息附加到该文件。

在理想情况下,winston会很乐意处理这种边缘情况并写入文件,但是我也可以在记录器实例上调用flush以手动强制将flush写入文件。

目前可能有一些手动“刷新”的方法,但是到目前为止,没有记录,也没有运气手动关闭/结束/销毁logger实例或其内部流,而实际上导致了日志的生成正在写到文件中。

var winston = require('winston');
var logger = new (winston.Logger)({
  transports: [
    new (winston.transports.Console)(),
    new (winston.transports.File)({ filename: 'winston.log' })
  ]
});

logger.info('info logged');
logger.error('error logged');

process.exit(0);
// the two logs get written out to console, but not to the winston.log file/
bug important winston-file

最有用的评论

@danielweck不,它坏了:#1629#1504!

6年,即正确,对于标记为_important_的错误,为6年。 这是令人印象深刻的边界。

所有87条评论

在node中,console。*方法正在编写异步文件,文件传输是异步的。 您将在节点甚至尚未写入数据之前关闭该进程。

在2013年3月25日,星期一,19:45,Yuri Zapuchlak写道:

将winston配置为登录到文件并在代码中调用process.exit(0)时,winston永远不会最终创建日志文件并将日志消息附加到该文件。
在理想情况下,winston会很乐意处理这种边缘情况并写入文件,但是我也可以在记录器实例上调用flush以手动强制将flush写入文件。
目前可能有一些手动“刷新”的方法,但是到目前为止,没有记录,也没有运气手动关闭/结束/销毁logger实例或其内部流,而实际上导致了日志的生成正在写到文件中。
var winston = require('winston'); var logger = new(winston.Logger)({ logger.info('已记录信息'); logger.error('已记录错误'); process.exit(0); //这两个日志会写到控制台,但不会写到winston.log文件/

-
直接回复此电子邮件或在GitHub(https://github.com/flatiron/winston/issues/228)上查看。

唔。 在这种情况下,如果必须杀死一个节点进程,但需要在杀死该节点进程之前立即记录信息,则将进程.exit()放入具有足够长的持续时间的setTimeout()内,这是唯一可以确保的操作温斯顿实际上将消息写入日志文件?

只是为了清楚起见, console.log和朋友是同步的

@yzapuchlak我还没有实际测试过,但这也是我所做的。

@yzapuchlak setTimeout将_可能_正常工作,但是我认为使用可选的回调参数是明智的。

setTimeout为2000或5000可以在我的简单测试脚本中使用,但是当我尝试在实际代码中使用它时则无法使用。 因此,我不知道该潜在修复程序的可靠性。 如果在可选的回调函数方面没有运气,我将在稍后探讨该问题。

@dtex我只是尝试使用可选的回调(如下面的示例代码所示),但是仍然不会导致日志写入文件中。 在这种情况下,实际上是创建了文件,但没有日志写入该文件。

var winston = require('winston');
var logger = new (winston.Logger)({
  transports: [
    new (winston.transports.Console)(),
    new (winston.transports.File)({ filename: 'winston.log' })
  ]
});

logger.info('winston - info logged');
logger.error('winston - error logged');

logger.info('winston - exiting now', { seriously: true }, function(err, level, msg, meta) {
  console.log('console - CALLING PROCESS EXIT');
  process.exit(0);
});

logger.warn('winston - I probably should only appear in console, not the log file?');

@yzaouchiak很好奇,是0.6.2版吗?

现在有同样的问题,需要终止进程并在日志文件中做一个记录。 具有回调选项会很好,我们只有在编写消息后才能使用它退出进程。 也许它已经存在了?

我在Winston 0.7.2中遇到了同样的问题。
我测试了setTimeout和回调解决方法,但没有成功。

这与#288相同,也是log4js-node问题(https://github.com/nomiddlename/log4js-node/issues/148)。 我认为问题在于,一旦process.exit回调完成后,事件循环就不会运行-因此任何待处理的异步调用(例如文件写入)都没有运行的机会。 如果有人能证明我做错了并提出解决方案,我将非常高兴。

如果我们能提出解决方案,我愿意花费时间解决此问题。 关键问题似乎是WritableStreams不能保证对process.exit()或未处理的异常进行刷新。 是否研究过其他替代解决方案? 似乎我们可以将日志缓存在内存中,直到WritableStream耗尽为止。 然后,如果发生process.exit或未捕获的异常,我们可以同步写入尚未耗尽的所有日志。 这可能会产生重复的日志,但至少可以防止日志丢失。 有什么想法吗?

与#288相关。

这里有更新吗? 仍然因~ 0.9.0而失败

是的,我仍在使用@yzapuchlak之前提到的setTimeout()hack :(

无论如何,我并不真正将其视为Winston的错误。 当你process.exit在你的代码所做的决定完全杀死仍在处理上运行的一切。 如果仍然有HTTP请求正在运行,则不要假设这些请求也会得到答复,那么为什么要假设日志消息确实存在于您的日志中呢? 这就是节点工作的方式,原因是异步的。 如果您使用了回调或setTimeout方法,则没有什么可以阻止您的应用程序在setTimeout完成或调用回调之前立即记录另一行。

解决此问题的唯一方法是进行同步日志记录,但是当您处理请求时,您就无法实现将异步系统作为简单的日志语句的全部目的。

因此,我的建议是使用不会解决的问题来解决此问题。 如果您不想弄错任何日志消息,请确保在调用process.exit之前正确清理并关闭了应用程序。

编辑此外,您的所有setTimeout hacks都有缺陷,无法解决问题,因为您不知道将所有数据写入操作系统将花费多长时间,以及磁盘或ssds的处理速度有多快。 唯一可行的解​​决方案是侦听流的drain事件并退出该过程。 但是,如果您的应用程序连续记录日志,那么很长一段时间都不会调用它; p使其成为另一种黑客,因为您没有在退出前正确关闭应用程序。

事情是目前没有办法等待(回调/承诺/任何)刷新日志。 同样,通过强制同步日志记录,可以在process.on('exit')添加日志

如果要在应用程序的生命周期内进行异步日志记录,而在process.exit期间进行同步日志记录,则应使用具有同步写入功能的自定义文件实现创建一个新的winston实例。 而且,如果您想知道什么时候冲洗东西,您应该听一听流的排水事件。

我会尝试的,谢谢!

对于它的价值,您可以绕开setTimeout的使用,但是您需要获取基础的_stream

// log then exit(1)
logger.error("The thing to log", function(err) {
  var numFlushes = 0;
  var numFlushed = 0;
  Object.keys(logger.transports).forEach(function(k) {
    if (logger.transports[k]._stream) {
      numFlushes += 1;
      logger.transports[k]._stream.once("finish", function() {
        numFlushed += 1;
        if (numFlushes === numFlushed) {
          process.exit(1);
        }
      });
      logger.transports[k]._stream.end();
    }
  });
  if (numFlushes === 0) {
    process.exit(1);
  }
});

如上所述,仅使用回调函数不足以使其正确刷新到文件。 对我来说,这就像个虫子。

请注意,我实际上是在听finish事件: https : flushclosed事件因为那也不足以使其正确记录:/

试试这个。 就我而言,它工作得很好。 我们没有直接调用process.exit ,而是让记录器在刷新日志后调用process.exit

logger.js:

var winston = require('winston');

winston.loggers.add('my-logger', {
    console: {
        level: 'debug',
        colorize: true,
        timestamp: true,
        handleExceptions: true
    },
    file: {
        level: 'info',
        colorize: false,
        timestamp: true,
        filename: 'file.log',
        handleExceptions: true
    }
});

var logger = winston.loggers.get('my-logger');


/* ******* *
 * EXPORTS
 * ******* */

exports.exitAfterFlush = function(code) {
    logger.transports.file.on('flush', function() {
        process.exit(code);
    });
};

exports.info = function() {
    logger.info.apply(this, arguments);
};

exports.warn = function() {
    logger.info.apply(this, arguments);
};

exports.error = function() {
    logger.info.apply(this, arguments);
};

在您的代码中:

var logger = require('./logger.js');
logger.exitAfterFlush(0);
logger.info('Done!');

在NodeJS v4.1.2和Winston 1.1.0上测试

我正在使用类似于@ da-mkay的东西。

function closeAllLoggersAndDisconnect() {
    "use strict";

    let openCount = 0;

    Object.keys(loggerInstance.transports).forEach((key) => {

        let transportInstance = loggerInstance.transports[key];

        if (typeof transportInstance.close === "function") {
            transportInstance.close();
            openCount++;
        }

        transportInstance.on("closed", () => {
            openCount--;
        });

        setInterval(() => {
            if (openCount === 0) {
                if (process.connected) {
                    process.disconnect();
                }
            }
        }, 100);
    });
}

在您的代码中:

winston.error("Error Occured", err, () => {
    closeAllLoggersAndDisconnect();
});

理想情况下是很好,如果我可以调用close的方法loggerInstance ,但由于发射的closed事件一旦它完成调用close在基础传输器上使用

使用@Kegsay将步骤和日志写入文件。

还成功使用@Kegsay的步骤...包装在我自己的函数中。

在版本2.2.0上仍然存在此问题。

仍然没有执行吗? 3岁以上。 我不想使用进程出口。

我知道这不是问题,但绝对应该有一个函数可以完成对文件的所有写入操作,并关闭所有打开的内容,以便该进程可以自行退出而无需显式调用它。 很难在生产系统中使用这些东西。

要做到这一点,确实需要温斯顿方面的解决方案。 无论是提供同步文件传输还是提供关闭钩子以“安全”关闭Winston,我都不在乎,这对我来说都是令人满意的解决方案。 但是什么也没有,只会使它无法写入日志,然后退出并确保它们将被实际写入。

同步传输的问题在于,代码的执行将被阻塞,直到IO完成为止,这限制了性能。 无法将异步写入转换为阻塞写入,这意味着一旦对日志进行异步写入,就必须等到NodeJS处理完之后,同时才能执行其他JS代码。

另一方面,可以同步取消promise,可以同步清除超时,可以同步关闭文件和数据库连接,因此更好(性能更高)的解决方案可能是跟踪需要取消/清除/关闭并在调用winston.log_and_exit()的异常处理程序或winston.log_and_exit()的可选回调中关闭它们。

如果Winston跟踪发生错误时需要关闭的所有内容,那肯定会很好,但是这样的任务管理器本身可能是有用的,并且可能值得一个单独的框架(请参见柯里定律)。

我看不到性能在这里有什么影响。 该过程即将终止,温斯顿只需要在最后的日志行进行簿记,在此期间它可以愉快地阻止IMO。

考虑到这个问题有多久了,并且有一个解决方法,我并没有很快在Winston提出任何解决方案。

听起来您和我在跨目的交谈(写作)。 听起来您好像有兴趣将最终消息同步写入文件,而我担心的是确保将在错误之前异步写入的日志写入文件。

将消息同步写入错误之前恰好发生的文件将要求所有消息都同步写入,这就是性能问题。

其他人则担心在出现错误之后但在将最后的日志写入文件之前停止其他JS代码的运行。

可能满足每个人需求的一个选项是编写一个自定义传输,该

是否真的很难提供一个关闭钩子来调用,该钩子要等到所有内容都被刷新后才能返回和/或调用回调? 这几乎可以解决每个用例。

但是,让我也告诉您我的用例,这是我不关心同步日志的原因。 测试。 我不在乎我的测试是否需要一两秒或更长时间才能运行。 我很在乎日志是否是不确定的,因为日志可能会写出也可能不会写出,具体取决于节点决定关闭的速度。 那是不好的。 我全心全意地同意异步应该是默认的。 我不同意它应该是唯一的选择,尤其是考虑到节点内部本身的问题。

@mscharley这就是log4js的工作方式-有一个log4js.shutdown函数,您可以提供一个回调。 它将等待确保所有附加程序(在我看来,winston都将它们称为传输器)已经完成编写,然后再调用回调。 对于我的用户来说,它似乎工作正常。 它确实需要附加程序的支持,因为需要编写附加程序,以便它们可以响应关闭调用。

顺便说一句,我并不是要推广log4js,也不是说它比winston更好-只是指出这种方法是行得通的。 这可能不是最佳方法。

这是关于winston.log_and_exit()作用。 请注意,在附加基于可写流( appenders.filter(a => a.shutdown).forEach(a => a.shutdown(complete)); )的情况下, log4js.shutdown()取决于writable.end(complete) ,这仍然是异步关闭的。

我认为关于@mscharley的注释,优点是有一个fileSync附加程序,它不需要使用shutdown()即可在Node写入文件时将完整的日志写入文件中。流程退出...

是的,在某些情况下使用fileSync传输会很有用,即使这会导致性能净下降。

@jdthorpe我认为您的想法是,拥有一个可以在关闭之前干净地关闭所有内容的库的想法很不错,但是它仍然没有将责任从Winston转移到提供一种等待它将所有内容刷新到磁盘的方法上(例如,提供关闭自身的机制),然后可以将其与此类库结合使用,以汇总各种库的close方法。

这张票至少可以更改文档,所以它看起来好像不是当前受支持吗?我只是花了30分钟来调试此问题,据说当您在存储库中搜索seriously时才受到支持。 README 。 这似乎是一个不受支持的功能或一个错误,并且解决方法并不是真的很可口。

什么时候可以解决? 这已经存在了3年了,非常重要。

至少让我们在实际起作用的记录器中放置一个回调。

我想说的是,可能为每个人编写了一个通用的shutdown()函数作为一项新功能,并且此功能非常关键。

是的,这是一个非常非常重要的问题imo

为此+1

坦率地说,我认为添加shutdown(callback)似乎是适当的,但需要警告的是运输工具需要积极地支持它。 各个传输是有关其基础输出机制的“信息专家”。 他们拥有有关应如何彻底关闭的最多信息。

winston核心所做的任何事情-以及绝对是我们在用户土地上所做的任何事情-都需要泄漏传输的实现细节。

因此, winston不需要做这项工作……但是它确实需要提供一种完成工作的方式。 然后,我们所有人都可以与运输作者一起进行繁重的工作。

一些伪代码来说明以下几点。

```js
关机(回调){
var transportCount = transports.length
var finish = 0;
//每次运输
如果(transport.shutdown){
transport.shutdown(function(){
//增加完成计数。
//如果全部完成,则调用原始回调。
});
} 别的 {
//传输尚不支持它。
//递增完成计数器
}
}

很乐意在v3.x中看到此问题。

这是我的解决方案(假设环境支持async / await


对于单次运输:

const logTransport = new winston.transports.File({filename: '/log/app.log'})

global.log = winston.createLogger({transports: [logTransport]})

// helper to exit with a given return code, but only after the logger is finished
// this will return a Promise that will never resolve, thus halting execution
log.exit = (exit = 5) => {
  return new Promise(() => {
    logTransport.on('finished', () => process.exit(exit))
  })
}



对于多种运输方式(未试用):

```js
const logTransports = [新的winston.transports.File({文件名:'/log/app.log'})]

global.log = winston.createLogger({transports:[logTransport]})

//辅助程序以给定的返回码退出,但仅在记录器完成后才退出
//这将返回一个永不解决的Promise,从而暂停执行
log.exit =(退出= 5)=> {
返回新的Promise(()=> {
Promise.all(
logTransports.map(transport =>新的Promise(resolve => transport.on('finished',resolve)))
).then(()=> process.exit(exit))
})
}

</details>
<br>
Then, call with `await` like:

```js
try {
  something()
} catch(e) {   
  //do something with the error
  await log.exit(5) // <--- nothing will happen past this line as the promise will never resolve!
  // <--- process will have exited before it reaches here
  trySomethingElse() // <--- this will never be called, and control wont return to the calling code
}

不要破纪录,但是Winston日志和退出也可以解决此问题

仅适用于非常非常特定的用例。 我不能使用winston-log-and-exit来表示该过程不会退出,但该过程确实在两次执行之间冻结,因此日志仍然会丢失。 它还假设我知道哪些消息是我的最终消息,在成功的执行路径中可能并非总是如此。

@mscharley上述await解决方案适用于您的用例吗? 也许不是log.exit()更好的API将await log.finish()它会等到所有传输写完,然后让你做什么(调用process.exit ,请拨打LAMDA done回调等)

除了Winston内部,这基本上就是我们在本期中一直追求的目标。 为什么这会是一个插件? 似乎应该更频繁地出现一些东西。 我不觉得我们正在做的事情有什么特别之处,但是我们在每个项目中都碰到了这堵墙-这就是为什么我们最终离开温斯顿的原因。 松动日志,尤其是在过程结束时(最有可能发生错误的地方),至少看起来很危险。

log4js-node实现了一个shutdown方法,该process.exit()类的回调。 可以将类似的内容添加到Winston吗?

然后是log4js-node

任何更新? 问题是很实际的。

对于任何测井系统,演算是:

  • 如果您绝对必须拥有日志并愿意支付响应时间较慢的费用,请使用同步记录器
  • 如果您自己呼叫process.exit() ,请等待直到清除缓冲的消息。 对于winston, winston-log-and-exit软件包可以为您完成此任务。
  • 如果其他一些代码正在调用process.exit()并且您的平台具有退出钩子,请使用该钩子并等待,直到清除了缓冲的消息为止。 Winston日志和退出也可以提供帮助。
  • 如果您使用的是类似AWS Lambda的平台,而该平台没有退出挂钩,那么您就在利用该平台的好处来交换丢失数据的风险。

顺便说一句,@ begin-再次, log_and_exit()方法与log-4js的shutdown()方法基本相同,另外还保证将记录提供的日志消息。

@jdthorpe但是winston-log-and-exit不会在Winston 3上轻松工作

@VRuzhentsov哦,那是一个问题。 他们真的应该为此做些事情。

@jdthorpe

const transport = new Transport();
const logger = createLogger({
  transports: [
    transport 
  ]
})

logger.finish = (exitCode) => {
  transport.on('finish', () => process.exit(exitCode));
  transport.close();
};

const shutDown = (exitCode) => {
  logger.info('Shutting down');
  logger.finish(exitCode);
};

shutDown(1);

以下对我有用:

logger.info('winston - info logged');
logger.error('winston - error logged');
process.nextTick(() => {
    process.exit(0)
})

@ redhat-raptor。 那将在大多数时间都有效,但不能保证一直都有效。 只是碰巧在调用nextTick()时清除了缓冲区,但是根据记录器所依赖的连接,这很容易导致消息丢失...

这段代码对我有用:

            logger.error(`No value specified for ${value} variable! Node will exit now...`);
            logger._flush(() => {
                process.exit(1);
            })

v3不本地支持此功能吗?

https://github.com/winstonjs/winston/blob/master/README.md#awaiting -logs-to-be-write-in-winston

@danielweck不,它坏了:#1629#1504!

6年,即正确,对于标记为_important_的错误,为6年。 这是令人印象深刻的边界。

我使用waitForWinston()承诺:

const winston = require('winston');

const fileTransport = new winston.transports.File({ name: 'file', filename: FILE_PATH });
const consoleTransport = new winston.transports.Console({ name: 'console', stderrLevels: ['error'] });
const transports = [
    fileTransport,
    consoleTransport
];
winston.configure({
    level: 'verbose',
    transports,
    format: winston.format.cli()
});
winston.log('info', 'TEST MSG');
try {
    await waitForWinston();
} catch (err) {
    console.log(err);
}
process.exit(0);
const waitForWinston = async () => {
    return new Promise(async (resolve, _reject) => {
        for (const transport of transports) {
            try {
                await closeWinstonTransportAndWaitForFinish(transport);
            } catch (err) {
                console.log(err);
            }
        }
        resolve();
    });
};
const closeWinstonTransportAndWaitForFinish = async (transport) => {
    if (!transport.close) {
        // e.g. transport.name === 'console'
        return Promise.resolve();
    }
    // e.g. transport.name === 'file'

    return new Promise(async (resolve, _reject) => {
        transport._doneFinish = false;
        function done() {
            if (transport._doneFinish) {
                return; // avoid resolving twice, for example timeout after successful 'finish' event
            }
            transport._doneFinish = true;
            resolve();
        }
        setTimeout(() => { // TODO: use a cancellable setInterval instead
            done();
        }, 5000); // just in case the 'finish' event never occurs
        const finished = () => {
            done();
        };

/* Update: `stream.end()` does not flush pending writes, so this solution is inadequate.  For some reason, in recent tests `transport.close();` + `transport.once('finish', ...);` works just fine ... not sure why this works now though! (it used to fail!) */

/*
        if (transport._stream) {
            transport._stream.once('finish', finished);
            transport._stream.end();
        }
*/
            transport.once('finish', finished);
            transport.close();
    });  
};

更新: stream.end()不会刷新挂起的写操作,因此该解决方案是不够的。 由于某些原因,在最近的测试中, transport.close(); + transport.once('finish', ...);可以正常工作……不确定为什么现在可以正常工作! (它曾经失败!)

在我上面的工作解决方案中,关键是要使用:
transport._stream.once('finish', finished); transport._stream.end();
代替:
transport.once('finish', finished); transport.close();
(添加的超时策略特定于我的用例,在一般情况下可能是可选的/冗余的)

更简单的方法:

logger.error(`No value specified for ${missing_vars.join(',')} variable! Node will exit now...`, () => {
            process.exit(1);
        });

@danielweck您是否能够找到解决方案? 我们最近升级到Winston 3.x,但可能不得不回到2.x或在这里没有解决方案的情况下找到其他记录器。

@IRC ,这些问题都与Winston @ 2有关。 考虑到该线程的长度,以及您不询问原始张贴者评论的事实,为什么不从您的问题开始新的线程呢?

顺便说一句,我在Winston @ 3上没有看到丢失日志的任何问题,因此您可能希望将配置包括在新问题中。

@cjbarth这不起作用:

  process.on(type as any, (err: ErrorExtended) => {
    const processLogger: Logger = loggers.get('processLogger');

    processLogger.error(errorFormatter(err, type));

    processLogger.on('finish', function () {
      processLogger.end();
      console.log('never reaches here');
      process.exit(1);
    });
  });

processExit('uncaughtException');
// log and exit for unhandledRejection events.
processExit('unhandledRejection');

@stephanoparaskeva如果我没记错的话, finish事件将永远不会在processLogger上触发,因为您永远不会调用processLogger.end() 。 如果调用此命令,则在Winston完成日志记录后,应触发finish事件。

我还将使用process.disconnect()代替process.exit() ,这使队列耗尽。 当队列耗尽时,它将自动退出。

@stephanoparaskeva如果我没记错的话, finish事件将永远不会在processLogger上触发,因为您永远不会调用processLogger.end() 。 如果调用此命令,则在Winston完成日志记录后,应触发finish事件。

我还将使用process.disconnect()代替process.exit() ,这使队列耗尽。 当队列耗尽时,它将自动退出。

知道了,是这样的吗?

process.on(type as any, (err: ErrorExtended) => {
  const processLogger: Logger = loggers.get('processLogger');

  processLogger.error(errorFormatter(err, type));
  processLogger.end()

  processLogger.on('finish', function () {
    process.disconnect();
  });
});

// log and exit for uncaughtException events.
processExit('uncaughtException');
// log and exit for unhandledRejection events.
processExit('unhandledRejection');

@stephanoparaskeva看起来更好。

我通常会在调用processLogger.end()之前绑定事件处理程序,但这没关系,因为finish事件仅在事件循环打开后才触发,届时将绑定处理程序。 我只是认为在事件处理程序首先绑定的地方编写代码可以使它更清晰。

@cjbarth
哦,您如何将事件处理程序绑定到某些东西?
会是:

processLogger.on('finish', () => {
    this.process.disconnect();
  });

@stephanoparaskeva是的。 那是绑定函数的正确语法

{
  this.process.disconnect();
}

到对象processLogger发出的finish事件。

如果您不调用process.exit而是通过关闭所有连接并等待事件循环耗尽来进行适当的关闭,则根本没有问题。

请参阅: https//stackoverflow.com/a/37592669 ,以更好地了解

结束事件多年后仍然没有发出这个事实,这真令人尴尬。 必须切换记录器并为它们重写我的所有自定义传输方式,这将是一种痛苦。

我不知道温斯顿还没有解决这个问题。 我有一个问题,就是代码中只有第一个记录器才被记录到Logstash(也使用winston-elasticsearch)。 如果我使用logger.end(),那么所有内容都会记录下来,但是程序退出得太早了。 尝试使用上述所有解决方案,但都没有真正起作用。
我真的很无奈

我不知道温斯顿还没有解决这个问题。 我有一个问题,就是代码中只有第一个记录器才被记录到Logstash(也使用winston-elasticsearch)。 如果我使用logger.end(),那么所有内容都会记录下来,但是程序退出得太早了。 尝试使用上述所有解决方案,但都没有真正起作用。
我真的很无奈

你试试这个

我不知道人们如何不知道这个“问题”还没有“解决”,因为没有任何问题。 只需通过不调用exit()编写正确的代码,就可以了。

我不知道人们如何不知道这个“问题”还没有“解决”,因为没有任何问题。 只需通过不调用exit()编写正确的代码,就可以了。

因此,我们解决此问题的方法是不调用process.exit()?

我不知道人们如何不知道这个“问题”还没有“解决”,因为没有任何问题。 只需通过不调用exit()编写正确的代码,就可以了。

因此,我们解决此问题的方法是不调用process.exit()?

是的,在nodejs中总是一个坏主意,请参阅https://stackoverflow.com/a/37592669

我不知道人们如何不知道这个“问题”还没有“解决”,因为没有任何问题。 只需通过不调用exit()编写正确的代码,就可以了。

因此,我们解决此问题的方法是不调用process.exit()?

是的,在nodejs中总是一个坏主意,请参阅https://stackoverflow.com/a/37592669

好吧,我个人使用process.exit的原因是因为我正在监听uncaughtException和unhandledRejection记录到我的所有传输中,然后退出该应用程序。 有没有更好的方法来解决此问题?

我不知道人们如何不知道这个“问题”还没有“解决”,因为没有任何问题。 只需通过不调用exit()编写正确的代码,就可以了。

您在哪里看到我说过我使用过exit()?

我不知道人们如何不知道这个“问题”还没有“解决”,因为没有任何问题。 只需通过不调用exit()编写正确的代码,就可以了。

您在哪里看到我说过我使用过exit()?

很抱歉,假设您的阅读和理解能力足以理解此错误的含义。 再次检查标题。

我不知道人们如何不知道这个“问题”还没有“解决”,因为没有任何问题。 只需通过不调用exit()编写正确的代码,就可以了。

您在哪里看到我说过我使用过exit()?

很抱歉,假设您的阅读和理解能力足以理解此错误的含义。 再次检查标题。

如果您遇到一个已经开放了8年的问题,并且根本没有提供任何适当的帮助,那么您必须非常忙。

我不知道人们如何不知道这个“问题”还没有“解决”,因为没有任何问题。 只需通过不调用exit()编写正确的代码,就可以了。

因此,我们解决此问题的方法是不调用process.exit()?

是的,在nodejs中总是一个坏主意,请参阅https://stackoverflow.com/a/37592669

好吧,我个人使用process.exit的原因是因为我正在监听uncaughtException和unhandledRejection记录到我的所有传输中,然后退出该应用程序。 有没有更好的方法来解决此问题?

我已经有一段时间没有使用Winston了,但是无论如何它不会登录吗? 如果不是,在记录错误后是否将其重新抛出?

我不知道人们如何不知道这个“问题”还没有“解决”,因为没有任何问题。 只需通过不调用exit()编写正确的代码,就可以了。

您在哪里看到我说过我使用过exit()?

很抱歉,假设您的阅读和理解能力足以理解此错误的含义。 再次检查标题。

如果您遇到一个已经开放了8年的问题,并且根本没有提供任何适当的帮助,那么您必须非常忙。

至少我可以解决自己的问题,而不必像小题大做那样抱怨。

此页面是否有帮助?
0 / 5 - 0 等级