编辑
2024-06-25
Golang
0
请注意,本文编写于 100 天前,最后修改于 100 天前,其中某些信息可能已经过时。

Golang 版本:1.22.2

为了更好的处理 Golang Cmd 的日志输出,我们可以先查看exce.Cmd 结构体的定义。在代码中可以 Stdout io.WriterStderr io.Writer 两个字段,一个进程的标准输出和标准错误输出可以通过这两个字段来指定。 简而言之我们只需要实现一个 io.Writer 接口的结构体,然后将这个结构体赋值给 Cmd 结构体的 StdoutStderr 字段即可。

go
type Cmd struct { // Path is the path of the command to run. // // This is the only field that must be set to a non-zero // value. If Path is relative, it is evaluated relative // to Dir. Path string // Args holds command line arguments, including the command as Args[0]. // If the Args field is empty or nil, Run uses {Path}. // // In typical use, both Path and Args are set by calling Command. Args []string ...... // Stdout and Stderr specify the process's standard output and error. // // If either is nil, Run connects the corresponding file descriptor // to the null device (os.DevNull). // // If either is an *os.File, the corresponding output from the process // is connected directly to that file. // // Otherwise, during the execution of the command a separate goroutine // reads from the process over a pipe and delivers that data to the // corresponding Writer. In this case, Wait does not complete until the // goroutine reaches EOF or encounters an error or a nonzero WaitDelay // expires. // // If Stdout and Stderr are the same writer, and have a type that can // be compared with ==, at most one goroutine at a time will call Write. Stdout io.Writer Stderr io.Writer ..... }

下面是一个简单的实现,将 Cmd 的标准输出和标准错误输出写入到文件中。

go
type LogWriter struct { file *os.File } func NewLogWriter(filename string) (*LogWriter, error) { // 打开文件,如果文件不存在则创建 file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) if err != nil { return nil, err } return &LogWriter{ file: file, }, nil } func (lw *LogWriter) Write(p []byte) (n int, err error) { message := string(p) go func() { // 这里可以对日志进行处理,比如sse推送等 }() // 将日志写入到文件中 if _, err := lw.file.Write(p); err != nil { return 0, err } return len(p), nil } // 关闭日志文件 func (lw *LogWriter) Close() error { return lw.file.Close() }

然后在启动cmd的时候将这个结构体赋值给 Cmd 结构体的 StdoutStderr 字段即可。例如:

go
// 创建一个日志文件 logWriter, e := NewLogWriter("log.txt") if e != nil { log.Log.Errorf("StartTask wirte log error:%s", e.Error()) } ctx, _ := context.WithCancel(context.Background()) cmd := exec.CommandContext(ctx, "sh", "run.sh") cmd.Stdout = logWriter cmd.Stderr = logWriter cmd.Start()

启动完成后查看log.txt文件是否自动创建并且驶入写入了日志信息。

本文作者:南月星河

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!