感谢hammar,我开始在Windows上运行作业管理服务器。目的是unix-side守护进程将向windows端发送命令并从windows端接收stderr / stdout。问题是,我无法让Windows端服务器在Windows端打印到stderr / stdout,也不能将流发送到连接到unix端的句柄(现在使用telnet客户端)。
这是我的尝试。我在这个例子中只使用了stdout,但stdout和stderr都不起作用。 runJob是我正在尝试的IO动作。我希望能解决这个问题。
编辑:我运行了一个haskell测试脚本来代替.bat文件,它捕获了stdout / stderr。下面我包括批处理文件。令我困惑的是,当我手动运行批处理文件时,它会生成stdout和stderr到屏幕。无法弄清楚发生了什么。也许我应该用haskell脚本替换批处理文件。
> import Network.Socket
> import Control.Monad
> import Network
> import System.Environment (getArgs)
> import System.Process
> import System.IO
> import Control.Concurrent (forkIO)
> import Control.Exception (bracket)
> import Data.Maybe
> main :: IO ()
> main = withSocketsDo $ do
> putStrLn ("up top\n")
> [port] <- getArgs
> bracket (prepareSocket (fromIntegral $ read port))
> sClose
> acceptConnections
> prepareSocket :: PortNumber -> IO Socket
> prepareSocket port = do
> sock <- socket AF_INET Stream defaultProtocol
> let socketAddress = SockAddrInet port 0000
> bindSocket sock socketAddress
> listen sock 1
> putStrLn $ "Listening on " ++ (show port)
> return sock
> acceptConnections :: Socket -> IO ()
> acceptConnections sock' = do
> forever $ do
> (sock, sockAddr) <- Network.Socket.accept sock'
> handle <- socketToHandle sock ReadWriteMode
> sockHandler sock handle
> sockHandler :: Socket -> Handle -> IO ()
> sockHandler sock' handle = do
> hSetBuffering handle LineBuffering
> -- Add the forkIO back if you want to allow concurrent connections.
> {- forkIO $ -}
> commandProcessor handle
> return ()
> commandProcessor :: Handle -> IO ()
> commandProcessor handle = untilM (hIsEOF handle) handleCommand >> hClose handle
> where
> handleCommand = do
> line <- hGetLine handle
> let (cmd:arg) = words line
> case cmd of
> "echo" -> echoCommand handle arg
> "runjob" -> runJob handle arg
> _ -> do hPutStrLn handle "Unknown command"
> echoCommand :: Handle -> [String] -> IO ()
> echoCommand handle arg = do
> hPutStrLn handle (unwords arg)
> runJob :: Handle -> [String] -> IO ()
> runJob handle jobNumber = do
>
> -- let batchDirectory = "fookit"
> (_, Just hout, Just herr, jHandle) <-
> createProcess (proc testJob []) { cwd = Just batchDirectory,
> std_out = CreatePipe,
> std_err = CreatePipe }
> stdOUT <- hGetLine herr
> hPutStrLn stdout stdOUT
> hPutStrLn handle stdOUT
> exitCode <- waitForProcess jHandle
> -- stdErr <- hShow hout
> --hPutStrLn handle stdOUT
> return ()
> batchDirectory = "C:\\Users\\ixia\\Documents"
> testJob = "C:\\Users\\ixia\\Documents\\680batch.bat"
> untilM cond action = do
> b <- cond
> if b
> then return ()
> else action >> untilM cond action
这是我提到的批处理文件。它执行手动运行时的预期
“C:\ Program Files(x86)\ Ixia \ Tcl \ 8.4.14.0 \ bin \ tclsh.exe”680template.tcl
答案 0 :(得分:3)
让我们尝试通过消除所有网络代码来缩小范围并使其更容易测试,因为它实际上与捕获进程的输出无关。这是从您的代码中提取的一个小测试程序。
import System.IO
import System.Process
main = do
(_, Just hout, Just herr, jHandle) <-
-- Replace with some other command on Windows
createProcess (proc "/bin/date" [])
{ cwd = Just "."
, std_out = CreatePipe
, std_err = CreatePipe
}
putStrLn "First line of stdout:"
hGetLine hout >>= putStrLn
exitCode <- waitForProcess jHandle
putStrLn $ "Exit code: " ++ show exitCode
至少可以在Ubuntu上按预期工作。 (目前我附近没有Windows框。)
$ runghc RunJob.hs
First line of stdout:
Wed Sep 28 22:28:37 CEST 2011
Exit code: ExitSuccess
我首先要测试一下这适用于你的工作。那应该会给你一些如何从那里开始的线索。