Running an Elixir File as a Script

Elixir is able to run “scripts” or files that are compiled into memory (not on disk) and executed. This is helpful when experimenting with larger Elixir code snippets. This is also helpful if you just want to occasionally run one-off scripts to perform some work and exit.

File: my_test_script.exs

defmodule MyTestScript do

  def say_hi do
    IO.puts "Hello!"
  end

end

MyTestScript.say_hi

To execute the file, from a command-line in the same directory as the file, you can run:

$ elixir my_test_script.exs 
Hello!

The output “Hello!” is displayed in the terminal.

What Just Happened?

This does the following things:

  1. A BEAM instance is started
  2. The file my_test_script.exs is loaded and compiled in memory. The interpreted symbols are loaded into the VM.
  3. The code after the module, (i.e.MyTestScript.say_hi) is interpreted and run.
  4. After completing execution, the BEAM instance is shutdown.

File Extension .exs?

The file extension used on the file is .exs. A normal Elixir file that is compiled ends in .ex. The “s” denotes it is a script and should be interpreted at runtime and not compiled.

Thinking Tip

Files ending in .exs are also used for writing your test files, project configuration files, database migrations and custom scripts. After all, you don’t want your unit test code to be compiled into your deployed project!

Downsides

There are several downsides with building any significant amount of source code using .exs script files.

  • They aren’t as performant. They must be “compiled” again each time they are run.
  • As a project grows, you want to break it out into multiple files for code organization and your own sanity. When running as a script, it is difficult to load and include those other files. However, you can do it. I just don’t recommend it.
  • If your code starts some concurrent tasks, the new processes will spawn and the BEAM promptly shuts down because it completed all the statements you gave it to execute. You can tell the runtime to keep it going using elixir --no-halt my_test_script.exs. To exit, hit CTRL+C, CTRL+C (yup, 2 times) to kill the running BEAM instance.

Mix Project Alternative

A better approach that’s easy to do and will grow with you as you experiment is creating a new mix project.

3 Comments

  1. vlhardy on April 18, 2023 at 9:00 am

    I have the following error in the Visual Studio Code when create exs script, it appears several times in OUTPUT logs. The script runs without errors though.

    Starting ElixirLS release v0.14.3
    Running in d:/Projects/Elixir/sandbox
    ** (Mix.Error) Could not find an SCM for dependency :sourceror from ElixirLS.LanguageServer.Mixfile
    (mix 1.14.4) lib/mix.ex:513: Mix.raise/2
    (mix 1.14.4) lib/mix/dep/loader.ex:195: Mix.Dep.Loader.with_scm_and_app/4
    (mix 1.14.4) lib/mix/dep/loader.ex:141: Mix.Dep.Loader.to_dep/3
    (elixir 1.14.4) lib/enum.ex:1658: Enum.”-map/2-lists^map/1-0-“/2
    (elixir 1.14.4) lib/enum.ex:1658: Enum.”-map/2-lists^map/1-0-“/2
    (mix 1.14.4) lib/mix/dep/loader.ex:358: Mix.Dep.Loader.mix_children/2
    (mix 1.14.4) lib/mix/dep/loader.ex:316: anonymous fn/4 in Mix.Dep.Loader.mix_dep/2
    (mix 1.14.4) lib/mix/project.ex:397: Mix.Project.in_project/4
    [Error – 4:44:08 PM] Server initialization failed.
    Message: Pending response rejected since connection got disposed
    Code: -32097
    [Info – 4:44:09 PM] Connection to server got closed. Server will restart.
    true
    [Error – 4:44:09 PM] ElixirLS – sandbox client: couldn’t create connection to server.
    Message: Pending response rejected since connection got disposed
    Code: -32097

    • Mark Ericksen on April 18, 2023 at 10:47 am

      Hi @vlhardy!

      The VS Code extension Elixir “ElixirLS: Elixir support and debugger” is what’s complaining there. If you were to run the script in a terminal outside of VS Code, you wouldn’t see that error message.

      You may need to update the plugin or there may be some other configuration issue. You can spot it by `ElixirLS.LanguageServer`. That’s the ElixirLS code completion engine complaining. I wonder if it complains because the single-file script isn’t a mix project? Hmm.

      • vlhardy on April 18, 2023 at 1:50 pm

        Hi Mark!
        Thank you for the quick reply. Indeed, the issue was related to the “ElixirLS: Elixir support and debugger” extension. I was testing my_test_script.exs from the example above.
        Fortunately, it was resolved with ChatGPT help) It suggested to run the following in the terminal:
        mix local.hex && mix local.rebar && mix hex.info elixir_ls
        And it helped! So, the issue is solved.

Leave a Comment

You must be logged in to post a comment.