首页 > 解决方案 > System.Process 如何保持 shell 会话而不是创建新进程?

问题描述

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”。

有什么比解析命令更好的吗?

标签: haskell

解决方案


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

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

您启动一个 shell 并将一个管道连接到它的输入流和一个管道连接到它的输出流。现在您可以向其输入流发送命令,并通过连接的管道从其输出流中读取响应。

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

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


推荐阅读