如何在 Haskell 中组合句柄?

发布于 2024-11-25 09:51:42 字数 465 浏览 0 评论 0原文

我希望在 Haskell 中有类似 bash 的 2>&1 重定向的功能,将进程中的 stdoutstderr 组合成一个 <代码>句柄。直接使用 System.Process.createProcess 或类似的库函数来完成此操作会很好,特别是如果它使用与来自句柄的 bash 重定向交错输入相同的语义。

createProcess 提供的灵活性一开始看起来很有希望:可以指定一个用于标准文件描述符的句柄,因此可以使用相同的句柄为 stdoutstderr 提供。但是,Handle 参数必须在调用之前已存在。如果无法在调用函数之前凭空创建一个句柄,我不确定问题是否可以通过这种方式解决。

编辑:该解决方案需要在任何平台上都能工作。

I'd like to have something like bash's 2>&1 redirect in Haskell that combines stdout and stderr from a process into a single Handle. It would be nice to do this directly with System.Process.createProcess or a similar library function, particularly if it used the same semantics as the bash redirect w.r.t. interleaving input from the handles.

The flexibility offered by createProcess seems promising at first: one can specify a Handle to use for the standard file descriptors, so the same Handle could be given for both stdout and stderr. However, the Handle arguments must already exist before the call. Without the ability to create a Handle from thin air before calling the function, I'm not sure the problem can be solved this way.

Edit: The solution needs to work regardless of platform.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我们只是彼此的过ke 2024-12-02 09:51:42

来自此处

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

From 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
将军与妓 2024-12-02 09:51:42

掌握 Handle 并不难:System.IO 提供常量 stdin、stdout、stderr :: Handle 和函数 >withFile::FilePath -> IO模式-> (句柄->IO r)-> IO ropenFile::FilePath -> IO模式-> IO 句柄。

或者,您可以从 createProcess 请求新管道,并将自己设置为转发服务(从您孩子的新 stdoutstderr 句柄读取并将两者发送到您喜欢的任何地方)。

Getting your hands on a Handle isn't too hard: System.IO offers constants stdin,stdout,stderr :: Handle and functions withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r and openFile :: FilePath -> IOMode -> IO Handle.

Alternately, you could request new pipes from createProcess and set yourself up as a forwarding service (reading from the new stdout and stderr handles of your child and sending both to wherever you like).

旧瑾黎汐 2024-12-02 09:51:42

由于 Windows 支持 管道 (3)< /code>原生和 GHC 的 IO 库 在 Windows 内部使用 CRT 文件描述符,因此有可能提出一个至少在 Windows 和 *nix 上都有效的解决方案。基本算法是:

  • 调用pipe。这为您提供了两个文件描述符,您可以使用 fdToHandle'
  • 调用 createProcess,并将 stdoutstderr 均设置为管道的写入端。
  • 从管道的读取端读取子输出。

System.Posix.Internals导出 c_pipe模块默认是隐藏的,但您可以编译一个自定义版本的 base 来访问它(提示:使用 cabal-dev)。或者,您可以通过 FFI 访问pipe注意:此解决方案是 GHC 特定的。

Since Windows supports pipe (3) natively and GHC's IO library uses CRT file descriptors internally on Windows, it is possible to come up with a solution that works on both Windows and *nix at least. The basic algorithm is:

  • Call pipe. This gives you two file descriptors which you can convert to Handles with fdToHandle'.
  • Call createProcess with stdout and stderr both set to the pipe's write end.
  • Read child output from the pipe's read end.

The System.Posix.Internals module, which exports c_pipe, is hidden by default, but you can compile a custom version of base that lets you access it (tip: use cabal-dev). Alternatively, you can access pipe via FFI. NB: this solution is GHC-specific.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文