所以我编写了一个服务来检查可能存在的日志,如果存在,则用递增的整数重命名它,然后添加要写入的新日志,如下所示:
async function moveLogs( path, i ){
if( i == 10 ){
fs.unlinkSync( path + '.' + i )
} else {
let j = i + 1
if( fs.existsSync( path + '.' + j ) ) {
await moveLogs( path, j )
}
// Then move the log
if( i == 0 ){
await fs.renameSync( path, path+'.'+j )
makeFile( path ) // Make new empty file if doesnt exist
} else {
await fs.renameSync( path+'.'+i, path+'.'+j )
}
}
}
但是,写入日志的服务仍在写入现已重命名的旧日志。 该记录器是一个自制记录器,它在初始化时使用 fs.createWriteStream ,然后在调用附加的写入函数时写入文件:
class Log_Wrap{
constructor( min_level, critical = false ){
if( critical ){
this.log = fs.createWriteStream( process.env.CRITICAL_PATH + min_level.toLowerCase() + '.log', {flags : 'a'})
} else {
this.log = fs.createWriteStream( process.env.LOG_PATH + min_level.toLowerCase() + '.log', {flags : 'a'})
}
var lev = [ true, true, true, true, true, true, true, true ]
for (var i = 0; i < log_level.indexOf( min_level.toUpperCase() ); i++){
lev[i] = false
}
this.level = lev
}
}
...
_write( functionName, level, ...out ) {
this.log.write( '[' + moment().format('YYYY-MM-DD HH:mm:ss') + '] ' + functionName + '.' + level.toUpperCase() + ': ' )
out.forEach( term => {
this.log.write( util.format( term ) ) } )
this.log.write( '\n' )
}
然后 Logger 是一个包含 Log_Wrap 数组的对象,并使用以下方式写入:
write( level, functionName, ...out ){
for( var i = 0; i < this.loggers.length; i++ ){
if ( this.loggers[i].canLog( level.toUpperCase() ) ){
this.loggers[i]._write( functionName, level, ...out )
}
}
}
所以我想问题是: 我应该重组记录器的工作方式,还是有办法循环输出正在写入的日志?
最佳答案
记录器使用的句柄 (this.log
) 指向光盘上的某个位置。重命名文件后,磁盘上的位置将无法再使用旧名称访问,但已经拥有该文件句柄的人将继续写入和读取。直到所有 handle 都被放下。
这个askUbuntu可能会解答你的疑问:https://askubuntu.com/questions/347371/is-it-100-safe-to-rename-a-file-while-its-being-written
如果文件仍然存在,您可以尝试每隔一段时间检查一次记录器: https://nodejs.org/api/fs.html#fs_fs_access_path_mode_callback
关于javascript - 尝试循环出nodeJS中的旧日志仍然会写入循环出的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58115495/