Haskell Conduit из процесса захвата как stdout, так и stderr

Существует ли канал Haskell, который может выполнять процесс и захватывать его потоки stderr и stdout (отдельно)? Возможность передать stdin в процесс была бы идеальной, поскольку канал тоже был бы идеальным, но не требованием (для этого я могу использовать файл).


person luispedro    schedule 11.11.2015    source источник


Ответы (1)


Вот пример из статьи школы Haskell Данные .Conduit.Process:

{-# LANGUAGE OverloadedStrings #-}
import           Control.Applicative      ((*>))
import           Control.Concurrent.Async (Concurrently (..))
import           Data.Conduit             (await, yield, ($$), (=$))
import qualified Data.Conduit.Binary      as CB
import qualified Data.Conduit.List        as CL
import           Data.Conduit.Process     (ClosedStream (..), streamingProcess,
                                           proc, waitForStreamingProcess)
import           System.IO                (stdin)

main :: IO ()
main = do
    putStrLn "Enter lines of data. I'll run ./base64-perl on it."
    putStrLn "Enter \"quit\" to exit."

    ((toProcess, close), fromProcess, fromStderr, cph) <-
        streamingProcess (proc "./base64-perl" [])

    let input = CB.sourceHandle stdin
             $$ CB.lines
             =$ inputLoop
             =$ toProcess

        inputLoop = do
            mbs <- await
            case mbs of
                Nothing -> close
                Just "quit" -> close
                Just bs -> do
                    yield bs
                    inputLoop

        output = fromProcess $$ CL.mapM_
            (\bs -> putStrLn $ "from process: " ++ show bs)

        errout = fromStderr $$ CL.mapM_
            (\bs -> putStrLn $ "from stderr: " ++ show bs)

    ec <- runConcurrently $
        Concurrently input *>
        Concurrently output *>
        Concurrently errout *>
        Concurrently (waitForStreamingProcess cph)

    putStrLn $ "Process exit code: " ++ show ec

В основном это пример в статье с добавленным потоком для обработки stderr.

Он вызывает эту программу Perl, которая выводит вывод как на стандартный вывод, так и на стандартный вывод:

#!/usr/bin/env perl

use strict;
use warnings;
use MIME::Base64;

$| = 1;

my $timeout = 3;
my $buf = "";
while (1) {
  my $rin = '';
  vec($rin, fileno(STDIN), 1) = 1;
  my ($nfound) = select($rin, undef, undef, $timeout);
  if ($nfound) {
    my $nread = sysread(STDIN, $buf, 4096, length($buf));
    last if $nread <= 0;
    print encode_base64($buf);
    $buf = "";
  } else {
    print STDERR "this is from stderr\n";
  }
}
person ErikR    schedule 11.11.2015