porcelain v2.0.3 Porcelain

The main module exposing the public API of Porcelain.

Basic concepts

Functions in this module can either spawn external programs directly (exec/3 and spawn/3 or using a system shell (shell/2 and spawn_shell/2.

Functions exec/3 and shell/2 are synchronous (or blocking), meaning they don’t return until the external program terminates.

Functions spawn/3 and spawn_shell/2 are non-blocking: they immediately return a Porcelain.Process struct and use one of the available ways to exchange input and output with the external process asynchronously.

Error handling

Using undefined options, passing invalid values to options or any function arguments will fail with a function clause error or Porcelain.UsageError exception. Those are programmer errors and have to be fixed.

Any other kinds of runtime errors are reported by returning an error tuple: {:error, <reason>} where <reason> is a string explaining the error.

Summary

Functions

Execute a program synchronously

Reruns the initialization and updates application env

Execute a shell invocation synchronously

Spawn an external process and return a Porcelain.Process struct to be able to communicate with it

Spawn a system shell and execute the command in it

Functions

exec(prog, args, options \\ [])

Specs

exec(binary, [binary], Keyword.t) :: Porcelain.Result.t

Execute a program synchronously.

Porcelain will look for the program in PATH and launch it directly, passing the args list as command-line arguments to it.

Feeds all input into the program (synchronously or concurrently with reading output; see :async_in option below) and waits for it to terminate. Returns a Porcelain.Result struct containing program’s output and exit status code.

When no options are passed, the following defaults will be used:

[in: "", out: :string, err: nil]

This will run the program with no input and will capture its standard output.

Available options:

  • :in – specify the way input will be passed to the program.

    Possible values:

    • <iodata> – the data is fed into stdin as the sole input for the program

    • <stream> – interprets <stream> as a stream of iodata to be fed into the program

    • {:path, <string>} – path to a file to be fed into stdin

    • {:file, <file>}<file> is a file descriptor obtained from e.g. File.open; the file will be read from the current position until EOF
  • :async_in – can be true or false (default). When enabled, an additional process will be spawned to feed input to the program concurrently with receiving output.

  • :out – specify the way output will be passed back to Elixir.

    Possible values:

    • nil – discard the output

    • :string (default) – the whole output will be accumulated in memory and returned as one string to the caller

    • :iodata – the whole output will be accumulated in memory and returned as iodata to the caller

    • {:path, <string>} – the file at path will be created (or truncated) and the output will be written to it

    • {:append, <string>} – the output will be appended to the the file at path (it will be created first if needed)

    • {:file, <file>}<file> is a file descriptor obtained from e.g. File.open; the file will be written to starting at the current position

    • <coll> – feeds program output (as iodata) into the collectable <coll>. Useful for outputting directly to the console, for example:

      stream = IO.binstream(:standard_io, :line)
      exec("echo", ["hello", "world"], out: stream)
      #=> prints "hello\nworld\n" to stdout
  • :err – specify the way stderr will be passed back to Elixir.

    Possible values are the same as for :out. In addition, it accepts the atom :out which denotes redirecting stderr to stdout.

    Caveat: when using Porcelain.Driver.Basic, the only supported values are nil (stderr will be printed to the terminal) and :out.

  • :dir – takes a path that will be used as the directory in which the program will be launched.

  • :env – set additional environment variables for the program. The value should be an enumerable with elements of the shape {<key>, <val>} where <key> is an atom or a binary and <val> is a binary or false (meaning removing the corresponding variable from the environment). Basically, it accepts any kind of dict, including keyword lists.
reinit(driver \\ nil)

Reruns the initialization and updates application env.

This function is useful in the following cases:

  1. The currently used driver is Goon and the location of the goon executable has changed.

  2. You want to change the driver being used.
shell(cmd, options \\ [])

Specs

shell(binary, Keyword.t) :: Porcelain.Result.t

Execute a shell invocation synchronously.

This function will launch a system shell and pass the invocation to it. This allows using shell features like chaining multiple programs with pipes. The downside is that those advanced features may be unavailable on some platforms.

It is similar to the exec/3 function in all other respects.

spawn(prog, args, options \\ [])

Specs

spawn(binary, [binary], Keyword.t) :: Porcelain.Process.t

Spawn an external process and return a Porcelain.Process struct to be able to communicate with it.

You have to explicitly stop the process after reading its output or when it is no longer needed.

Use the Porcelain.Process.await/2 function to wait for the process to terminate.

Supports all options defined for exec/3 plus some additional ones:

  • in: :receive – input is expected to be sent to the process in chunks using the Porcelain.Process.send_input/2 function.

  • :out and :err can choose from a few more values (with the familiar caveat that Porcelain.Driver.Basic does not support them for :err):

    • :stream – the corresponding field of the returned Process struct will contain a stream of iodata.

      Note that the underlying port implementation is message based. This means that the external program will be able to send all of its output to an Elixir process and terminate. The data will be kept in the Elixir process’s memory until the stream is consumed.

    • {:send, <pid>} – send the output to the process denoted by <pid>. Will send zero or more data messages and will always send one result message in the end.

      The data messages have the following shape:

       {<from>, :data, :out | :err, <iodata>}

      where <from> will be the same pid as the one contained in the Process struct returned by this function.

      The result message has the following shape:

       {<from>, :result, %Porcelain.Result{} | nil}

      The result will be nil if the :result option that is passed to this function is set to :discard.

      Note: if both :out and :err are set up to send to the same pid, only one result message will be sent to that pid in the end.

  • :result – specify how the result of the external program should be returned after it has terminated.

    This option has a smart default value. If either :out or :err option is set to :string or :iodata, :result will be set to :keep. Otherwise, it will be set to :discard.

    Possible values:

    • :keep – the result will be kept in memory until requested by calling Porcelain.Process.await/2 or discarded by calling Porcelain.Process.stop/1.

    • :discard – discards the result and automatically closes the port after program termination. Useful in combination with out: :stream and err: :stream.
spawn_shell(cmd, options \\ [])

Specs

spawn_shell(binary, Keyword.t) :: Porcelain.Process.t

Spawn a system shell and execute the command in it.

Works similar to spawn/3.