लॉग टू फाइल कैसे लिखें


108

मैं गो के साथ एक लॉग फ़ाइल में लिखने की कोशिश कर रहा हूं।

मैंने कई दृष्टिकोणों की कोशिश की है, जिनमें से सभी विफल रहे हैं। यही मैंने कोशिश की है:

func TestLogging(t *testing.T) {
    if !FileExists("logfile") {
        CreateFile("logfile")
    }
    f, err := os.Open("logfile")
    if err != nil {
        t.Fatalf("error: %v", err)
    }

    // attempt #1
    log.SetOutput(io.MultiWriter(os.Stderr, f))
    log.Println("hello, logfile")

    // attempt #2
    log.SetOutput(io.Writer(f))
    log.Println("hello, logfile")

    // attempt #3
    log.SetOutput(f)
    log.Println("hello, logfile")
}

func FileExists(name string) bool {
    if _, err := os.Stat(name); err != nil {
       if os.IsNotExist(err) {
            return false
        }
    }
    return true
}

func CreateFile(name string) error {
    fo, err := os.Create(name)
    if err != nil {
        return err
    }
    defer func() {
        fo.Close()
    }()
    return nil
}

लॉग फ़ाइल बन जाती है, लेकिन कुछ भी कभी भी मुद्रित या संलग्न नहीं होता है। क्यों?


2
यदि आप अपने प्रोग्राम को लिनक्स में तैनात करते हैं, तो आप अपने लॉग को एसटीडी आउटपुट पर लिख सकते हैं, फिर आउटपुट को एक फाइल की तरह पाइप कर सकते हैं : //program 2> & 1 | टी लॉग । अन्य प्रणाली में कोई और तरीका होना चाहिए।
nvcnvn

जवाबों:


165

os.Open() अतीत में अलग तरह से काम किया होगा, लेकिन यह मेरे लिए काम करता है:

f, err := os.OpenFile("testlogfile", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
if err != nil {
    log.Fatalf("error opening file: %v", err)
}
defer f.Close()

log.SetOutput(f)
log.Println("This is a test log entry")

गो डॉक्स के आधार पर, इसके os.Open()लिए काम नहीं कर सकता log.SetOutput, क्योंकि यह "पढ़ने के लिए:" फाइल खोलता है:

func Open

func Open(name string) (file *File, err error) Openपढ़ने के लिए नामित फ़ाइल खोलता है। सफल होने पर, लौटी फ़ाइल पर विधियों को पढ़ने के लिए उपयोग किया जा सकता है; संबंधित फ़ाइल डिस्क्रिप्टर में मोड है O_RDONLY। यदि कोई त्रुटि है, तो यह प्रकार की होगी *PathError

संपादित करें

जांच के defer f.Close()बाद ले जाया गयाif err != nil


9
शून्य के लिए जाँच करने से पहले बंद मत करो!
वोल्कर

यह वास्तव में सभी मामलों में बंद करने के लिए हानिकारक गतिविधि नहीं है। यह सभी प्रकार के लिए सही नहीं है, हालांकि।
डस्टिन

2
@ डस्टिन fहो सकता है nil, जिसके परिणामस्वरूप घबराहट होगी। इसलिए errकॉल डिफर करने से पहले जांच करना उचित है।
nemo

@AllisonA देखभाल के साथ समझाने के लिए क्यों Openकाम नहीं करेगा log.SetOutput?
नीमो

1
उपयोगकर्ता को पढ़ने / लिखने, उपयोगकर्ता और समूह को पढ़ने / लिखने की अनुमति देने के लिए सुरक्षित अनुमतियाँ 0644 या यहां तक ​​कि 0664 हैं, और दोनों ही मामलों में सभी को लिखने की अनुमति नहीं है।
जोनाथन

39

मैं लॉगिंग के लिए 12 फैक्टर ऐप सिफारिश की सादगी और लचीलापन पसंद करता हूं। लॉग फ़ाइल में संलग्न करने के लिए आप शेल पुनर्निर्देशन का उपयोग कर सकते हैं। Go में डिफ़ॉल्ट लकड़हारा stderr (2) को लिखता है।

./app 2>> logfile

इसे भी देखें: http://12factor.net/logs


जब आप चीजों को जल्दी करना चाहते हैं, तो एक अच्छा अभ्यास मत बनो, शुरुआत के साथ एस्प-tsop-daemon
श्रेय

3
@ श्रेय सिस्टमड लॉगिंग का ध्यान रखने के साथ-साथ स्टार्ट-स्टॉप फंक्शन के बारे में भी बता सकता है।
वारगमैस

इसके बावजूद यह एक अच्छा अभ्यास है या नहीं, यह उस प्रकार की लॉगिंग है जिसे मैं गोलंग में ढूंढ रहा हूं। इसे साझा करने के लिए धन्यवाद!
नशे की लत

क्या खिड़कियों के नीचे भी कुछ ऐसा ही है?
सर्फिंग

मेरे $ cd /etc/systemd/system $ sudo vi app.service ExecStart=/bin/bash -c 'sudo go run main.go >> /home/ubuntu/go/src/html_menu_1/logfile' काम की तरह नहीं थाUbuntu 18.04.3
रायसुके हुजीसावा

20

मैं आमतौर पर स्क्रीन पर लॉग प्रिंट करता हूं और एक फाइल में भी लिखता हूं। आशा है कि यह किसी की मदद करता है।

f, err := os.OpenFile("/tmp/orders.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
    log.Fatalf("error opening file: %v", err)
}
defer f.Close()
wrt := io.MultiWriter(os.Stdout, f)
log.SetOutput(wrt)
log.Println(" Orders API Called")

7

यह मेरे लिए काम करता है

  1. logger.go नामक एक पैकेज बनाया

    package logger
    
    import (
      "flag"
      "os"
      "log"
      "go/build"
    )
    
    var (
      Log      *log.Logger
    )
    
    
    func init() {
        // set location of log file
        var logpath = build.Default.GOPATH + "/src/chat/logger/info.log"
    
       flag.Parse()
       var file, err1 = os.Create(logpath)
    
       if err1 != nil {
          panic(err1)
       }
          Log = log.New(file, "", log.LstdFlags|log.Lshortfile)
          Log.Println("LogFile : " + logpath)
    }
    1. जहाँ भी आप लॉग इन करना चाहते हैं, पैकेज को आयात करें

      package main
      
      import (
         "logger"
      )
      
      const (
         VERSION = "0.13"
       )
      
      func main() {
      
          // time to use our logger, print version, processID and number of running process
          logger.Log.Printf("Server v%s pid=%d started with processes: %d", VERSION, os.Getpid(),runtime.GOMAXPROCS(runtime.NumCPU()))
      
      }

6

यदि आप linux मशीन पर बाइनरी चलाते हैं तो आप शेल स्क्रिप्ट का उपयोग कर सकते हैं।

किसी फ़ाइल में ओवरराइट करें

./binaryapp > binaryapp.log

एक फ़ाइल में जोड़ें

./binaryapp >> binaryapp.log

एक फ़ाइल में stderr को अधिलेखित करें

./binaryapp &> binaryapp.error.log

एक फ़ाइल में stderr संलग्न करें

./binaryapp &>> binalyapp.error.log

यह शेल स्क्रिप्ट फ़ाइल का उपयोग करके अधिक गतिशील हो सकता है।


यह जानकर अच्छा लगा, कि हम लॉग करने के लिए स्ट्रेडर को कैसे ओवरराइड करते हैं।
असंभव

5

Go में डिफ़ॉल्ट लकड़हारा stderr (2) को लिखता है। फ़ाइल पर रीडायरेक्ट करें

import ( 
    "syscall"
    "os" 
 )
func main(){
  fErr, err = os.OpenFile("Errfile", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
  syscall.Dup2(int(fErr.Fd()), 1) /* -- stdout */
  syscall.Dup2(int(fErr.Fd()), 2) /* -- stderr */

}

5

अपने वैश्विक में शीर्ष की घोषणा करें varताकि जरूरत पड़ने पर आपकी सभी प्रक्रियाएं पहुंच सकें।

package main

import (
    "log"
    "os"
)
var (
    outfile, _ = os.Create("path/to/my.log") // update path for your needs
    l      = log.New(outfile, "", 0)
)

func main() {
    l.Println("hello, log!!!")
}

हे @ कोस्टाहुंग, कृपया विस्तृत प्रतिक्रिया छोड़ें। धन्यवाद
openwonk

@ कोस्टाहुंग, मैंने सिर्फ अपना कोड स्निपेट चलाया और यह काम करता है।
ओपनवॉक

हाय @openwonk, मैं फिर से परीक्षण किया है और यह मेरे कंप्यूटर पर काम नहीं किया। मेरा संस्करण है go version go1.10.2 windows/amd64, तुम्हारा क्या है?
कोस्टा हुआंग

@ कोस्टाहुंग, मैं आपके साथ एक ही सेट अप के साथ उदाहरण प्रस्तुत करता हूं। उदाहरण मानता है कि आपके पास पहले से ही एक फ़ोल्डर संरचना है। इसके लिए जाँच करने के आसान तरीके हैं, हालाँकि उदाहरण के साथ मेरा लक्ष्य यह दिखाना है कि लॉग फ़ाइल में कितना सरल लेखन है। अपना कोड बदलें, outfile, _ = os.Create("my.log")और यह उम्मीद के मुताबिक काम करेगा।
Openwonk

आपका कोड काम करता है। मैं उपयोग कर रहा था outfile, _ = os.Create("./path/to/my.log")। किसी तरह मुझे उम्मीद थी कि कोड path/toफ़ोल्डर और my.logफ़ाइल बनाएगा , लेकिन जाहिर है कि यह काम नहीं किया। मेरा सुझाव है कि आप अपने उत्तर को संशोधित करें outfile, _ = os.Create("./my.log")। इस तरह हम स्पष्ट रूप से जानते हैं कि यह वर्तमान फ़ोल्डर में एक लॉग बना रहा है।
कोस्टा हुआंग

5

एलीसन और दीपक के उत्तर पर बिल्डिंग, मैंने लॉगरस का उपयोग करना शुरू कर दिया और वास्तव में इसे पसंद किया:

var log = logrus.New()

func init() {

    // log to console and file
    f, err := os.OpenFile("crawler.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    if err != nil {
        log.Fatalf("error opening file: %v", err)
    }
    wrt := io.MultiWriter(os.Stdout, f)

    log.SetOutput(wrt)
}

मेरे पास मुख्य कार्य में एक defer f.Close () है


0

मैं फ़ाइलों के लिए लॉग लिख रहा हूं, जो दैनिक आधार पर उत्पन्न होते हैं (प्रति दिन एक लॉग फ़ाइल उत्पन्न हो रही है)। यह तरीका मेरे लिए ठीक काम कर रहा है:

var (
    serverLogger *log.Logger
)

func init() {
    // set location of log file
    date := time.Now().Format("2006-01-02")
    var logpath = os.Getenv(constant.XDirectoryPath) + constant.LogFilePath + date + constant.LogFileExtension
    os.MkdirAll(os.Getenv(constant.XDirectoryPath)+constant.LogFilePath, os.ModePerm)
    flag.Parse()
    var file, err1 = os.OpenFile(logpath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)

    if err1 != nil {
        panic(err1)
    }
    mw := io.MultiWriter(os.Stdout, file)
    serverLogger = log.New(mw, constant.Empty, log.LstdFlags)
    serverLogger.Println("LogFile : " + logpath)
}

// LogServer logs to server's log file
func LogServer(logLevel enum.LogLevel, message string) {
    _, file, no, ok := runtime.Caller(1)
    logLineData := "logger_server.go"
    if ok {
        file = shortenFilePath(file)
        logLineData = fmt.Sprintf(file + constant.ColonWithSpace + strconv.Itoa(no) + constant.HyphenWithSpace)
    }
    serverLogger.Println(logLineData + logLevel.String() + constant.HyphenWithSpace + message)
}

// ShortenFilePath Shortens file path to a/b/c/d.go tp d.go
func shortenFilePath(file string) string {
    short := file
    for i := len(file) - 1; i > 0; i-- {
        if file[i] == constant.ForwardSlash {
            short = file[i+1:]
            break
        }
    }
    file = short
    return file
}

"shortenFilePath ()" विधि का उपयोग फ़ाइल के पूर्ण पथ से फ़ाइल का नाम प्राप्त करने के लिए किया जाता है। और "LogServer ()" विधि का उपयोग स्वरूपित लॉग स्टेटमेंट बनाने के लिए किया जाता है (जिसमें: फ़ाइल नाम, लाइन नंबर, लॉग स्तर, त्रुटि विवरण आदि ...)


0

दूसरों की मदद करने के लिए, मैं दोनों मामलों में लॉगिंग को संभालने के लिए एक मूल लॉग फ़ंक्शन बनाता हूं, यदि आप आउटपुट को स्टडआउट करना चाहते हैं, तो डिबग चालू करें, इसके सीधे आगे एक स्विच फ्लैग करें ताकि आप अपना आउटपुट चुन सकें।

func myLog(msg ...interface{}) {
    defer func() { r := recover(); if r != nil { fmt.Print("Error detected logging:", r) } }()
    if conf.DEBUG {
        fmt.Println(msg)
    } else {
        logfile, err := os.OpenFile(conf.LOGDIR+"/"+conf.AppName+".log", os.O_RDWR | os.O_CREATE | os.O_APPEND,0666)
        if !checkErr(err) {
            log.SetOutput(logfile)
            log.Println(msg)
        }
        defer logfile.Close()
    }
}




0

शायद यह आपकी मदद करेगा (यदि लॉग फ़ाइल मौजूद है तो इसका उपयोग करें, यदि यह मौजूद नहीं है तो इसे बनाएं):

package main

import (
    "flag"
    "log"
    "os"
)
//Se declara la variable Log. Esta será usada para registrar los eventos.
var (
    Log *log.Logger = Loggerx()
)

func Loggerx() *log.Logger {
    LOG_FILE_LOCATION := os.Getenv("LOG_FILE_LOCATION")
        //En el caso que la variable de entorno exista, el sistema usa la configuración del docker.
    if LOG_FILE_LOCATION == "" {
        LOG_FILE_LOCATION = "../logs/" + APP_NAME + ".log"
    } else {
        LOG_FILE_LOCATION = LOG_FILE_LOCATION + APP_NAME + ".log"
    }
    flag.Parse()
        //Si el archivo existe se rehusa, es decir, no elimina el archivo log y crea uno nuevo.
    if _, err := os.Stat(LOG_FILE_LOCATION); os.IsNotExist(err) {
        file, err1 := os.Create(LOG_FILE_LOCATION)
        if err1 != nil {
            panic(err1)
        }
                //si no existe,se crea uno nuevo.
        return log.New(file, "", log.Ldate|log.Ltime|log.Lshortfile)
    } else {
                //si existe se rehusa.
        file, err := os.OpenFile(LOG_FILE_LOCATION, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
        if err != nil {
            panic(err)
        }
        return log.New(file, "", log.Ldate|log.Ltime|log.Lshortfile)
    }
}

अधिक विवरण के लिए: https://su9.co/9BAE74B

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.