github.com/enetx/g@v1.0.80/examples/files/stderr_to_file.go (about) 1 package main 2 3 import ( 4 "io" 5 "log" 6 "os" 7 8 "github.com/enetx/g" 9 ) 10 11 func main() { 12 fn := RedirectLogOutput() 13 defer fn() 14 15 g.NewFile("file_not_exist.txt").Stat().Unwrap() 16 } 17 18 func RedirectLogOutput() func() { 19 // Define the name of the log file 20 logfile := "logfile.txt" 21 22 // Open or create the log file in append mode with read and write permissions 23 f, err := os.OpenFile(logfile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) 24 if err != nil { 25 panic(err) 26 } 27 28 // Save the existing stdout for later use 29 out := os.Stdout 30 31 // Create a MultiWriter that writes to both the original stdout and the log file 32 mw := io.MultiWriter(out, f) 33 34 // Create a pipe to capture stdout and stderr 35 r, w, err := os.Pipe() 36 if err != nil { 37 panic(err) 38 } 39 40 // Replace stdout and stderr with the write end of the pipe 41 // os.Stdout = w 42 os.Stderr = w 43 44 // Set the log package's output to the MultiWriter, so log.Print writes to both stdout and the log file 45 log.SetOutput(mw) 46 47 // Create a channel to control program exit 48 exit := make(chan bool) 49 50 go func() { 51 // Copy all reads from the pipe to the MultiWriter, which writes to stdout and the log file 52 io.Copy(mw, r) 53 // Signal that copying is finished by sending true to the channel 54 exit <- true 55 }() 56 57 // Return a function that can be deferred to clean up and ensure writes finish before program exit 58 return func() { 59 // Close the write end of the pipe and wait for copying to finish 60 w.Close() 61 <-exit 62 63 // Close the log file after all writes have finished 64 f.Close() 65 } 66 }