mix cmd (Mix v1.19.1)

View Source

Executes the given command.

For example, you can invoke an external command such as make:

$ mix cmd make

Shell expansion

When you invoke mix cmd from the command line, environment variables, glob patterns, and similar are expanded by the current shell and then passed to mix cmd. For example, if you invoke:

$ mix cmd echo lib/*

Your shell will expand "lib/*" and then pass multiple arguments to mix cmd, which in turn passes them to echo. Note that, mix cmd by itself, does not perform any shell expansion. This means that, if you invoke mix cmd programatically, as in:

Mix.Task.run("cmd", ["echo", "lib/*"])

or through a mix.exs alias:

alias: "cmd echo lib/*"

It will literally print "lib/*".

This behaviour is the default from Elixir v1.19. If you want mix cmd to behave like a shell, you can pass the --shell option before the command name:

Mix.Task.run("cmd", ["--shell", "echo", "lib/*"])

Keep in mind however that, if --shell is given, quoted arguments are no longer correctly propagated to the underlying command (as they get expanded before hand).

This task is automatically re-enabled, so it can be called multiple times with different arguments.

Umbrella applications and directories

This task is also useful in umbrella applications to execute a command on each child app:

$ mix cmd pwd

In such cases, Mix will change the current working directory to the root of each umbrella application before executing the command.

You can limit which apps the cmd runs in by using mix do with the --app option:

$ mix do --app app1 --app app2 cmd pwd

Note the tasks aborts whenever a command exits with a non-zero status.

Outside of umbrella projects, you can pass the --cd flag before the command, to specify a directory:

$ mix cmd --cd "third-party" make

Command line options

  • --cd (since v1.10.4) - the directory to run the command in
  • --shell (since v1.19.0) - perform shell expansion of the arguments

Orphan operating system processes

Beware that the Erlang VM does not terminate child processes when it shuts down. Therefore, if you use mix cmd to start long running processes and then shut down the VM, it is likely that those child processes won't be terminated with the VM.

A solution is to make sure the child processes listen to the standard input and terminate when standard input is closed. We discuss this topic at length in the "Orphan operating system processes" of the Port module documentation.