私は起動が必要な長い実行プロセスがあります。 起動には数秒かかり、ログはstdoutに出力されます。Haskell:長期間にわたるプロセスを静かに開始し、stdoutをキャプチャします
私はしたいと思います:プロセスからのstdoutが私のセッションで表示されないように
-
は、黙ってプロセスを開始
- 。
- 出力がストリームとしてキャプチャされ、準備ができていると判断できるようになります。
- プロセスのハンドルがあるので、後でプロセスを停止できます。
Shelly、Turtle、およびSystem.Processを使用して近づいてきましたが、標準出力をキャプチャできません。私が持っていたSystem.Process使用
:
import Control.Concurrent (threadDelay)
import Control.Concurrent.Async (race)
import System.IO
import System.Process
startService :: IO ProcessHandle
startService = do
let cmd = "./my-service"
args = [ "-p 1234" ]
(_, Just hout, _, p) <- createProcess $ (proc cmd args) { std_out = CreatePipe }
started <- either id id <$> race (checkStarted hout) timeOut
unless started $ fail "Service not started"
pure p
where
checkStarted :: Handle -> IO Bool
checkStarted h = do
str <- hGetLine h
-- check str for started log, else loop
timeOut :: IO Bool
timeOut = do
threadDelay 10000000
pure False
しかしハンドラhout
はレディ状態ではなかったです。シェリーを使用して
は私が持っていた:
import Control.Concurrent (threadDelay)
import Control.Concurrent.Async (race)
import Control.Concurrent.MVar
import Shelly
import System.IO
startService :: IO (Async())
startService = do
let cmd = "./my-service"
args = [ "-p 1234" ]
startedMVar <- newEmptyMVar
async <- shelly $ asyncSh $ runHandle cmd args $ recordWhenStarted startedMVar
started <- either id id <$> race (readMVar startedMVar) timeOut
unless started $ fail "Service not started"
pure async
where
recordWhenStarted :: MVar Bool -> Text -> IO()
recordWhenStarted mvar txt =
when (isStartedLog txt) $
modifyMVar_ mvar (const $ pure True)
timeOut :: IO Bool
timeOut = do
threadDelay 10000000
pure False
しかしrecordWhenStarted
が呼び出されることはありません。
あなたが今までに書いたコードと動作しないコードを含めてください。 – thoferon
'checkStarted h = True <$ hGetLine h'を定義し、' './my-service''を' 'yes ''に置き換えることで、最初のバージョンを動作させることができます。 '純粋な(hout、p)'を持つ)。私はそれが働いていない理由はあなたのハスケルコードではなく、 'my-service'と関係していると思います。 – user2407038
端末では、私は 'my-service'をstdoutを運行なしのファイルにリダイレクトしようとしました。 ログ出力がstderrを介して生成されているので、なぜ私のコードが動作しませんでしたか – tmortiboy