【问题标题】:Haskell read from processHaskell 从进程中读取
【发布时间】:2015-10-13 08:12:39
【问题描述】:

我不太确定问题出在哪里,所以我不确定标题是否真的准确。我想打开一个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 杀死它)。我想外壳仍在运行,这会阻止 Haskell prohram 退出。所以我尝试用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

但无济于事。我还尝试将exit 发送到shell:

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

这也不起作用。

我确定解决方案非常简单,但我找不到它(尝试搜索“haskell kill process”等,但问题可能不是我想的那样)。如果已经问过这个问题,请提前道歉。非常感谢任何帮助!

【问题讨论】:

  • 您的方法很糟糕,因为您不知道何时停止阅读并开始发送更多命令。人类 shell 用户知道这一点,因为他看到了提示。您的程序不知道ls 输出在哪里结束,提示从哪里开始。您原则上可以解析输出并检测提示,但这非常困难且容易出错。更好地组织它,使您只运行一个命令,该命令首先读取所有输入然后生成所有输出,并且在其输出中间不需要任何输入。您使用的语言无关紧要。
  • 话虽如此,您可以尝试先发送"ls\nexit\n",然后再读取输出。但是直接执行ls 更容易,根本不用shell。
  • 我明白了。我希望(错误地,事实证明)禁用缓冲会对此有所帮助,但我应该看到它不会(程序如何知道外壳何时完成写入?)。问题是,我希望多次写入和读取同一个 shell,而不是为每个命令启动一个新的 shell,以保持相同的环境。无论如何,非常感谢。
  • 您应该创建另一个问题,其中包含有关您的用例的更多详细信息以及为什么保持相同的环境很重要。也许你会得到一些解决问题的替代方法的想法。然后在此处的 cmets 中发布指向新问题的链接。

标签: shell haskell process io


【解决方案1】:

我有一些从 shell 进程中读取内容的 haskell 代码,但它不会挂起....试一试:

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。但是指出,这是行不通的。还是谢谢你。
猜你喜欢
  • 2011-08-15
  • 1970-01-01
  • 2020-03-24
  • 1970-01-01
  • 2012-04-28
  • 2014-01-28
  • 1970-01-01
  • 1970-01-01
  • 2015-01-28
相关资源
最近更新 更多