1package main 2 3import ( 4 "context" 5 "fmt" 6 "io" 7 "net" 8 "os" 9 "sync" 10 11 "github.com/Microsoft/go-winio" 12 "github.com/pkg/errors" 13) 14 15func main() { 16 if err := logContainerStdoutToFile(); err != nil { 17 fmt.Fprintln(os.Stderr, err) 18 os.Exit(1) 19 } 20} 21 22func logContainerStdoutToFile() (err error) { 23 ctx, cancel := context.WithCancel(context.Background()) 24 defer cancel() 25 26 var sout, wait net.Conn 27 28 soutPipe := os.Getenv("CONTAINER_STDOUT") 29 waitPipe := os.Getenv("CONTAINER_WAIT") 30 31 if sout, err = winio.DialPipeContext(ctx, soutPipe); err != nil { 32 return errors.Wrap(err, "couldn't open stdout pipe") 33 } 34 defer sout.Close() 35 36 // The only expected argument should be output file path 37 if len(os.Args[1:]) != 1 { 38 return errors.Errorf("Expected exactly 1 argument, got: %d", len(os.Args[1:])) 39 } 40 41 var dest *os.File 42 destPath := os.Args[1] 43 if dest, err = os.Create(destPath); err != nil { 44 return errors.Wrap(err, "couldn't open destination file") 45 } 46 defer dest.Close() 47 48 if wait, err = winio.DialPipeContext(ctx, waitPipe); err != nil { 49 return errors.Wrap(err, "couldn't open wait pipe") 50 } 51 // Indicate that logging binary is ready to receive output 52 wait.Close() 53 54 var wg sync.WaitGroup 55 56 wg.Add(1) 57 go func() { 58 defer wg.Done() 59 _, err = io.Copy(dest, sout) 60 }() 61 wg.Wait() 62 return 63} 64