Module Subprocess.StringResults

The StringResults module presents an interface similar to the functions in the Results module, but the output is wrapped in a result type, where a non-zere exit status becomes Error of string. string is perhaps less useful than Exit.t but it composes better. Core is included here to avoid having to open both Subprocess and StringResults.

val exec : ('stdin, 'stdout, 'stderr) Core.Cmd.t -> f:(('stdin, 'stdout, 'stderr) Core.t -> 'a) -> ('a, string) Stdlib.result

Execute a command in, where a handle to the created process will be availbe as the sole input parameter of the function f. When f exits, we close any "dangling" file descriptors and wait for the process to exit, finally returning the output value of f wrapped in the output type.

val exec_joined : ('stdin, Core.stdout, Core.stderr) Core.Cmd.t -> f:(('stdin, Core.pipe, Core.stdout) Core.t -> 'a) -> ('a, string) Stdlib.result

Same as exec, but stdout and stderr are redirected to the same pipe. This is similar to 2>&1 | in the shell.

val run : ('stdin, 'stdout, 'stderr) Core.Cmd.t -> (unit, string) Stdlib.result

Execute the command and wait for it to exit, returning () wrapped in the output type.

val write : (Core.stdin, 'stdout, 'stderr) Core.Cmd.t -> input:string -> (unit, string) Stdlib.result

Execute the command and write the input string to the stdin of the process.

val write_lines : (Core.stdin, 'stdout, 'stderr) Core.Cmd.t -> input:string Stdlib.Seq.t -> (unit, string) Stdlib.result

Execute the command and write the input Seq.t instance to the stdin of the process, separated by newline characters. If you want to read from stdout while writing, use fold_with.

val read : ('stdin, Core.stdout, 'stderr) Core.Cmd.t -> (string, string) Stdlib.result

Execute the command and read its stdout into a string wrapped in the output type.

val lines : ('stdin, Core.stdout, 'stderr) Core.Cmd.t -> (string list, string) Stdlib.result

Same as read but with a list of lines wrapped in the output type.

val read_err : ('stdin, 'stdout, Core.stderr) Core.Cmd.t -> (string, string) Stdlib.result

Same as read, but reads stderr rather than stdout.

val lines_err : ('stdin, 'stdout, Core.stderr) Core.Cmd.t -> (string list, string) Stdlib.result

Same as lines, but reads stderr rather than stdout.

val read_joined : ('stdin, Core.stdout, Core.stderr) Core.Cmd.t -> (string, string) Stdlib.result

Same as read but reads stdout and stderr as a single stream.

val lines_joined : ('stdin, Core.stdout, Core.stderr) Core.Cmd.t -> (string list, string) Stdlib.result

Same as lines but reads stdout and stderr as a single stream.

val read_both : ?sleep:float -> ('stdin, Core.stdout, Core.stderr) Core.Cmd.t -> (string * string, string) Stdlib.result

Same as read_joined but reads stdout and stderr as a separate strings streams, returning a pair of strings wrapped in the ouput type. This function uses asynchronous I/O internally, so the optional sleep parameter is provided as a means to pause briefly if output is expected to be slow to avoid pegging the CPU with a loop that does nothing.

val lines_both : ?sleep:float -> ('stdin, Core.stdout, Core.stderr) Core.Cmd.t -> (string list * string list, string) Stdlib.result

Same as lines_joined but reads stdout and stderr as a separate strings streams, returning a pair of string lists wrapped in the ouput type. This function uses asynchronous I/O internally, so the optional sleep parameter is provided as a means to pause briefly if output is expected to be slow to avoid pegging the CPU with a loop that does nothing.

val fold : ('stdin, Core.stdout, 'stderr) Core.Cmd.t -> f:('acc -> string -> 'acc) -> init:'acc -> ('acc, string) Stdlib.result

Execute the command. Do a left fold over the lines of output from the processe's stdout. Wraps the accumulated output in the output type.

val fold_err : ('stdin, 'stdout, Core.stderr) Core.Cmd.t -> f:('acc -> string -> 'acc) -> init:'acc -> ('acc, string) Stdlib.result

Same as fold, but fold over lines from stderr.

val fold_joined : ('stdin, Core.stdout, Core.stderr) Core.Cmd.t -> f:('acc -> string -> 'acc) -> init:'acc -> ('acc, string) Stdlib.result

Same as fold, but joins stdout and stderr into a single stream.

val fold_both : ?sleep:float -> ('stdin, Core.stdout, Core.stderr) Core.Cmd.t -> f:('acc -> (string, string) Stdlib.result -> 'acc) -> init:'acc -> ('acc, string) Stdlib.result

Same as fold_joined, but wraps each line of stdin in Ok and lines of stderr in Error so they can be distinguished. This function uses asynchronous I/O internally, so the optional sleep parameter is provided as a means to pause briefly if output is expected to be slow to avoid pegging the CPU with a loop that does nothing.

val fold_with : ?sleep:float -> ?sep:string -> (Core.stdin, Core.stdout, 'stderr) Core.Cmd.t -> lines:string Stdlib.Seq.t -> f:('acc -> string -> 'acc) -> init:'acc -> ('acc, string) Stdlib.result

Execute the command. Feed items from lines to the process stdin, which will be separated with a newline character by default. Use the optional sep parameter to change this to another string. While all that is happening, fold over lines from stdout. This function uses asynchronous I/O internally, so the optional sleep parameter is provided as a means to pause briefly if output is expected to be slow to avoid pegging the CPU with a loop that does nothing.

val bind : ('stdin, 'stdout, 'stderr) Cmd.t -> f:(('stdin, 'stdout, 'stderr) t -> ('a, string) Stdlib.result) -> ('a, string) Stdlib.result

Similar to exec, but composes better for monadic binding.

val bind_joined : ('stdin, stdout, stderr) Cmd.t -> f:(('stdin, pipe, stdout) t -> ('a, string) Stdlib.result) -> ('a, string) Stdlib.result

Similar to exec_joined, but composes better for monadic binding.

val (let*) : ('a, 'b) Stdlib.result -> ('a -> ('c, 'b) Stdlib.result) -> ('c, 'b) Stdlib.result

Just an alias for Stdlib.Result.bind. If you like monads, you know what to do.

val (let&) : ('stdin, 'stderr, 'stdout) Cmd.t -> (('stdin, 'stderr, 'stdout) t -> ('a, string) Stdlib.result) -> ('a, string) Stdlib.result

Same as bind, but as a binding operator for monad funtimes.

include module type of Core
type stdin = Core.stdin
type stdout = Core.stdout
type stderr = Core.stderr
type channel = Core.channel
type devnull = Core.devnull
type file = Core.file
type append = Core.append
type pipe = Core.pipe
exception Subprocess_error of string

When the library raises, it always raises a Subprocess_error of string.

module Cmd = Core.Cmd

home of Cmd.t, which is kind of the whole basis of the thing.

module Exit = Core.Exit

types for exit status with lots of extra info for fun and profit.

In and Out are I/O wrappers for process streams. It's thanks to these bad boys we can have such verbose types.

module In = Core.In
module Out = Core.Out
type ('stdin, 'stdout, 'stderr) t = ('stdin, 'stdout, 'stderr) Core.t = {
  1. pid : int;
  2. cmd : ('stdin, 'stdout, 'stderr) Cmd.t;
  3. stdin : 'stdin In.t;
  4. stdout : 'stdout Out.t;
  5. stderr : 'stderr Out.t;
  6. close : ?mode:Unix.wait_flag list -> unit -> Exit.t;
}

The type t represents a process which may still be running. Some of the higher-level functions don't expose it directly, but almost everything else is implemented in terms of this type.

Apply () to the close property to close any managed file descriptors and wait for the process to exit.

val pp : Stdlib.Format.formatter -> ('stdin, 'stdout, 'stderr) t -> unit

Obligatory pretty printer, for your debugging pleasure.

val show : ('stdin, 'stdout, 'stderr) t -> string

What follows are some helper functions which fetch pipes to a running process for interactive reading and writting. They shadow channels with the same names in the standard library. Probably a good reason to only open Subprocess within a limited scope.

If you try to use one of these functions to access a stream which isn't a pipe, it's a type error.

val stdin : (pipe, 'stdout, 'stderr) t -> Stdlib.out_channel
val stdout : ('stdin, pipe, 'stderr) t -> Stdlib.in_channel
val stderr : ('stdin, 'stdout, pipe) t -> Stdlib.in_channel
val wait : ?mode:Unix.wait_flag list -> ('stdin, 'stdout, 'stderr) t -> int * Exit.status

Teeny, tiny, leaky wrapper for Unix.waitpid refer to its documentation

val poll : ('stdin, 'stdout, 'stderr) t -> Exit.status option

Find out if your process has finished executing.

val cmd : ?prog:string -> ?env:string list -> ?block:bool -> string list -> (stdin, stdout, stderr) Cmd.t

Helper funtions for constructing Cmd.t. The optional prog argument is mainly for if you don't want your path to be searched for the executable.

env is a list of strings with the format "NAME=value". block may be set to false for non-blocking I/O on pipes. This one setting is used with any pipes which are used for I/O. Remember to catch Sys_blocked_io when doing I/O with any non-blocking pipes.

Both env and block can also be set with combinators.

val pipe_in : (stdin, 'stdout, 'stderr) Cmd.t -> (pipe, 'stdout, 'stderr) Cmd.t

redirect stdin to a pipe for writing.

val pipe_out : ('stdin, stdout, 'stderr) Cmd.t -> ('stdin, pipe, 'stderr) Cmd.t

redirect stdout to a pipe for reading.

val pipe_err : ('stdin, 'stdout, stderr) Cmd.t -> ('stdin, 'stdout, pipe) Cmd.t

redirect stdout to a pipe for writing.

val channel_in : Stdlib.in_channel -> (stdin, 'stdout, 'stderr) Cmd.t -> (channel, 'stdout, 'stderr) Cmd.t

redirect stdin to an in_channel.

val channel_out : Stdlib.out_channel -> ('stdin, stdout, 'stderr) Cmd.t -> ('stdin, channel, 'stderr) Cmd.t

redirect stdout to an out_channel.

val channel_err : Stdlib.out_channel -> ('stdin, 'stdout, stderr) Cmd.t -> ('stdin, 'stdout, channel) Cmd.t

redirect stderr to an out_channel.

val file_in : string -> (stdin, 'stdout, 'stderr) Cmd.t -> (file, 'stdout, 'stderr) Cmd.t

redirect stdin to an named file. Similar to < in the shell.

val file_out : string -> ('stdin, stdout, 'stderr) Cmd.t -> ('stdin, file, 'stderr) Cmd.t

redirect stdout to an named file. Similar to > in the shell.

val file_err : string -> ('stdin, 'stdout, stderr) Cmd.t -> ('stdin, 'stdout, file) Cmd.t

redirect stderr to an named file. Similar to 2> in the shell.

val append_out : string -> ('stdin, stdout, 'stderr) Cmd.t -> ('stdin, append, 'stderr) Cmd.t

redirect stdout to an named file for appending. Similar to >> in the shell.

val append_err : string -> ('stdin, 'stdout, stderr) Cmd.t -> ('stdin, 'stdout, append) Cmd.t

redirect stderr to an named file for appending. Similar to 2>> in the shell.

val devnull_out : ('stdin, stdout, 'stderr) Cmd.t -> ('stdin, devnull, 'stderr) Cmd.t

redirect stdout to /dev/null. similar to > /dev/null in the shell

val devnull_err : ('stdin, 'stdout, stderr) Cmd.t -> ('stdin, 'stdout, devnull) Cmd.t

redirect stderr to /dev/null. similar to 2> /dev/null in the shell

val env : string list -> ('stdin, 'stdout, 'stderr) Cmd.t -> ('stdin, 'stdout, 'stderr) Cmd.t

Set additional environment variables. Variables are passed in as a list of strings with the format "NAME=value".

val no_block : ('stdin, 'stdout, 'stderr) Cmd.t -> ('stdin, 'stdout, 'stderr) Cmd.t

Use non-blocking I/O on any pipes. When doing I/O with any such channel, you must catch Sys_blocked_io in the event no data is ready for reading.