我有一个 Haskell 程序,可以定期记录一些数据。当我将其作为后台进程运行时,除非我将缓冲模式更改为NoBuffering. 我不明白为什么默认设置LineBuffering不起作用。
这是我的测试程序:
import Control.Concurrent (forkIO, threadDelay)
import Control.Monad (forever)
import System.IO (BufferMode(..), hSetBuffering, stdout)
main :: IO ()
main = forever $ do
-- hSetBuffering stdout NoBuffering
threadDelay $ 1000 * 1000
putStrLn "log"
Run Code Online (Sandbox Code Playgroud)
当我在控制台中正常运行该程序时,我得到预期的输出:
$ ./Main
log
log
log
Run Code Online (Sandbox Code Playgroud)
每秒输出一次“log”。当我将其重定向到文件时,它也按预期工作:
$ ./Main >log
^C
$ cat log
log
log
log
Run Code Online (Sandbox Code Playgroud)
但是,当我将其作为后台进程运行时:
$ ./Main >log &
$ cat log
Run Code Online (Sandbox Code Playgroud)
那么日志文件中不会写入任何内容,除非我取消注释将 stdout 缓冲设置为NoBuffering.
我使用该hGetBuffering函数来确定默认缓冲设置,它是LineBuffering. 考虑到每个“log”语句确实位于不同的行,为什么我需要将缓冲模式设置为NoBuffering以便将日志写入日志文件?IE 当缓冲区模式设置为 时,为什么缓冲区不会在每个换行符处刷新LineBuffering?
请参阅对问题的评论。添加此答案主要是为了将问题标记为“已解答”。
没有必要将缓冲模式严格设置为NoBuffering- 或者LineBuffering导致按预期创建日志输出。
问题是当程序在后台模式下运行时,默认值是 ,BlockBuffering而不是。LineBuffering我认为在后台模式下运行程序不会影响标准输出缓冲的默认设置。