You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何无法打印通过标准输入传入createProcess启动进程的文本?

Haskell System.Process 代码执行卡住问题解析

我在查找System.Process的使用示例时,找到了一段代码:

import System.IO
import System.Process

main = do
    (Just hin, Just hout, _, _) <- createProcess (proc "grep" ["hello"])
                                    { std_in = CreatePipe, std_out = CreatePipe }
    hPutStr hin "hello grep\ngoodbye grep"
    grepBytes <- hGetContents hout
    putStrLn "> grep hello"
    putStrLn grepBytes

程序执行会卡在最后一行,改成putStrLn "1" >> putStrLn grepBytes >> putStrLn "2"后,只会打印出1,请问这是什么原因?


核心原因

hGetContents是懒加载的,它会一直等待输入直到遇到EOF;同时你没有关闭grep的输入管道hin,导致grep进程一直等待更多输入,不会退出,也就不会输出EOF,你的程序因此卡在等待hout内容的步骤上。

修复方案

  1. 写完输入后立即关闭hin,明确告诉grep没有更多输入;
  2. 等待grep进程结束,避免僵尸进程,同时确保输出全部读取完成。

修复后的代码示例:

import System.IO
import System.Process
import Control.Concurrent (waitForProcess)

main = do
    (Just hin, Just hout, _, procHandle) <- createProcess (proc "grep" ["hello"])
                                    { std_in = CreatePipe, std_out = CreatePipe }
    hPutStr hin "hello grep\ngoodbye grep"
    hClose hin  -- 关闭输入管道,让grep终止等待输入
    grepBytes <- hGetContents hout
    putStrLn "> grep hello"
    putStrLn grepBytes
    _ <- waitForProcess procHandle  -- 等待进程退出,清理系统资源
    hClose hout  -- 关闭输出管道

补充说明

  • hClose hin是解决卡住的关键:没有这一步,grep会一直阻塞在读取stdin,永远不会输出结果,hGetContents也会一直等待EOF,导致程序卡死;
  • waitForProcess能确保进程正常退出,避免僵尸进程,还能获取退出码用于错误处理;
  • 懒加载的hGetContents在你实际使用grepBytes时才会开始读取,若输入管道未关闭,这个读取操作会无限期等待。

内容的提问来源于stack exchange,提问作者Enlico

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 18:56:01