代码之家  ›  专栏  ›  技术社区  ›  Damian Nadales

读取通过createProcess获得的管道的几行,然后将其关闭

  •  1
  • Damian Nadales  · 技术社区  · 7 年前

    (_, Just outh, _, ph) <- createProcess $
        (proc "someproc" []) { std_out = CreatePipe }
    line <- hGetLine outh
    doSomeComputationOn line
    -- ... 'outh' is not read anymore from here onwards
    

    所以 "someproc" 创建,然后父对象读取 line 从中获取一些信息,然后忘记了句柄为的管道 outh .

    现在的问题是,如果没有读取管道, “someproc” 它一满就会阻塞。因此,这需要父进程读取 即使它与它没有任何关系。所以我的问题是:

    1. 这是获得子进程输出的第一行,然后忘记其他输出的好方法吗?
    2. Haskell中是否有任何方法可以自动放弃管道的输入(甚至将其重定向到文件)?。

    到目前为止,我能看到的解决这个问题的唯一方法是产生一个新的线程,不断尝试从中读取 (并丢弃输出),这表明我做错了什么。。。

    作为附加背景,这个问题与 this one .

    2 回复  |  直到 7 年前
        1
  •  1
  •   danidiaz    7 年前

    现在的问题是,如果没有读取管道,“someproc”将在管道充满后立即阻塞。[...] 在Haskell中有什么方法可以自动丢弃 输入到管道(甚至重定向到文件)?

    有一个用于 过程 打电话 process-streaming 自动地

    库不直接使用句柄,但接受 pipe -消费功能和 foldl adapter type .

    import           Data.Text.Lazy
    import qualified Pipes.Prelude
    import           System.Process.Streaming      (CreateProcess,shell,
                                                    piped,execute,foldOut,transduce1,withCont)
    import           System.Process.Streaming.Text (utf8x,foldedLines)
    
    program :: CreateProcess
    program = piped $ shell "{ echo aaa ; echo bbbb ; }"
    
    firstLine :: IO (Maybe Text)
    firstLine = execute program streams
        where
        streams = foldOut
                . transduce1 utf8x
                . transduce1 foldedLines
                $ withCont Pipes.Prelude.head
    

    该库的依赖性足迹比 虽然

        2
  •  1
  •   chi    7 年前

    使用的替代方法取决于外部命令的行为。

    如果你只是想打断,你可以 hClose outh . 这将关闭管道,通过外部命令进一步写入管道将失败,并出现“断管”错误。大多数进程在收到此消息后终止。

    如果您想读取并丢弃输出,也可以这样做。也许最简单的方法是

    do c <- hGetContents outh
       evaluate (length c)  -- force this to fetch all data
       doStuff              -- now we are sure that the remote end closed its output
    

    它应该在恒定的空间中运行。

    doStuff ,将所有内容 forkIO .