Golang windows 服务不写入日志文件

问题描述 投票:0回答:2

我有一个用 Go 编写并作为 Windows 服务运行的简单 TCP 服务器。它安装/卸载很好,它作为服务工作并完成它的工作,但它不会在日志文件中写一个字。当我在控制台中将它简单地作为可执行文件运行时 - 日志记录工作正常。但是当它作为服务启动时 - 创建了日志文件,应用程序进程打开它(例如不允许删除它)但文件仍然是空的。我做错了什么?

任何建议都表示赞赏。

logging 是这样定义的

func (p *Program) run() {
    exec, _ := os.Executable()
    WORK_DIR = filepath.Join(filepath.Dir(exec), "ATT")
    _, err := checkDir(WORK_DIR)
    if err != nil {
        panic("Не удалось создать рабочий каталог")
    }

    f, err := os.OpenFile(filepath.Join(filepath.Dir(exec), "server.log"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    if err != nil {
        log.Fatalf("Не удалось создать лог-файл: %v", err)
    }
    defer f.Close()

    wrt := io.MultiWriter(os.Stdout, f)
    log.SetOutput(wrt)

    server, err := net.Listen("tcp", ":"+PORT)
    if err != nil {
        log.Fatal(err)
    }
    defer server.Close()
    log.Println("Сервер запущен на порту:", PORT)
    for {
        connection, err := server.Accept()
        if err != nil {
            log.Println("Не удалось установить соединение с клиентом", err)
        }
        go HandleServer(connection)
    }
}
go logging windows-services
2个回答
0
投票

您遇到的日志记录问题可能与作为服务运行时的文件权限有关。当服务启动时,它以不同于作为常规可执行文件运行时的一组权限运行。在某些情况下,该服务可能没有权限写入与可执行文件位于同一位置的日志文件。

一个可能的解决方案是为日志文件指定不同的位置,例如

C:\Windows\System32\LogFiles
,这是Windows中日志文件的常用位置。您还可以尝试在
OpenFile
调用中指定日志文件的绝对路径,以避免对工作目录产生任何混淆。

另一个潜在的问题可能与关闭日志文件的延迟语句有关。当服务终止时,将执行任何延迟的语句,这可能会导致日志文件在所有日志消息被写入之前关闭。为避免这种情况,您可以删除 defer 语句并在服务停止时手动关闭日志文件。

向日志记录调用添加错误处理可能也是一个好主意,以确保即使日志文件不可用也能写入所有日志消息。这是一个例子:

func (p *Program) run() {
    exec, _ := os.Executable()
    WORK_DIR = filepath.Join(filepath.Dir(exec), "ATT")
    _, err := checkDir(WORK_DIR)
    if err != nil {
        panic("Не удалось создать рабочий каталог")
    }

    // Specify the absolute path for the log file
    logFilePath := filepath.Join(filepath.Dir(exec), "server.log")
    f, err := os.OpenFile(logFilePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    if err != nil {
        log.Fatalf("Не удалось создать лог-файл: %v", err)
    }

    // Remove the defer statement to close the log file manually later
    // defer f.Close()

    wrt := io.MultiWriter(os.Stdout, f)
    log.SetOutput(wrt)

    server, err := net.Listen("tcp", ":"+PORT)
    if err != nil {
        log.Fatal(err)
    }
    defer server.Close()
    log.Println("Сервер запущен на порту:", PORT)
    for {
        connection, err := server.Accept()
        if err != nil {
            log.Println("Не удалось установить соединение с клиентом", err)
        }
        go HandleServer(connection)
    }

    // Manually close the log file when the service stops
    f.Close()
}

// Add error handling to the logging calls
func logMessage(message string) {
    _, logErr := log.Println(message)
    if logErr != nil {
        fmt.Printf("Error logging message: %v\n", logErr)
    }
}

希望这些建议能帮助您解决登录服务的问题。请告诉我。


0
投票

原因是

wrt := io.MultiWriter(os.Stdout, f)
.

下面是 multiWriter 的实现。如果按顺序写入失败,则不再进行写入。

func (t *multiWriter) Write(p []byte) (n int, err error) {
    for _, w := range t.writers {
        n, err = w.Write(p)
        if err != nil {
            return
        }
        if n != len(p) {
            err = ErrShortWrite
            return
        }
    }
    return len(p), nil
}

在 Windows 服务中,stdout 不起作用。如果你看wrt.Write的错误,那就是

write /dev/stdout: The handle is invalid
.

© www.soinside.com 2019 - 2024. All rights reserved.