捕获 stderr 时与子进程交互 haskell

Interacting with a subprocess while capturing stderr haskell

所以我有一个 Haskell 程序,它使用 System.Process.Typed 库与子进程交互。我试图在子进程的整个生命周期内捕获子进程的标准错误。如果子进程在我到达第 * 行之前完成,则当前方法不起作用。我认为要做到这一点,我需要使用 STM,但我对 STM 一无所知,所以想知道是否有更简单的方法。

fun :: MyType -> IO MyOtherType
fun inparam = withProcessWait config $ \process -> do
    hPutStrLn (getStdin process) (getStr1 inparam)
    hFlush (getStdin process)
    response1 <- hGetLine (getStdout process)

    hPutStrLn (getStdin process) (getStr2 inparam)
    hFlush (getStdin process)
    response2 <- hGetLine (getStdout process)

    err <- hGetContents (getStderr process) -- this is line *
    hClose (getStdin process)

    exitCode <- timedWaitExitCode 100 process
    return $ MyOtherType response1 response2 err
  where
    config =    setStdin createPipe
              $ setStdout createPipe
              $ setStderr createPipe
              $ fromString (fp inparam)

提前致谢。

编辑 1:修复了 * 标签

编辑 2:当我尝试 运行 代码时,我得到 Exception: [..] hGetContents: illegal operation (delayed read on closed handle)

您没有在您的代码中具体说明什么“不起作用”,所以我会尝试猜测。我可以立即看到的一个潜在问题是,您正在从函数中 returning 从文件句柄 (response1response2err) 读取的值。这里的问题是 Haskell 是一种惰性语言,因此您 return 的值 实际上 不会从这些句柄中读取,直到真正需要它们为止。并且在需要它们时,子进程已经退出并且句柄已关闭,因此无法读取它们。

最简单的解决方法是在您从函数“return”之前强制读取整个字符串。一种标准方法是使用 force followed by evaluate。这将使您的程序实际读取值并记住它们,因此可以关闭句柄。

所以,而不是:

value <- hGetContents handle

你应该做的:

value' <- hGetContents handle
value <- evaluate $ force value'