System.Process如何保留Shell会话而不是创建新进程?

时间:2018-11-12 09:05:18

标签: haskell

import System.Process

createProcess (shell "pwd") -- /Users/username/current-directory    
createProcess (shell "cd app") -- LOST
createProcess (shell "pwd") -- /Users/username/current-directory

很显然,createProcess (shell "cd app")在下一个过程中不是持久的。

但是,如何保持会话的持久性?

我知道我可以通过cwd,但是

createProcess (shell "mkdir some-dir && cd some-dir")
createProcess (shell "pwd") { cwd = Just "some-dir" } 

但是,我必须解析前面的命令以获取“ some-dir”。

有比解析命令更好的东西吗?

2 个答案:

答案 0 :(得分:2)

首先是一个工作代码示例:

module Main where

import System.Process
import System.IO

ourShell :: CreateProcess
ourShell =  (proc "/bin/bash" []) { std_in = CreatePipe, std_out = CreatePipe }

main = do
  (Just bashIn, Just bashOut, Nothing, bashHandle) <- createProcess ourShell

  hSetBuffering bashIn NoBuffering
  hSetBuffering bashOut NoBuffering

  print "Sending pwd"
  hPutStrLn bashIn "pwd"
  print "reading response"
  hGetLine bashOut >>= print

  print "Sending cd test"
  hPutStrLn bashIn "cd test"
  print "reading response"
--  hGetLine bashOut >>= print you need to know there is no answer ....

  print "Sending pwd"
  hPutStrLn bashIn "pwd"
  print "reading response"
  hGetLine bashOut >>= print

  hPutStrLn bashIn "exit"
  hGetContents bashOut >>= print
  ec <- waitForProcess bashHandle
  print ec

这会在我的计算机上以/tmp的现有/tmp/test输出:

"Sending pwd"
"reading response"
"/tmp"
"Sending cd test"
"reading response"
"Sending pwd"
"reading response"
"/tmp/test"
""
ExitSuccess

启动外壳程序,然后将管道连接到其输入流,并将管道连接到其输出流。现在,您可以将命令发送到其输入流,并通过连接的管道读取其输出流的响应。

但是现在您需要一个协议,因此您知道哪个输出属于哪个命令。因此,您需要知道例如将为哪个输出生成多少条输出线。例如,如果您尝试读取cd test命令的响应,则程序将挂起,因为没有任何输出。

还有其他方法可以解决此问题,但是它们都涉及某种启发式方法,超出了问题的范围。

答案 1 :(得分:1)

您不能使用外部程序来更改 current 程序的当前目录。那只是行不通的。

因此,cd是Shell内置的运算符,而不是外部程序。 (至少,这就是Unix的工作方式。我对Windows并非100%肯定。)

尝试改用setCurrentDirectory。那应该允许您更改Haskell程序的当前目录,该目录将在程序的其余运行期间保持永久(或直到您再次更改它)。