I am trying to spawn a process from within a Haskell program, and I would like to print its standard error stream to the screen while also writing the same stream to a file, much like what the tee
command achieves.
I can print the standard error stream:
import Data.Conduit ((.|), runConduit)
import qualified Data.Conduit.List as CL
import Data.Conduit.Process
main :: IO ()
main = do
(ClosedStream, ClosedStream, err, sph) <- streamingProcess (shell myCommand)
runConduit $ err .| CL.mapM_ print
And I can direct the stream to a file:
import System.IO (withFile, IOMode (..))
import Data.Conduit.Process
main :: IO ()
main = do
let logFile = "myCommand.log"
withFile logFile WriteMode $ \h -> do
(ClosedStream, ClosedStream, UseProvidedHandle, sph) <-
streamingProcess (shell myCommand) {std_err = UseHandle h}
How can I do both simultaneously?
One approach is to use the conduitFile
function:
#!/usr/bin/env stack
-- stack --resolver lts-10.3 script
import Conduit
import Data.Conduit.Process
import Data.Conduit.Binary (conduitFile)
main :: IO ()
main = do
(ClosedStream, out, ClosedStream, ph) <-
streamingProcess (shell "cat /etc/passwd")
runConduitRes $ out .| conduitFile "myCommand.log" .| printC
Another is to use ZipSink
to consume the stream in two different ways at once:
#!/usr/bin/env stack
-- stack --resolver lts-10.3 script
import Conduit
import Data.Conduit.Process
main :: IO ()
main = do
(ClosedStream, out, ClosedStream, ph) <-
streamingProcess (shell "cat /etc/passwd")
runConduitRes $ out .| getZipSink (
ZipSink (sinkFile "myCommand.log") *>
ZipSink printC)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With