2015-10-13 60 views
2

我不太確定問題出在哪裏,所以我不確定標題是否真的準確。我想開一個shell進程,並寫信給它,然後讀取輸出:Haskell從進程中讀取

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 prohram退出。所以我試圖用terminateProcess明確終止外殼:

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到外殼:

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

哪個也不起作用。我確定解決方案非常簡單,但我找不到它(嘗試搜索「haskell kill process」等等,但問題可能不是我想象的)。如果已經提出了這個問題,請提前道歉。任何幫助非常感謝!

+1

您的方法很糟糕,因爲您不知道何時停止閱讀並開始發送更多命令。一個人殼用戶知道,因爲他看到提示。你的程序不知道'ls'輸出結束並且提示開始。原則上可以解析輸出並檢測提示,但這非常困難且容易出錯。更好地組織它,只需運行一個命令,首先讀取所有輸入,然後生成所有輸出,而不需要輸出中間的任何輸入。你使用的語言是不相關的。 –

+1

話雖如此,您可以先嚐試發送''ls \ nexit \ n「',然後讀取輸出。但是,直接執行'ls'並不需要任何shell。 –

+0

我明白了。我希望(錯誤的是,事實證明)禁用緩衝會對此有所幫助,但我應該看到它不會(程序如何知道shell何時寫完?)。事情是,我希望多次寫入和讀取同一個shell,而不是爲每個命令啓動一個新的shell,以保持相同的環境。無論如何,非常感謝。 –

回答

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 process

+0

事實上,這並沒有掛起。但是我想知道是否可以創建一個可以保留的進程並傳遞給其他函數,這些函數會自己寫入並從中讀取。作爲@ n.m。然而,指出,這是行不通的。非常感謝。 –