execvp

execvp is a small library that allows a running BEAM instance to hand over control to another OS process. Just like exec replaces the current process with another command in bash. This is particularly useful for escripts or CLI tools that need to replace themselves with another process as their final step. This means when that other process exits, execution does not return to the BEAM.

Erlang:

  execvp:cmd("git", ["help", "rebase"]).
  execvp:'cmd!'("git", ["help", "rebase"]).

Elixir:

  :execvp.cmd("git", ["help", "rebase"])
  :execvp.cmd!("git", ["help", "rebase"])

The difference between cmd and cmd! is that the formar may return an error tuple in case of an error (like a non existent command), but the latter always crashes the entire BEAM in case of an error.

⚠️ Warning: Calling execvp:cmd or cmd!replaces the current BEAM process. Any further Erlang/Elixir code will not run. Concurrent BEAM processes are brutally killed. Use this only if you know what you are doing. Otherwise consider using ports or os:cmd.


Installation

Mix

Add this to your mix.exs dependencies:

  def deps do
    [
      {:execvp, "~> 1.0.0"}
    ]
  end

Then run:

  mix deps.get
  mix deps.compile

Rebar3

Add this to your rebar.config:

  {deps, [
    {execvp, "~> 1.0.0"}
  ]}.

Compile with:

  rebar3 compile

The NIF is built automatically and placed in priv/.

Usage

Erlang

  % Replace current VM with `ls -l /etc`
  execvp:cmd("ls", ["-l", "/etc"]).

Elixir

  # Replace current VM with `ls -l /etc`
  :execvp.cmd("ls", ["-l", "/etc"])

Behavior

  {error, Reason} % Reason is a binary describing the failure

Examples:

  bash$ rebar3 shell
  erl> execvp:cmd("nosuchcommand", []).
  {error, <<"No such file or directory">>}
  erl> execvp:cmd("echo", ["1", "2", "3"]).
  1 2 3
  bash$ _
  bash$ iex -S mix
  iex> :execvp.cmd("nosuchcommand", [])
  {:error, "No such file or directory"}
  erl> :execvp.cmd("echo", ["1", "2", "3"])
  1 2 3
  bash$ _

Intended Use Case

execvp is designed for:

Development