Golang 版本:1.22.2
为了更好的处理 Golang Cmd 的日志输出,我们可以先查看exce.Cmd 结构体的定义。在代码中可以 Stdout io.Writer
和 Stderr io.Writer
两个字段,一个进程的标准输出和标准错误输出可以通过这两个字段来指定。
简而言之我们只需要实现一个 io.Writer 接口的结构体,然后将这个结构体赋值给 Cmd 结构体的 Stdout
和 Stderr
字段即可。
gotype 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 的标准输出和标准错误输出写入到文件中。
gotype 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 结构体的 Stdout
和 Stderr
字段即可。例如:
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 许可协议。转载请注明出处!