我想创建一个进程并定期将我的haskell程序中的一些文本写入进程的stdin(来自IO操作)。
以下在GHCi中正常工作,但在构建和运行时无法正常工作。在GHCi中,一切都运行良好,IO动作的价值定期提供。然而,当构建并运行时,它似乎会在写入进程的标准输入时暂停任意长时间。
我已使用CreateProcess
(来自System.Process
)来创建句柄并尝试hPutStrLn
(bufferent设置为NoBuffering
- LineBuffering
没有工作要么)。
所以我正在尝试使用process-streaming
软件包和pipes
,但似乎无法完成任何工作。
真正的问题是:我如何从haskell创建一个进程并定期写入它?
展示此行为的最小示例:
import System.Process
import Data.IORef
import qualified Data.Text as T -- from the text package
import qualified Data.Text.IO as TIO
import Control.Concurrent.Timer -- from the timers package
import Control.Concurrent.Suspend -- from the suspend package
main = do
(Just hin, _,_,_) <- createProcess_ "bgProcess" $
(System.Process.proc "grep" ["10"]) { std_in = CreatePipe }
ref <- newIORef 0 :: IO (IORef Int)
flip repeatedTimer (msDelay 1000) $ do
x <- atomicModifyIORef' ref $ \x -> (x + 1, x)
hSetBuffering hin NoBuffering
TIO.hPutStrLn hin $ T.pack $ show x
非常感谢任何帮助。
答案 0 :(得分:3)
这是一个管道Producer
,它会发出一系列带有第二个延迟的数字:
{-# language NumDecimals #-}
import Control.Concurrent
import Pipes
import qualified Data.ByteString.Char8 as Bytes
periodic :: Producer Bytes.ByteString IO ()
periodic = go 0
where
go n = do
d <- liftIO (pure (Bytes.pack (show n ++ "\n"))) -- put your IO action here
Pipes.yield d
liftIO (threadDelay 1e6)
go (succ n)
并且,使用process-streaming,我们可以将生产者提供给这样的外部流程:
import System.Process.Streaming
main :: IO ()
main = do
executeInteractive (shell "grep 10"){ std_in = CreatePipe } (feedProducer periodic)
我使用了executeInteractive
,将std_in
自动设置为NoBuffering
。
此外,如果您管道std_out
并希望立即处理每个匹配项,请确保将--line-buffered
选项传递给grep(或使用stdbuf
命令)以确保匹配是在输出端立即可用。
答案 1 :(得分:0)
如何使用threadDelay
,例如:
import Control.Monad (forever)
import Control.Concurrent (threadDelay)
...
forever $ do
x <- atomicModifyIORef' ref $ \x -> (x + 1, x)
hSetBuffering hin NoBuffering
TIO.hPutStrLn hin $ T.pack $ show x
threadDelay 1000000 -- 1 sec
如果你需要同时做其他工作,可以在另一个线程中生成这个。
您可以通过以下方式删除他对IORef的需求:
loop h x = do
hSetBuffering h NoBuffering
TIO.hPutStrLn h $ T.pack $ show x
threadDelay 1000000
loop h (x+1)
当然,您只需要执行hSetBuffering
一次 - 例如在你进入循环之前去做。