英文:
Golang bad 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
}
}
}()
英文:
I am getting a bad file descriptor when trying to append to a logging file within my go routine.
write ./log.log: bad file descriptor
The file exists and has 666 for permissions. At first I thought well maybe it is because each one of them is trying to open the file at the same time. I implemented a mutex to try and avoid that but got the same issue so I removed it.
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
}
}
}()
答案1
得分: 107
你需要添加O_WRONLY
标志:
if f, err := os.OpenFile("./log.log", os.O_APPEND|os.O_WRONLY, os.ModeAppend); err != nil { /*[...]*/ }
解释一下,这是关于open
函数的Linux文档:http://man7.org/linux/man-pages/man2/openat.2.html:
参数
flags
必须包含以下访问模式之一: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
所以默认情况下你会得到一个只读的文件描述符。
英文:
You need to add the O_WRONLY
flag :
if f, err := os.OpenFile("./log.log", os.O_APPEND|os.O_WRONLY, os.ModeAppend); err != nil { /*[...]*/ }
To explain, here is the linux documentation for open
: http://man7.org/linux/man-pages/man2/openat.2.html :
> The argument flags must include one of the following access modes:
> O_RDONLY, O_WRONLY, or O_RDWR. These request opening the file read-
> only, write-only, or read/write, respectively.
If you check /usr/local/go/src/syscall/zerrors_linux_amd64.go:660, you can see that:
O_RDONLY = 0x0
O_RDWR = 0x2
O_WRONLY = 0x1
So by default you get a read-only file descriptor.
答案2
得分: 3
这似乎是Windows和Linux之间的差异。
在Windows操作系统中,O_APPEND意味着写访问权限,可以在syscall_windows.go代码中看到。
if mode&O_APPEND != 0 {
access &^= GENERIC_WRITE
access |= FILE_APPEND_DATA
}
在Linux中,openflags原样传递给Linux系统调用。
因此,在DOS / WINDOWS中,您不需要显式添加写标志和追加标志,因为它是隐含的(自DOS时代以来一直是默认行为)。
在Linux中,Go需要添加额外的标志才能正常工作。
(...但我认为它不应该“需要”这个标志,因为追加隐含地意味着我想要写入。我应该向golang报告这个问题吗?)
英文:
This appears to be a discrepancy between windows and linux.
On windows os.O_APPEND implies write access, as can be seen in the code in syscall_windows.go.
if mode&O_APPEND != 0 {
access &^= GENERIC_WRITE
access |= FILE_APPEND_DATA
}
in linux the openflags are passed as-is to a linux syscall
So in DOS/WINDOWS you do not need to explicitly add a write flag with an append flag, as it is implied. (this has been default behaviour since the DOS days)
Go in linux does need the extra flag added to work.
(...but imo it should not need this flag, as appending implicitly implies that I want to write. Should I bugreport this to golang ?)
答案3
得分: 2
这是为我使用的代码。
之前的代码:
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)
这样就没有出现问题了。
英文:
it used for me
the code before:
os.OpenFile(fileName, os.O_CREATE|os.O_APPEND, os.ModePerm)
and it occured the error: bad file descriptor,
then i add the os.O_WRONLY into the function
the code after:
os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.ModePerm)
and it did't occured the problem.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论