2011-07-18 14 views
15

Me gustaría tener algo como bash's 2>&1 redirigir en Haskell que combina stdout y stderr desde un proceso en un solo Handle. Sería bueno hacerlo directamente con System.Process.createProcess o una función de biblioteca similar, particularmente si usa la misma semántica que la redirección bash w.r.t. entrelazado de entrada de los controladores.¿Cómo puedo combinar Handles en Haskell?

La flexibilidad ofrecida por createProcess parece prometedor en un primer momento: se puede especificar un Handle a utilizar para los descriptores de fichero estándar, por lo que la misma Handle podría darse tanto para stdout y stderr. Sin embargo, los argumentos Handle ya deben existir antes de la llamada. Sin la capacidad de crear un Handle desde el aire antes de llamar a la función, no estoy seguro de que el problema se pueda resolver de esta manera.

Editar: La solución debe funcionar independientemente de la plataforma.

+1

¿Es necesario un enfoque multiplataforma? ¿O solo se ejecutará en un sistema unix-y? –

+0

@camccann Sí; actualizado la pregunta en consecuencia. – acfoltzer

+1

Bueno, [aquí está la respuesta que habría conseguido] (http://hackage.haskell.org/packages/archive/unix/2.4.2.0/doc/html/System-Posix-IO.html) en caso contrario. Técnicamente esto funciona si tienes una capa de compatibilidad como cygwin, pero eso es ... eugh. –

Respuesta

3

De here:

import GHC.IO.Handle -- yes, it's GHC-specific 
import System.IO 

main = do 
    stdout_excl <- hDuplicate stdout 
    hDuplicateTo stderr stdout -- redirect stdout to stderr 

    putStrLn "Hello stderr" -- will print to stderr 
    hPutStrLn stdout_excl "Hello stdout" -- prints to stdout 
+0

¡Genial! Probablemente me perdí esto debido a la biblioteca específica de GHC – acfoltzer

4

conseguir sus manos en un Handle no es demasiado difícil: System.IO ofrece constantes y funciones stdin,stdout,stderr :: HandlewithFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r y openFile :: FilePath -> IOMode -> IO Handle.

Como alternativa, podría solicitar nuevas tuberías de createProcess y establecerse como un servicio de reenvío (lectura de los nuevos stdout y stderr mangos de su hijo y enviar tanto a donde quiera que te gusta).

2

Dado que Windows admite pipe (3) de forma nativa y la biblioteca IO de GHC uses CRT file descriptors internally on Windows, es posible encontrar una solución que funcione tanto en Windows como * nix al menos. El algoritmo básico es:

  • Llamada pipe. Esto le da dos descriptores de archivo que puede convertir a Handles con fdToHandle'.
  • llamada createProcess con stdout y stderr establecen en extremo de escritura de la tubería.
  • Lectura de salida infantil desde el extremo de lectura de la tubería.

El módulo System.Posix.Internals, que exporta c_pipe, se oculta de forma predeterminada, pero se puede compilar una versión personalizada de base que le permite acceder a él (consejo: utilizar cabal-dev). Alternativamente, puede acceder al pipe a través de FFI. NB: esta solución es específica de GHC.

+0

Esto parece ser la forma en que debería implementarse, gracias. Voy a experimentar con lo portátil que puede ser este enfoque. – acfoltzer

+0

@acfoltzer ¿Puede decirnos sus resultados? – nh2

+0

@ nh2 terminamos cojeando junto con la solución bash, por desgracia. Sería bueno volver a visitar esto en algún momento, aunque – acfoltzer

Cuestiones relacionadas