在后台运行的 Haskell 程序不会将输出重定向到文件,除非缓冲模式为 NoBuffering

jca*_*er2 5 haskell

我有一个 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

jca*_*er2 1

请参阅对问题的评论。添加此答案主要是为了将问题标记为“已解答”。

没有必要将缓冲模式严格设置为NoBuffering- 或者LineBuffering导致按预期创建日志输出。

问题是当程序在后台模式下运行时,默认值是 ,BlockBuffering而不是。LineBuffering我认为在后台模式下运行程序不会影响标准输出缓冲的默认设置。