2011-07-18 29 views
15

Tôi muốn có một cái gì đó như bash's 2>&1 chuyển hướng trong Haskell kết hợp stdoutstderr từ một quá trình vào một đơn Handle. Nó sẽ là tốt đẹp để làm điều này trực tiếp với System.Process.createProcess hoặc một chức năng thư viện tương tự, đặc biệt nếu nó được sử dụng cùng một ngữ nghĩa như chuyển hướng bash w.r.t. xen kẽ đầu vào từ tay cầm.Làm cách nào để kết hợp Handles trong Haskell?

Sự linh hoạt được cung cấp bởi createProcess dường như hứa hẹn ban đầu: người ta có thể chỉ định một Handle để sử dụng cho các file descriptor tiêu chuẩn, do cùng Handle có thể được trao cho cả stdoutstderr. Tuy nhiên, đối số Handle phải tồn tại trước cuộc gọi. Không có khả năng để tạo ra một Handle từ không khí mỏng trước khi gọi chức năng, tôi không chắc chắn vấn đề có thể được giải quyết theo cách này.

Chỉnh sửa: Giải pháp cần phải hoạt động bất kể nền tảng.

+1

Bạn có cần một cách tiếp cận đa nền tảng? Hoặc điều này sẽ chỉ chạy trên một hệ thống unix-y? –

+0

@camccann Yep; đã cập nhật câu hỏi cho phù hợp. – acfoltzer

+1

Vâng, [đây là câu trả lời bạn sẽ nhận được] (http://hackage.haskell.org/packages/archive/unix/2.4.2.0/doc/html/System-Posix-IO.html) nếu không. Về mặt kỹ thuật, nó hoạt động nếu bạn có một lớp tương thích như Cygwin, nhưng đó là ... eugh. –

Trả lời

3

Từ 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

Tuyệt vời! Có lẽ tôi đã bỏ lỡ điều này vì thư viện đặc thù của GHC – acfoltzer

4

Bắt tay của bạn trên một Handle không phải là quá khó: System.IO cung cấp hằng stdin,stdout,stderr :: Handle và chức năng withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO ropenFile :: FilePath -> IOMode -> IO Handle.

Cách khác, bạn có thể yêu cầu các đường ống mới từ createProcess và đặt bản thân làm dịch vụ chuyển tiếp (đọc từ số mới stdoutstderr xử lý con của bạn và gửi đến bất cứ nơi nào bạn muốn).

2

Vì Windows hỗ trợ pipe (3) nguyên bản và thư viện IO của GHC uses CRT file descriptors internally on Windows, có thể đưa ra giải pháp hoạt động trên cả Windows và * nix ít nhất. Thuật toán cơ bản là:

  • Gọi pipe. Điều này cung cấp cho bạn hai bộ mô tả tệp mà bạn có thể chuyển đổi thành Handles với fdToHandle'.
  • Gọi createProcess với stdoutstderr cả hai được đặt thành đầu ghi của đường ống.
  • Đọc kết quả đầu ra của trẻ từ đầu đọc của ống.

Module System.Posix.Internals, trong đó xuất khẩu c_pipe, được ẩn theo mặc định, nhưng bạn có thể biên dịch một phiên bản tùy chỉnh của base cho phép bạn truy cập vào nó (tip: sử dụng cabal-dev). Ngoài ra, bạn có thể truy cập pipe qua FFI. NB: giải pháp này là GHC cụ thể.

+0

Điều này có vẻ giống như cách nó nên được thực hiện, cảm ơn. Tôi sẽ thử nghiệm với cách tiếp cận di động này có thể được. – acfoltzer

+0

@acfoltzer Bạn có thể cho chúng tôi biết kết quả của bạn không? – nh2

+0

@ nh2 chúng tôi vết thương lên cùng với giải pháp bash, thật đáng buồn. Nó sẽ là tốt đẹp để xem lại điều này tại một số điểm, mặc dù – acfoltzer

Các vấn đề liên quan