Skip to content

Instantly share code, notes, and snippets.

@quasi-coherent
Last active November 27, 2018 23:05
Show Gist options
  • Save quasi-coherent/2aac1e36284928655c97130fa83432cd to your computer and use it in GitHub Desktop.
Save quasi-coherent/2aac1e36284928655c97130fa83432cd to your computer and use it in GitHub Desktop.
Stream to port example
#!/usr/bin/env stack
-- stack --resolver lts-12.7 script
import Conduit hiding (connect)
import qualified Data.Conduit.Binary as CB
import qualified Data.Conduit.Network as CN
import qualified Data.Conduit.Process as CP
import qualified Data.Text as T
import Network.Socket
import System.Directory
import System.Environment
import System.Exit
main :: IO ()
main = do
let cmd = "echo asdfasdfasdf"
code <- teeSock 8989 cmd "test.log"
putStrLn . show $ code
teeSock :: Int -- ^ Port to bind to on localhost.
-> String
-> FilePath
-> IO ExitCode
teeSock port cmd logFile = do
(sock, addr) <- getSocket "127.0.0.1" (show port)
connect sock $ addrAddress addr
(CP.Inherited, out, CP.ClosedStream, sph) <- execShellCommand cmd
runConduitRes $ out .| CN.sinkSocket sock
-- .| CB.conduitFile logFile
-- .| stdoutC
CP.waitForStreamingProcess sph
execShellCommand
:: (CP.InputSource stdin, CP.OutputSink stdout, CP.OutputSink stderr)
=> String
-> IO (stdin, stdout, stderr, CP.StreamingProcessHandle)
execShellCommand cmd = do
sourceProfile <- sourceProfileIfExists
env' <- getEnvironment
CP.streamingProcess (CP.shell $ sourceProfile ++ cmd ++ " 2>&1") {CP.env = Just env'}
sourceProfileIfExists :: IO String
sourceProfileIfExists = getEnv "HOME" >>= \root ->
doesFileExist (root ++ "/.profile") >>= \exists -> return $
if exists then "source ~/.profile; " else ""
getSocket :: String -> String -> IO (Socket, AddrInfo)
getSocket host port = do
addr:_ <- getAddrInfo Nothing (Just host) (Just port)
sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
return (sock, addr)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment