如何从混合任务中 运行 混合任务?

How do I run a mix task from within a mix task?

我想运行自定义混合任务中的混合任务。

类似

def run(_) do
  Mix.Shell.cmd("mix edeliver build release")
  #do other stuff

但我不知道如何执行 shell 命令。如果有任何更简单的方法(除了制作 bash 脚本之外),请告诉我。

虽然我从未尝试过 运行通过 Mix.shell.cmd 从另一个混合任务中执行一个混合任务,但我不确定这是否是最佳实践,它看起来像你的目标因为会工作:

def run(args) do
  Mix.Shell.cmd("mix test", fn(output) -> IO.write(output) end)
  # (...)
end

以上代码通过 mix test 执行 运行 测试并打印出它们的输出。注:以上代码基于Mix 1.3.4,1.4.0界面略有不同

不过,为 "composite" 任务创建一个 mix alias 可能是一种更优雅的方法,该任务由您依赖的任务和自定义任务组成:

# inside mix.exs
def project do
  [
    # (...)
    aliases: [
      "composite.task": [
        "test",
        "edeliver build release",
        "my.custom.task",
      ] 
    ]
  ]
end

现在 运行宁 mix composite.task 应该 运行 my.custom.task 之前的其他两个任务。

Shell 是这里多余的 link。如果要运行edeliver任务,运行Mix.Tasks.Edeliver#run:

def run(_) do
  Mix.Tasks.Edeliver.run(~w|build release|)
  # do other stuff

要执行 shell 命令,您可以使用 Loki。您可以找到 shell 执行 execute/1.

的函数

以及我如何在 Mix.Task 中用于执行其他混合任务的示例:

defmodule Mix.Tasks.Sesamex.Gen.Auth do
  use Mix.Task

  import Loki.Cmd
  import Loki.Shell

  @spec run(List.t) :: none()
  def run([singular, plural]) do

    execute("mix sesamex.gen.model #{singular} #{plural}")
    execute("mix sesamex.gen.controllers #{singular}")
    execute("mix sesamex.gen.views #{singular}")
    execute("mix sesamex.gen.templates #{singular}")
    execute("mix sesamex.gen.routes #{singular}")

    # ...
  end
end

或者看看它是如何执行命令的:

@spec execute(String.t, list(Keyword.t)) :: {Collectable.t, exit_status :: non_neg_integer}
def execute(string, opts) when is_bitstring(string) and is_list(opts) do
  [command | args] = String.split(string)
  say IO.ANSI.format [:green, " *   execute ", :reset, string]
  System.cmd(command, args, env: opts)
end

希望对你有帮助。

Mix.Task.run("edeliver build release") 有效