【问题标题】:Argument Error when trying to specify :env in Elixir Port.open尝试在 Elixir Port.open 中指定 :env 时出现参数错误
【发布时间】:2017-12-26 14:32:20
【问题描述】:

我正在尝试在使用Port.open 运行 shell 命令时设置环境变量。无论我传入什么,它都会引发错误,ArgumentError

port = Port.open({ :spawn_executable, "/usr/local/bin/cool" },
        [:stream, :in, :binary, :eof, :hide, 
          {:env, [{"COOL_ENV", "cool"}]},
          { :args, ["test.js"] }])

根据 Port.open 的 Elixir 文档,它应该接受 Erlang 函数 :erlang.open_port 接受的任何参数。 Erlang 文档提到:

{env, Env} 仅对 {spawn, Command} 和 {spawn_executable, 文件名}。启动过程的环境使用扩展 Env.中的环境规范。

Env 是元组 {Name, Val} 的列表,其中 Name 是 一个环境变量,Val 是它在 衍生端口进程。 Name 和 Val 都必须是字符串。唯一的那个 例外是 Val 是原子 false(类似于 os:getenv/1, 删除环境变量。 (http://erlang.org/doc/man/erlang.html#open_port-2)

即使我尝试像这样直接调用 erlang 函数也会出现此错误:

:erlang.open_port({:spawn_executable, "/usr/local/bin/cool"}, [:stream, :in, :binary, :eof, :hide, {:env, [{"COOL", "cool"}] },{:args, ["test.js"]}])

如果我删除 {:env, [{...}] 参数,错误就会消失。

【问题讨论】:

    标签: erlang elixir


    【解决方案1】:

    :env 选项要求名称和值都是 Erlang 字符串,在 Elixir 中称为 charlist,使用单引号而不是双引号构造。

    Opt =
        ...
        {env, Env :: [{Name :: string(), Val :: string() | false}]} |
        ...
    

    Source

    以下应该可以修复错误:

    port = Port.open({ :spawn_executable, "/usr/local/bin/cool" },
            [:stream, :in, :binary, :eof, :hide, 
              {:env, [{'COOL_ENV', 'cool'}]},
              { :args, ["test.js"] }])
    

    :args 接受 Erlang 字符串和 Erlang 二进制文件(Elixir 字符串),因此您无需更改它。

    【讨论】:

    • 谢谢!你已经回答了我最近的 3 个长生不老药问题:D。有没有更简单的方法来解决这样的错误?错误消息非常简洁,几乎没有任何帮助。
    • 我同意错误信息没有帮助。每当我从 Erlang 标准库中的函数中得到参数错误时,我首先检查 docs 中函数的类型签名,然后检查我是否传递了正确类型的参数。如果这没有帮助,那么最后的手段是找到函数的源代码并查看所有失败的检查导致参数错误的原因。
    • 这个答案让我很开心:-)
    猜你喜欢
    • 2022-08-17
    • 2021-04-15
    • 2019-03-02
    • 2018-06-06
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多