Выполнение основной команды оболочки в Elixir
На самом раннем этапе изучения языка и работы с сериями видеороликов ElixirSips. Я продолжаю сталкиваться с вещами, которые были слегка искажены языковыми изменениями. Пытаясь обернуть голову вокруг этого, и треки Google/Github для отслеживания/трассировки SO не принесут мне ничего полезного. У меня есть этот очень простой модуль, который должен просто запускать команду оболочки:
defmodule QuickieSynth.Sound do
def command(note) do
"play -qn synth 2 pluck #{note}"
end
def play(note) do
note |> command |> System.cmd
end
end
Однако, когда этот файл скомпилирован и запущены тесты, я получаю ошибку аргумента; достаточно справедливо - System.cmd/1, похоже, больше не входит в стандартную библиотеку lib.
System.cmd/3 находится в стандартной библиотеке, и чтение документов, указанных в параметрах, является необязательным. Поэтому я пропускаю пустые args note |> command |> System.cmd([])
, а то, что я получаю, это erlang: :enoent
: снова после чтения документов немного более тщательно, достаточно справедливо.
Итак, я пытаюсь использовать Erlang :os.cmd/1
, поэтому note |> command |> :os.cmd
, и я получаю (FunctionClauseError) no function clause matching in :os.validate/1
. И я теперь застрял.
Ответы
Ответ 1
System.cmd/3
кажется, принимает аргументы команды в виде списка и не радует, когда вы пытаетесь проникнуть в аргументы в имени команды. Например, System.cmd("ls", ["-al"])
работает, а System.cmd("ls -al", [])
- нет. Так что в вашем случае вам, вероятно, понадобится что-то вроде:
System.cmd("play", ["-qn", "synth", "2", "pluck", note])
На самом деле ниже происходит :os.find_executable/1
System.cmd/3
:os.find_executable/1
с его первым аргументом, который прекрасно работает для чего-то вроде ls
но возвращает false для ls -al
.
Если вы решите пойти по чисто эрланговскому маршруту, то вызов ожидает список символов вместо двоичного, поэтому вам нужно что-то вроде следующего:
"ls -al" |> String.to_char_list |> :os.cmd