读取通过 createProcess 获得的管道的几行,然后关闭它
Reading a couple of lines of a pipe obtained with createProcess and then closing it
我有一个生成进程的函数,如下所示:
(_, Just outh, _, ph) <- createProcess $
(proc "someproc" []) { std_out = CreatePipe }
line <- hGetLine outh
doSomeComputationOn line
-- ... 'outh' is not read anymore from here onwards
所以创建了"someproc"
,然后parent从里面读取了一个line
来获取一些信息,然后忘记了句柄为outh
的管道。
现在的问题是,如果管道不读,"someproc"
一满就会阻塞。所以这要求父进程读取 outh
即使它没有对它做任何事情。所以我的问题是:
- 这是获取子进程输出的第一行然后忘记其他输出的好方法吗?
- 在 Haskell 中有什么方法可以自动丢弃管道的输入(甚至将其重定向到文件)?
到目前为止,我能看到解决这个问题的唯一方法是生成一个新线程,不断尝试从 outh
读取(并丢弃输出),这表明我做错了什么...
作为附加背景,此问题与 。
有关
要使用的替代方法取决于外部命令的行为。
如果你只是想打断它,你可以hClose outh
。这将关闭管道,并且通过外部命令进一步写入管道将失败并出现 "broken pipe" 错误。大多数进程在收到此消息后终止。
如果您想要读取并丢弃输出,您也可以这样做。也许最简单的方法是
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
应该 运行 常量 space。
如果您不想等待进程结束再执行doStuff
,请将所有内容包装在forkIO
.
中
Now the problem is that if the pipe is not read, "someproc" will block as soon as it is full. [...] Is there any way in Haskell in which I can automatically discard the
input to the pipe (or even redirect it to a file)?
process 有一个名为 process-streaming 的帮助程序库(由本答案的作者编写)试图做到这一点:即使用户通过不会耗尽标准流的流消耗函数,它会在引擎盖下自动排出流以避免潜在的死锁。
该库不直接使用句柄,但接受 pipe-consuming functions and foldl folds through an 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
尽管库的依赖足迹比 process 大得多。
我有一个生成进程的函数,如下所示:
(_, Just outh, _, ph) <- createProcess $
(proc "someproc" []) { std_out = CreatePipe }
line <- hGetLine outh
doSomeComputationOn line
-- ... 'outh' is not read anymore from here onwards
所以创建了"someproc"
,然后parent从里面读取了一个line
来获取一些信息,然后忘记了句柄为outh
的管道。
现在的问题是,如果管道不读,"someproc"
一满就会阻塞。所以这要求父进程读取 outh
即使它没有对它做任何事情。所以我的问题是:
- 这是获取子进程输出的第一行然后忘记其他输出的好方法吗?
- 在 Haskell 中有什么方法可以自动丢弃管道的输入(甚至将其重定向到文件)?
到目前为止,我能看到解决这个问题的唯一方法是生成一个新线程,不断尝试从 outh
读取(并丢弃输出),这表明我做错了什么...
作为附加背景,此问题与
要使用的替代方法取决于外部命令的行为。
如果你只是想打断它,你可以hClose outh
。这将关闭管道,并且通过外部命令进一步写入管道将失败并出现 "broken pipe" 错误。大多数进程在收到此消息后终止。
如果您想要读取并丢弃输出,您也可以这样做。也许最简单的方法是
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
应该 运行 常量 space。
如果您不想等待进程结束再执行doStuff
,请将所有内容包装在forkIO
.
Now the problem is that if the pipe is not read, "someproc" will block as soon as it is full. [...] Is there any way in Haskell in which I can automatically discard the input to the pipe (or even redirect it to a file)?
process 有一个名为 process-streaming 的帮助程序库(由本答案的作者编写)试图做到这一点:即使用户通过不会耗尽标准流的流消耗函数,它会在引擎盖下自动排出流以避免潜在的死锁。
该库不直接使用句柄,但接受 pipe-consuming functions and foldl folds through an 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
尽管库的依赖足迹比 process 大得多。