কীভাবে ফাইল লগ লিখতে হয়


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
আপনি যদি লিনাক্সে আপনার প্রোগ্রাম স্থাপন করেন তবে আপনি আপনার লগটি কেবল স্টডি আউটপুটে লিখতে পারেন তবে আউটপুটটি কোনও ফাইলে পাইপ করুন:। / প্রোগ্রাম 2> & 1 | tee logs.txt । অন্যান্য সিস্টেমে অবশ্যই অন্য কোনও উপায় থাকতে হবে।
এনভিসিএনভিএন

উত্তর:


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কলটি মুলতুবি করার আগে পরীক্ষা করা বাঞ্ছনীয়।
নিমো

@ অ্যালিসনএ কেন Openকাজ করবে না তা ব্যাখ্যা করার জন্য যত্নশীল log.SetOutput?
nemo

1
নিরাপদ অনুমতিগুলি 0644 বা এমনকি 0664 ব্যবহারকারীর পড়ার / লেখার জন্য, ব্যবহারকারী এবং গোষ্ঠীর পঠন / লেখার অনুমতি দেয় এবং উভয় ক্ষেত্রেই প্রত্যেককে লেখার অনুমতি দেয় না।
জোনাথন

39

আমি লগিংয়ের জন্য 12 ফ্যাক্টর অ্যাপ্লিকেশন প্রস্তাবনের সরলতা এবং নমনীয়তাটিকে পছন্দ করি। লগ ফাইলে সংযুক্ত করতে আপনি শেল পুনঃনির্দেশ ব্যবহার করতে পারেন। গো-তে ডিফল্ট লগার স্টাডারকে লিখুন (2)।

./app 2>> logfile

এছাড়াও দেখুন: http://12factor.net/logs


একটি ভাল অনুশীলন হতে অভ্যস্ত যখন আপনি ESP স্টার্ট tsop-ডেমন সঙ্গে, daemonize জিনিষ করতে চান
Shrey

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. লগার.গো নামে একটি প্যাকেজ তৈরি করেছে

    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

আপনি যদি লিনাক্স মেশিনে বাইনারি চালান তবে আপনি শেল স্ক্রিপ্ট ব্যবহার করতে পারেন।

একটি ফাইলে ওভাররাইট করুন

./binaryapp > binaryapp.log

একটি ফাইল যোগ করুন

./binaryapp >> binaryapp.log

স্ট্যাডারকে একটি ফাইলে ওভাররাইট করুন

./binaryapp &> binaryapp.error.log

একটি ফাইলে স্ট্যাডার যুক্ত করুন

./binaryapp &>> binalyapp.error.log

এটি শেল স্ক্রিপ্ট ফাইল ব্যবহার করে আরও গতিশীল হতে পারে।


জেনে ভাল লাগল, আমরা কিভাবে স্ট্রডারকে লগ করতে ওভাররাইড করব।
অসম্ভব

5

গো-তে ডিফল্ট লগার স্টাডারকে লিখুন (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!!!")
}

আরে @ কোস্টা হুয়াং, দয়া করে বিস্তারিত প্রতিক্রিয়া জানান। ধন্যবাদ
ওপেনওনক

@ কোস্টা হুয়াং, আমি কেবল আমার কোড স্নিপেট চালিয়েছি এবং এটি কার্যকর হয়।
ওপেনওনক

হাই @ ওপেনউইঙ্ক, আমি আবার পরীক্ষা করেছি এবং এটি আমার কম্পিউটারে কার্যকর হয়নি। আমার সংস্করণটি go version go1.10.2 windows/amd64, আপনার কি?
কোস্টা হুয়াং

@ কোস্টা হুয়াং, আমি আপনার মতো একই সেট আপের উদাহরণ রেখেছি। উদাহরণটি ধরে নেওয়া হয়েছে যে আপনার ইতিমধ্যে একটি ফোল্ডার কাঠামো সেট আপ হয়েছে। এটি যাচাই করার সহজ উপায় রয়েছে তবে উদাহরণ সহ আমার লক্ষ্য হ'ল লগ ফাইলে তুলনামূলকভাবে সহজ লেখার পরিমাণ কী। আপনার কোডটি এতে পরিবর্তন করুন outfile, _ = os.Create("my.log")এবং এটি প্রত্যাশার মতো কাজ করবে।
ওপেনওনক

আপনার কোড কাজ করে। আমি ব্যবহার করছিলাম 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)
}

আমার মূল ফাংশনে একটি ডিফার এফ। ক্লোজ () রয়েছে


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 ()" পদ্ধতিটি ফাইলের পুরো পথ থেকে ফাইলটির নাম পেতে ব্যবহৃত হয়। এবং "লগ সার্ভার ()" পদ্ধতিটি একটি ফর্ম্যাট লগ স্টেটমেন্ট তৈরি করতে ব্যবহৃত হয় (এতে রয়েছে: ফাইলের নাম, লাইন নম্বর, লগ স্তর, ত্রুটি বিবৃতি ইত্যাদি ...)


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

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.