Làm thế nào để chạy một ứng dụng Elixir?


81

Cách chính xác để chạy ứng dụng Elixir là gì?

Tôi đang tạo một dự án đơn giản bằng cách:

mix new app

và sau đó tôi có thể làm:

mix run

về cơ bản biên dịch ứng dụng của tôi một lần. Vì vậy, khi tôi thêm:

IO.puts "running"

trong lib/app.extôi "running"chỉ thấy lần đầu tiên, mỗi lần liên tiếp runkhông làm gì cả trừ khi có một số thay đổi. Tôi có thể làm gì tiếp theo với được tạo app.app?

Tất nhiên tôi biết tôi có thể làm:

escript: [main_module: App]

trong mix.exs, cung cấp def main(args):và sau đó:

mix escript.build
./app

nhưng theo tôi thì nó hơi rườm rà.

Ngoài ra còn có một cái gì đó như:

elixir lib/app.exs

nhưng nó không tính mix.exsrõ ràng, cần thiết cho các phụ thuộc trong của tôi app.


1
Nếu bạn muốn chạy tập lệnh Elixir (một .exstệp) nhưng làm như vậy trong ngữ cảnh của ứng dụng kết hợp của bạn, bạn có thể chạy mix run <script>. Xem mix help runđể biết thêm thông tin.
Michelle Tilley

Câu trả lời:


103

mix runchạy ứng dụng của bạn. Chỉ là khi bạn chỉ cần đưa IO.puts "something"vào một tệp mà dòng đó chỉ được đánh giá trong thời gian biên dịch, nó không có tác dụng gì trong thời gian chạy. Nếu bạn muốn điều gì đó bắt đầu khi bạn khởi động ứng dụng của mình, bạn cần chỉ định điều đó trong của bạn mix.exs.

Thông thường, bạn muốn một cấp cao nhất Applicationsẽ bắt đầu. Để đạt được điều đó, hãy thêm một modtùy chọn vào mix.exs:

def application do
  [
    # this is the name of any module implementing the Application behaviour
    mod: {NewMix, []},
    applications: [:logger]
  ]
end

Và sau đó trong mô-đun đó, bạn cần triển khai một lệnh gọi lại sẽ được gọi khi khởi động ứng dụng:

defmodule NewMix do
  use Application

  def start(_type, _args) do
    IO.puts "starting"
    # some more stuff
  end
end

Lệnh startgọi lại thực sự sẽ thiết lập quy trình cấp cao nhất hoặc gốc cây giám sát của bạn nhưng trong trường hợp này, bạn sẽ thấy rằng nó được gọi mỗi khi bạn sử dụng mix run, mặc dù sau đó là một lỗi.

def start(_type, _args) do
  IO.puts "starting"
  Task.start(fn -> :timer.sleep(1000); IO.puts("done sleeping") end)
end

Trong trường hợp này, chúng tôi đang bắt đầu một quy trình đơn giản trong lệnh gọi lại của chúng tôi, chỉ ngủ trong một giây và sau đó xuất ra một thứ gì đó - điều này đủ để đáp ứng API của lệnh startgọi lại nhưng chúng tôi không thấy "done sleeping". Lý do cho điều này là theo mặc định mix runsẽ thoát sau khi lệnh gọi lại đó hoàn tất quá trình thực thi. Để điều đó không xảy ra, bạn cần sử dụng mix run --no-halt- trong trường hợp này, máy ảo sẽ không bị dừng.

Một cách hữu ích khác để khởi động ứng dụng của bạn là iex -S mix- điều này sẽ hoạt động theo cách tương tự mix run --no-haltnhưng cũng mở ra một trình iexbao nơi bạn có thể tương tác với mã và ứng dụng đang chạy của mình.


4
Được rồi, đó gần như là những gì tôi cần! Một điều nữa, bạn có thể giải thích returned a bad value: :oklỗi này khi không có Task, hoặc Agenthoặc Supervisorvv? Điều đó hoạt động như thế nào và tại sao chúng ta cần một quy trình riêng? Tại sao tôi không thể chạy một số tập lệnh thực thi bất cứ thứ gì tôi cần?
Kamil Lelonek

18
Một cuộc gọi lại ứng dụng phải trả về một cây giám sát. Nếu bạn không trả lại một cái, nó sẽ không thành công. Trong thực tế, tôi thậm chí sẽ thay thế các biểu cuối cùng thể hiện bởi Paweł bởi: Supervisor.start_link [], strategy: :one_for_one. Việc trả lại một tác vụ bị tắt có thể khiến ứng dụng bị lỗi sau khi ngủ.
José Valim

1
@squixy một số lợi ích của việc sử dụng và xác định các ứng dụng được nêu ở đây: stackoverflow.com/questions/30422184/...
José Valim

2
Nếu bạn đang xây dựng bất kỳ loại ứng dụng lâu dài nào, bạn hầu như luôn muốn có một Supervisor. Tôi đã sử dụng Taskchỉ để có chương trình chính xác nhỏ nhất nhưng như Jose đã đề cập - bạn muốn bắt đầu cây giám sát của mình ở đó.
Paweł Obrok

1
Câu trả lời chính xác! Một câu hỏi. Bạn đã viết "Chỉ là khi bạn chỉ cần đưa IO.puts "something"vào một tệp mà dòng đó chỉ được đánh giá trong thời gian biên dịch, nó không làm gì cả trong thời gian chạy." có vẻ tương ứng với những gì tôi đang thấy nhưng tôi không hiểu logic của điều này? Tại sao nó hoạt động theo cách đó?
user2104969

10

Bạn có thể chạy các tác vụ bằng cách nhập Mix.Taskvào mô-đun của mình thay vì mix run.

Tôi nghĩ đây là những gì bạn đang tìm kiếm.

Trên hết, thay vào đó mix <task.run>, bạn có thể chỉ cần chạy mixđể chạy tác vụ mặc định. Chỉ cần thêm default_task: "bot.run"vào danh sách def project do [..] endtrong mix.exs. Tham khảo tại đây .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.