Golang坏文件描述符

时间:2015-11-22 04:46:02

标签: go file-descriptor

尝试在go例程中追加日志文件时,我收到了错误的文件描述符。

write ./log.log: bad file descriptor

该文件存在且具有666权限。起初我认为可能是因为他们每个人都试图同时打开文件。我实现了一个互斥锁,试图避免这种情况,但是遇到了同样的问题,所以我删除了它。

logCh := make(chan string, 150)
go func() {
    for {
        msg, ok := <-logCh
        if ok {
            if f, err := os.OpenFile("./log.log", os.O_APPEND, os.ModeAppend); err != nil {
                panic(err)
            } else {
                logTime := time.Now().Format(time.RFC3339)
                if _, err := f.WriteString(logTime + " - " + msg); err != nil {
                    fmt.Print(err)
                }
                f.Close()
            }
        } else {
            fmt.Print("Channel closed! \n")
            break
        }
    }
}()

3 个答案:

答案 0 :(得分:30)

您需要添加O_WRONLY标志:

if f, err := os.OpenFile("./log.log", os.O_APPEND|os.O_WRONLY, os.ModeAppend); err != nil { /*[...]*/ }

要解释一下,这是open的开放式文档:http://man7.org/linux/man-pages/man2/openat.2.html

  

参数标志必须包含以下访问模式之一:          O_RDONLY,O_WRONLY或O_RDWR。这些请求打开文件读取 -          只有,只写或读/写。

如果你查看/usr/local/go/src/syscall/zerrors_linux_amd64.go:660,你可以看到:

O_RDONLY                         = 0x0
O_RDWR                           = 0x2
O_WRONLY                         = 0x1

因此,默认情况下,您将获得只读文件描述符。

答案 1 :(得分:1)

这似乎是Windows和Linux之间的差异。 在Windows上,os.O_APPEND表示写访问权限,如syscall_windows.go中的代码所示。

if mode&O_APPEND != 0 {
    access &^= GENERIC_WRITE
    access |= FILE_APPEND_DATA
}

在linux中,openflags原样传递给linux系统调用

因此,在DOS / WINDOWS中,您不需要显式添加带有附加标志的写标志,因为这是隐含的。 (这是自DOS以来的默认行为) 在Linux中运行确实需要添加额外的标志才能工作。

(...但是imo不应 该标志,因为隐式附加意味着我要写。我应该将其错误报告给golang吗?)

答案 2 :(得分:0)

对我有用

之前的代码:

os.OpenFile(fileName, os.O_CREATE|os.O_APPEND, os.ModePerm)

并发生错误:错误的文件描述符,

然后我将os.O_WRONLY添加到函数中

后面的代码:

os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.ModePerm)

它并没有出现问题。