Düğüm: konsol yerine bir dosyaya giriş yapın


174

console.logGünlüklerin konsolda yazdırılmak yerine bir dosyaya yazılmasını sağlayacak şekilde yapılandırabilir miyim ?


1
olabilir, ancak uzun çalışma süresi üretim uygulamaları için, belirli bir güne ait günlükleri bulmak zor olurdu, değil mi? @racar

Yanıtlar:


73

Güncelleme 2013 - Bu, v0.2 ve v0.4 düğümü çevresinde yazılmıştır; Günlüğe kaydetmenin etrafında çok daha iyi faydalar var. Winston tavsiye ederim

Güncelleme 2013 Sonu - Hala winston kullanıyoruz, ancak şimdi özel nesneleri günlüğe kaydetme ve biçimlendirme etrafındaki işlevselliği sarmak için bir logger kütüphanesi ile. İşte logger.js dosyamızın bir örneği https://gist.github.com/rtgibbons/7354879


Bu kadar basit olmalı.

var access = fs.createWriteStream(dir + '/node.access.log', { flags: 'a' })
      , error = fs.createWriteStream(dir + '/node.error.log', { flags: 'a' });

// redirect stdout / stderr
proc.stdout.pipe(access);
proc.stderr.pipe(error);

1
Nvm, bu süreç bence düşünüyorum ... Bu nasıl çalışır? console.log(whatever);hala konsola gider, dosyaya değil.
trusktr

12
Yakın zamanda yapılan bir değişiklik nedeniyle, artık stderr.pipe () 'i çağıramazsınız - bunu şimdi alıyor:process.__defineGetter__('stderr', function() { return fs.createWriteStream(__dirname + '/error.log', {flags:'a'}) })
damianb

15
Şahsen Winston'dan çok uzak dururdum. Bir yılı aşkın bir süredir kullandık ve sonunda üretim ortamımızda birçok soruna neden olduğu için tamamen kaldırmaya karar verdik. Proje şu anda son derece zayıf bir şekilde sürdürülüyor gibi görünüyor. Kolunuz olduğu sürece bir sorun listesi var. Sorunların çoğunun diğer kullanıcılar tarafından gönderilen istekleri vardı, ancak proje yöneticileri bunları birleştirmek için bile zaman ayırmıyor. Alternatifler için düğüm-bunyan ve tırtıl bakmaya değer olabilir.
UpTheCreek

Koruyucuların cevap vermemeleri berbat. Ben Nodejitsu millet tarafından muhafaza olduğunu düşündüm. Günde bir milyondan fazla sayfa görüntülemesini çeken ve günlük kaydıyla ilgili herhangi bir sorun yaşamadığımız birkaç sitede kullandık. Belki de kaydedilenlerle ve miktarıyla ilgilidir.
Ryan Gibbons

1
Nisan 2015 itibariyle Winston güncel ve iyi bir etkinlik alıyor gibi görünüyor.
Mike Grace

181

Ayrıca, varsayılan console.log işlevini aşırı yükleyebilirsiniz:

var fs = require('fs');
var util = require('util');
var log_file = fs.createWriteStream(__dirname + '/debug.log', {flags : 'w'});
var log_stdout = process.stdout;

console.log = function(d) { //
  log_file.write(util.format(d) + '\n');
  log_stdout.write(util.format(d) + '\n');
};

Yukarıdaki örnek debug.log ve stdout'a giriş yapacaktır.

Düzenleme: Bu sayfadaki Clément tarafından çok parametreli versiyona da bakın.


9
i üzerinde üzerine yazma rahatsız etmem console.log. Sadece belirli bir dosyada oturum açan kendi işlevinizi oluşturun.
Alexander Mills

Ayrıca, bu birden çok parametre için çalışmaz. Örneğin, console.log (p1, p2, p3)
user603749

10
Mükemmel cevap! Ayrıca, birden çok console.log argümanı yakalamak istiyorsanız, 'd' yerine 'Bağımsız Değişkenler' nesnesini alın - developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
Charlie

@AlexMills Merhaba, belki bunun tam olarak nasıl yapılacağına dair bir örnek verebilirsin?
Jonathan

6
ama bunu her js dosyasında olması gerekir, küresel yapmak mümkün mü?
stackdave

60

Üretimde bir şey arıyorsanız Winston muhtemelen en iyi seçimdir.

Sadece hızlıca dev şeyler yapmak istiyorsanız, doğrudan bir dosyaya çıktı (Bence bu sadece * nix sistemleri için çalışır):

nohup node simple-server.js > output.log &

7
Kullanılması >Windows üzerinde de STDOUT eserlerini yönlendirmek. nohupyapmaz.
Brad

1
Bu nohup, * nix, yani olmadan mutlu bir şekilde çalışır node simple-server.js > output.log. Eğer günlüğü yazılı olarak takip etmek isterseniztail -f output.log
kötü mantı

Bu işe yaramadı 2 kez ben sürece geçti argümanlar vardı
eran otzap

Bunu üretimde yapmanın dezavantajı nedir?
marcelino

1
btw işletim sisteminize bağlı olarak, "bu konuda bir şeyler yapın" sadece günlük rotasyon olabilir, bu da iyi bir çözümdür imo - abdussamad.com/archives/541-Log-rotation-in-CentOS-Linux.html
ferr

59

Sık sık console.log () ve console.error () için birçok argüman kullanıyorum , bu yüzden benim çözümüm:

var fs = require('fs');
var util = require('util');
var logFile = fs.createWriteStream('log.txt', { flags: 'a' });
  // Or 'w' to truncate the file every time the process starts.
var logStdout = process.stdout;

console.log = function () {
  logFile.write(util.format.apply(null, arguments) + '\n');
  logStdout.write(util.format.apply(null, arguments) + '\n');
}
console.error = console.log;

32

Winston , günlük kaydı için kullanılan çok popüler bir npm modülüdür.

İşte nasıl yapılır.
Winston'u projenize şu şekilde yükleyin:

npm install winston --save

Projelerimde, araçlar altında logger.js olarak sık kullandığım kullanıma hazır bir yapılandırma.

 /**
 * Configurations of logger.
 */
const winston = require('winston');
const winstonRotator = require('winston-daily-rotate-file');

const consoleConfig = [
  new winston.transports.Console({
    'colorize': true
  })
];

const createLogger = new winston.Logger({
  'transports': consoleConfig
});

const successLogger = createLogger;
successLogger.add(winstonRotator, {
  'name': 'access-file',
  'level': 'info',
  'filename': './logs/access.log',
  'json': false,
  'datePattern': 'yyyy-MM-dd-',
  'prepend': true
});

const errorLogger = createLogger;
errorLogger.add(winstonRotator, {
  'name': 'error-file',
  'level': 'error',
  'filename': './logs/error.log',
  'json': false,
  'datePattern': 'yyyy-MM-dd-',
  'prepend': true
});

module.exports = {
  'successlog': successLogger,
  'errorlog': errorLogger
};

Ve sonra gereken şekilde şu şekilde içe aktarın:

const errorLog = require('../util/logger').errorlog;
const successlog = require('../util/logger').successlog;

Daha sonra başarıyı şu şekilde kaydedebilirsiniz:

successlog.info(`Success Message and variables: ${variable}`);

ve Hatalar:

errorlog.error(`Error Message : ${error}`);

Ayrıca tüm başarı günlüklerini ve hata günlüklerini burada gördüğünüz gibi date-wise günlükleri dizini altındaki bir dosyaya kaydeder.
kütük direği


Günlükler konsolda görülebilir. ve hiçbir dosya hemen oluşturulur !! Bir şey mi kaçırıyorum?
Nigilan

1
Yapılandırmalarınızı paylaşabilir misiniz? Yoksa önerdiğim gibi mi kullandın? Konfigürasyonlar iyi ise içe aktarmaları ( winston& winston-daily-rotate-file) bir kez kontrol edin. logsProjenin kök dizininde adlandırılan bir klasör içinde oluşturulmalıdır . Geciken cevap için beni affedin.
keshavDulal

@Nigilan bunu nasıl düzelttiniz? Aynı sorunla karşı karşıyayım.
user2180794

@ user2180794 Nigilan'ın yorumunun üstündeki yorumuma bir göz atın. Hala halledemezseniz bize bildirin.
keshavDulal

1
Logger-util üstünde bu eklemeyi unutmayın const winston = require('winston'); const winstonRotator = require('winston-daily-rotate-file'); Ve const errorLog = require('../util/logger').errorlog; const successlog = require('../util/logger').successlog; her yerde birşeyler giriş yapmak istiyorum.
keshavDulal

14
const fs = require("fs");
const {keys} = Object;
const {Console} = console;

/**
 * Redirect console to a file.  Call without path or with false-y
 * value to restore original behavior.
 * @param {string} [path]
 */
function file(path) {
    const con = path ? new Console(fs.createWriteStream(path)) : null;

    keys(Console.prototype).forEach(key => {
        if (path) {
            this[key] = (...args) => con[key](...args);
        } else {
            delete this[key];
        }
    });
};

// patch global console object and export
module.exports = console.file = file;

Kullanmak için şöyle bir şey yapın:

require("./console-file");
console.file("/path/to.log");
console.log("write to file!");
console.error("also write to file!");
console.file();    // go back to writing to stdout

sadece hataları kurtarmak mümkün mü?
18'de stackdave

Console.prototypeAnahtarlar üzerinde döngü yapmak yerine , sadece açıkça ayarlanmış this.error.
zengin remer

Bu console.log mu?
G_V

Kırılmaz console.log. Davranışını değiştirir, ancak eski davranışı arayarak geri yükleyebilirsiniz console.file().
zengin hatırlatıcı


7

Basit durumlar için Standart Çıkış (STDOUT) ve Standart Hata (STDERR) akışlarını doğrudan '>' ve '2> & 1' ile dosyaya yönlendirebiliriz

Misal:

// test.js
(function() {
    // Below outputs are sent to Standard Out (STDOUT) stream
    console.log("Hello Log");
    console.info("Hello Info");
    // Below outputs are sent to Standard Error (STDERR) stream
    console.error("Hello Error");
    console.warn("Hello Warning");
})();

düğüm test.js> test.log 2> & 1

POSIX standardına göre, 'girdi', 'çıktı' ve 'hata' akışları pozitif tamsayı dosya tanımlayıcıları (0, 1, 2) tarafından tanımlanır. yani, stdin 0, stdout 1 ve stderr 2'dir.

'2> & 1' 2'den (stderr) 1'e (stdout) yönlendirir

'>' 1'den (stdout) dosyaya (test.log) yönlendirir


6

Henüz belirtilmeyen bir başka çözüm çengel olan Writableakışları process.stdoutve process.stderr. Bu şekilde , stdout ve stderr'ye çıkış yapan tüm konsol işlevlerini geçersiz kılmanız gerekmez . Bu uygulama stdout ve stderr dosyalarını bir günlük dosyasına yeniden yönlendirir:

var log_file = require('fs').createWriteStream(__dirname + '/log.txt', {flags : 'w'})

function hook_stream(stream, callback) {
    var old_write = stream.write

    stream.write = (function(write) {
        return function(string, encoding, fd) {
            write.apply(stream, arguments)  // comments this line if you don't want output in the console
            callback(string, encoding, fd)
        }
    })(stream.write)

    return function() {
        stream.write = old_write
    }
}

console.log('a')
console.error('b')

var unhook_stdout = hook_stream(process.stdout, function(string, encoding, fd) {
    log_file.write(string, encoding)
})

var unhook_stderr = hook_stream(process.stderr, function(string, encoding, fd) {
    log_file.write(string, encoding)
})

console.log('c')
console.error('d')

unhook_stdout()
unhook_stderr()

console.log('e')
console.error('f')

Konsolda yazdırmalıdır

a
b
c
d
e
f

ve günlük dosyasında:

c
d

Daha fazla bilgi için bu özü kontrol edin .


Doğru cevap.
nikk wong

5

Console.log üzerine yazma yoludur. Ancak gerekli modüllerde çalışabilmesi için dışa aktarmanız gerekir.

module.exports = console;

Günlük dosyalarını, döndürme ve diğer şeyleri yazma zahmetinden kurtulmak için, winston gibi basit bir günlükçü modülü kullanmayı düşünebilirsiniz:

// Include the logger module
var winston = require('winston');
// Set up log file. (you can also define size, rotation etc.)
winston.add(winston.transports.File, { filename: 'somefile.log' });
// Overwrite some of the build-in console functions
console.error = winston.error;
console.log = winston.info;
console.info = winston.info;
console.debug = winston.debug;
console.warn = winston.warn;
module.exports = console;

Evet. Afedersiniz. Benim kötü
Simon Rigét

globalnesne üzerindeki konsol özelliklerinin üzerine yazabilirsiniz . neden module.exports?
r3wt

3

YÖNTEM STDOUT VE STDERR

Bu yaklaşım size yardımcı olabilir (projelerimde benzer bir şey kullanıyorum) ve console.log, console.warn, console.error, console.info dahil tüm yöntemler için çalışır

Bu yöntem stdout ve stderr ile yazılan baytları dosyaya yazar. Console.log, console.warn, console.error, console.info yöntemlerini değiştirmekten daha iyidir, çünkü çıktı bu yöntemlerle tamamen aynı olacaktır


var fs= require("fs")
var os= require("os")
var HOME= os.homedir()
var stdout_r = fs.createWriteStream(HOME + '/node.stdout.log', { flags: 'a' })
var stderr_r = fs.createWriteStream(HOME + '/node.stderr.log', { flags: 'a' })

var attachToLog= function(std, std_new){

    var originalwrite= std.write
    std.write= function(data,enc){
        try{
            var d= data
            if(!Buffer.isBuffer(d))
                d= Buffer.from(data, (typeof enc === 'string') ? enc : "utf8")
            std_new.write.apply(std_new, d)
        }catch(e){}
        return originalwrite.apply(std, arguments)
    }


}
attachToLog(process.stdout, stdout_r)
attachToLog(process.stderr, stderr_r)

// recommended catch error on stdout_r and stderr_r
// stdout_r.on("error", yourfunction)
// stderr_r.on("error", yourfunction)

Bunu benim npm modülünde kullanacağım ve size bu kodu atacağım. bu havalı mı?
r3wt

2

Doğrudan Nodejs konsolundaki API belgelerinden

const output = fs.createWriteStream('./stdout.log');
const errorOutput = fs.createWriteStream('./stderr.log');
// custom simple logger
const logger = new Console(output, errorOutput);
// use it like console
const count = 5;
logger.log('count: %d', count);
// in stdout.log: count 5

1

Artık Caterpillar'ı kullanabilirsiniz akış tabanlı bir kayıt sistemi olan kullanarak oturum açmanıza ve ardından çıkışı farklı dönüşümlere ve konumlara bağlamanıza izin verebilirsiniz.

Bir dosyaya çıktı almak şu kadar kolaydır:

var logger = new (require('./').Logger)();
logger.pipe(require('fs').createWriteStream('./debug.log'));
logger.log('your log message');

Caterpillar Web Sitesinde tam örnek



0

Çıkış akışını bir akışımla değiştirme fikrini aldım.

const LogLater                = require ('./loglater.js');
var logfile=new LogLater( 'log'+( new Date().toISOString().replace(/[^a-zA-Z0-9]/g,'-') )+'.txt' );


var PassThrough = require('stream').PassThrough;

var myout= new PassThrough();
var wasout=console._stdout;
myout.on('data',(data)=>{logfile.dateline("\r\n"+data);wasout.write(data);});
console._stdout=myout;

var myerr= new PassThrough();
var waserr=console._stderr;
myerr.on('data',(data)=>{logfile.dateline("\r\n"+data);waserr.write(data);});
console._stderr=myerr;

loglater.js:

const fs = require('fs');

function LogLater(filename, noduplicates, interval) {
    this.filename = filename || "loglater.txt";
    this.arr = [];
    this.timeout = false;
    this.interval = interval || 1000;
    this.noduplicates = noduplicates || true;
    this.onsavetimeout_bind = this.onsavetimeout.bind(this);
    this.lasttext = "";
    process.on('exit',()=>{ if(this.timeout)clearTimeout(this.timeout);this.timeout=false; this.save(); })
}

LogLater.prototype = {
    _log: function _log(text) {
        this.arr.push(text);
        if (!this.timeout) this.timeout = setTimeout(this.onsavetimeout_bind, this.interval);
    },
    text: function log(text, loglastline) {
        if (this.noduplicates) {
            if (this.lasttext === text) return;
            this.lastline = text;
        }
        this._log(text);
    },
    line: function log(text, loglastline) {
        if (this.noduplicates) {
            if (this.lasttext === text) return;
            this.lastline = text;
        }
        this._log(text + '\r\n');
    },
    dateline: function dateline(text) {
        if (this.noduplicates) {
            if (this.lasttext === text) return;
            this.lastline = text;
        }
        this._log(((new Date()).toISOString()) + '\t' + text + '\r\n');
    },
    onsavetimeout: function onsavetimeout() {
        this.timeout = false;
        this.save();
    },
    save: function save() { fs.appendFile(this.filename, this.arr.splice(0, this.arr.length).join(''), function(err) { if (err) console.log(err.stack) }); }
}

module.exports = LogLater;

0

Herhangi bir sayıda argümanı ele almak için Andres Riofrio üzerinde geliştirin

var fs = require('fs');
var util = require('util');

var log_file = fs.createWriteStream(__dirname + '/debug.log', {flags : 'w'});
var log_stdout = process.stdout;

console.log = function(...args) {
    var output = args.join(' ');
    log_file.write(util.format(output) + '\r\n');
    log_stdout.write(util.format(output) + '\r\n');
};


0

Kendim için winston'dan örnek aldım ve log(...)yöntemi ekledim (çünkü winston bunu adlandırıyor info(..):

Console.js:

"use strict"

// Include the logger module
const winston = require('winston');

const logger = winston.createLogger({
    level: 'info',
    format: winston.format.json(),
    transports: [
        //
        // - Write to all logs with level `info` and below to `combined.log`
        // - Write all logs error (and below) to `error.log`.
        //
        new winston.transports.File({ filename: 'error.log', level: 'error' }),
        new winston.transports.File({ filename: 'combined.log' })
    ]
});

//
// If we're not in production then log to the `console` with the format:
// `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
//
if (process.env.NODE_ENV !== 'production') {
    logger.add(new winston.transports.Console({
        format: winston.format.simple()
    }));
}

// Add log command
logger.log=logger.info;

module.exports = logger;

Ardından kodunuzda kullanın:

const console = require('Console')

Artık dosyanızdaki normal günlük işlevlerini kullanabilirsiniz ve bir dosya oluşturacak ve konsolunuza kaydedecektir (hata ayıklama / geliştirme sırasında). Çünkü if (process.env.NODE_ENV !== 'production') {(üretimde de istiyorsanız) ...


Winston "ileti" ve günlük düzeyi gibi bir sürü çöp eklemiyor mu?
G_V

@G_V Ne demek istiyorsun? Winston çok esnektir, yapılandırabilirsiniz ... arıyorsunuz ... github.com/winstonjs/winston#formats ?
TechupBusiness
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.