Как я могу комбинировать ручки в Haskell? - PullRequest
15 голосов
/ 18 июля 2011

Мне бы хотелось иметь что-то вроде перенаправления bash 2>&1 в Haskell, которое объединяет stdout и stderr из процесса в один Handle.Было бы неплохо сделать это напрямую с System.Process.createProcess или подобной библиотечной функцией, особенно если она использовала ту же семантику, что и перенаправление bash с чередованием ввода с дескрипторов.

Кажется, что createProcess обеспечивает гибкостьобещая сначала: можно указать Handle для стандартных дескрипторов файлов, поэтому для 1011 * и stderr может быть задано одинаковое Handle.Однако аргументы Handle должны существовать до вызова.Без возможности создания Handle из воздуха перед вызовом функции, я не уверен, что проблему можно решить таким образом.

Редактировать: Решение должно работать независимоплатформы.

Ответы [ 3 ]

4 голосов
/ 19 июля 2011

Захватить Handle не так уж сложно: System.IO предлагает константы stdin,stdout,stderr :: Handle и функции withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r и openFile :: FilePath -> IOMode -> IO Handle.

Кроме того, вы можете запросить новые каналы у createProcess и настроить себя в качестве службы переадресации (чтение из новых дескрипторов stdout и stderr вашего ребенка и отправка обоих в любое удобное место).

3 голосов
/ 02 августа 2012

С здесь :

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
2 голосов
/ 19 июля 2011

Поскольку Windows изначально поддерживает pipe (3), а библиотека ввода-вывода GHC использует дескрипторы файлов CRT внутри Windows , можно предложить решение, которое работает как в Windows, так и *по крайней мере.Основной алгоритм:

  • Вызов pipe.Это дает вам два файловых дескриптора, которые можно преобразовать в Handles с fdToHandle'.
  • Вызов createProcess с stdout и stderr, оба установлены в конец записи канала.
  • Чтение дочернего вывода с конца чтения канала.

Модуль System.Posix.Internals, который экспортирует c_pipe, по умолчанию скрыт, но выМожно скомпилировать пользовательскую версию base, которая позволит вам получить к ней доступ (совет: используйте cabal-dev ).Кроме того, вы можете получить доступ к pipe через FFI. Примечание: это решение зависит от GHC.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...