我想在Haskell中使用bash的2>&1
重定向,将stdout
和stderr
从一个进程合并为一个Handle
。使用System.Process.createProcess
或类似的库函数直接执行此操作会很好,特别是如果它使用与bash重定向w.r.t相同的语义。交错来自句柄的输入。
createProcess
提供的灵活性最初似乎很有希望:可以指定Handle
用于标准文件描述符,因此可以为{{1}提供相同的Handle
}和stdout
。但是,stderr
参数必须在调用之前已存在。如果没有能力在调用函数之前从空中创建Handle
,我不确定问题是否可以通过这种方式解决。
编辑:无论平台如何,解决方案都需要运作。
答案 0 :(得分:4)
开始使用Handle
并不太难:System.IO
提供常量stdin,stdout,stderr :: Handle
和功能withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r
以及openFile :: FilePath -> IOMode -> IO Handle
。
或者,您可以从createProcess
请求新的管道并将自己设置为转发服务(从您孩子的新stdout
和stderr
句柄中读取并将其发送到您的任何地方等)。
答案 1 :(得分:3)
来自here:
import GHC.IO.Handle -- yes, it's GHC-specific
import System.IO
main = do
stdout_excl <- hDuplicate stdout
hDuplicateTo stderr stdout -- redirect stdout to stderr
putStrLn "Hello stderr" -- will print to stderr
hPutStrLn stdout_excl "Hello stdout" -- prints to stdout
答案 2 :(得分:2)
由于Windows本身支持pipe (3)
和GHC的IO库uses CRT file descriptors internally on Windows,因此有可能提出一种至少适用于Windows和* nix的解决方案。基本算法是:
pipe
。这为您提供了两个文件描述符,您可以使用fdToHandle'
将其转换为Handles
。createProcess
,stdout
和stderr
都设置为管道的写入结束。导出c_pipe
的{{3}}模块默认是隐藏的,但您可以编译允许您访问它的base
自定义版本(提示:使用System.Posix.Internals
})。或者,您可以通过FFI访问pipe
。 NB:此解决方案是GHC特定的。