Haskell 从进程中读取

3

我不确定问题出在哪里,所以我不确定标题是否真正准确。我想要打开一个 shell 进程,并且写入内容然后读取输出:

import System.IO (hPutStr, hGetContents, hSetBuffering, hClose,
            BufferMode(NoBuffering))
import System.Process (runInteractiveProcess)

main = do
        (hIn, hOut, _, _) <- runInteractiveProcess
                                "/bin/sh" [] Nothing Nothing
        hSetBuffering hIn NoBuffering
        hPutStr hIn "ls /\n"
        hGetContents hOut >>= putStrLn
        hClose hIn
        hClose hOut

这似乎可以(有点)有效:

$ ./mwe
bin
boot
cdrom
dev
etc
...

问题是,程序一直卡住(需要用Ctrl-C强制终止)。我想 shell 仍在运行,这阻止了 Haskell 程序的退出。所以我尝试使用 terminateProcess 明确终止 shell:
main = do
        (hIn, hOut, _, sh) <- runInteractiveProcess
                                "/bin/sh" [] Nothing Nothing
        hSetBuffering hIn NoBuffering
        hPutStr hIn "ls /\n"
        hGetContents hOut >>= putStrLn
        terminateProcess sh
        hClose hIn
        hClose hOut

但无济于事。我还尝试向 shell 发送 exit 命令:

    ...
    hGetContents hOut >>= putStrLn
    hPutStr hIn "exit\n"
    ...

这也不起作用。

我确定解决方案非常简单,但我找不到它(尝试搜索“haskell kill process”等,但也许问题不是我认为的那样)。如果已经有人提出了这个问题,请提前道歉。非常感谢您的帮助!


1
你的方法不好,因为你不知道何时停止阅读并开始发送更多命令。人类 shell 用户知道这一点,因为他看到提示符。你的程序不知道 ls 输出在哪里结束,提示符从哪里开始。原则上,你可以解析输出并检测提示符,但这非常困难且容易出错。最好以这样的方式组织它,即只运行一个命令,首先读取所有输入,然后生成所有输出,并且不需要在其输出中间输入任何内容。你使用的语言是无关紧要的。 - n. m.
1
话虽如此,您可以尝试先发送"ls\nexit\n",然后读取输出。但是直接在没有 shell 的情况下执行 ls 更容易。 - n. m.
我明白了。事实证明,禁用缓冲并不能解决这个问题(程序如何知道shell何时完成写入操作呢?),我之前错误地以为可以帮助解决问题。问题在于,我希望能够多次向同一个shell中写入和读取内容,而不是每次都启动新的shell,以便保持相同的环境。无论如何,非常感谢。 - Thomas Junier
你应该创建另一个问题,更详细地描述你的用例以及为什么保持相同的环境很重要。也许你会得到一些解决问题的替代方法的想法。然后在这里的评论中发布新问题的链接。 - ErikR
1个回答

3

我有一些Haskell代码,用于从shell进程读取内容,它不会卡住... 试试看:

import System.Process
import GHC.IO.Handle.Text

main :: IO ()
main = do
   (_,Just ho1, _, hp1) <- createProcess (shell "find -iname \"*.lhs\""){std_out=CreatePipe}
   sOut <- hGetContents ho1
   _ <- waitForProcess hp1

然后,sOut将拥有shell进程的内容。

确实,这不会挂起。但我在想是否可以创建一个进程,将其保留并传递给其他函数,这些函数本身会从中写入和读取。正如@n.m.所指出的那样,这是行不通的。无论如何,谢谢大家。 - Thomas Junier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接