{"id":615975,"date":"2023-03-09T08:49:08","date_gmt":"2023-03-09T14:49:08","guid":{"rendered":"https:\/\/news.sellorbuyhomefast.com\/index.php\/2023\/03\/09\/single-file-elixir-scripts\/"},"modified":"2023-03-09T08:49:08","modified_gmt":"2023-03-09T14:49:08","slug":"single-file-elixir-scripts","status":"publish","type":"post","link":"https:\/\/newsycanuse.com\/index.php\/2023\/03\/09\/single-file-elixir-scripts\/","title":{"rendered":"Single File Elixir Scripts"},"content":{"rendered":"\n<dl>\n<dt>Author<\/dt>\n<dd> <img decoding=\"async\" src=\"http:\/\/fly.io\/static\/images\/jason.jpg\" alt=\"Jason Stiebs\" srcset> <\/p>\n<dl>\n<dt>Name<\/dt>\n<dd> Jason Stiebs <\/dd>\n<dt>Social Media<\/dt>\n<dd> <a href=\"https:\/\/twitter.com\/peregrine\" target=\"_blank\" rel=\"noopener noreferrer\">  <span>View Twitter Profile<\/span> <\/a> <\/dd>\n<\/dl>\n<\/dd>\n<\/dl>\n<section>\n<figure> <img decoding=\"async\" src=\"http:\/\/fly.io\/phoenix-files\/2023-03-08\/scripts-cover.png\" alt=\"Man fitting an entire script into his head as he runs.\"><figcaption> <span>Image by<\/span> <svg role=\"img\" style=\"pointer-events: none; width: 17px; height: 17px;\" viewBox=\"0 0 20 20\" fill=\"currentColor\" fill-rule=\"evenodd\"> <g buffered-rendering=\"static\"> <path fill-rule=\"evenodd\" d=\"M1 8a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 018.07 3h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0016.07 6H17a2 2 0 012 2v7a2 2 0 01-2 2H3a2 2 0 01-2-2V8zm13.5 3a4.5 4.5 0 11-9 0 4.5 4.5 0 019 0zM10 14a3 3 0 100-6 3 3 0 000 6z\" clip-rule=\"evenodd\" \/> <\/g> <\/svg> <a href=\"https:\/\/annieruygtillustration.com\/\" target=\"_blank\" rel=\"noopener\"> Annie Ruygt <\/a> <\/figcaption><\/figure>\n<p> This article&#8217;s about running single file Elixir scripts. We even show a Phoenix LiveView Example! Fly.io is a great place to run your Phoenix applications. Check out how to <a href=\"http:\/\/fly.io\/docs\/elixir\/\">get started<\/a>!<\/p>\n<p>Elixir has powerful built in scripting functionality, allowing us to write Elixir to a file\u2014say <code>my_script.exs<\/code>\u2014 and execute it directly by <code>elixir my_script.exs<\/code>.<\/p>\n<p>The vast majority of production Elixir projects will be directly compiled via mix with all available optimizations and performance enhancements enabled. But let&#8217;s explore what we can accomplish when we go on <em>script<\/em> and throw out compilation!<\/p>\n<h3 id=\"mix-install-2\"><a href=\"http:\/\/fly.io\/#mix-install-2\" aria-label=\"Anchor\"><\/a>Mix.install\/2<\/h3>\n<p>The first command to know is <code>Mix.install\/2<\/code>. If you are familiar with <a href=\"https:\/\/livebook.dev\/\">Livebook<\/a> this will be a review, but this command enables installation of <em>any<\/em> <a href=\"https:\/\/hex.pm\/\">hex<\/a> package. Let&#8217;s jump in:<\/p>\n<div>\n<pre><code><span>Mix<\/span><span>.<\/span><span>install<\/span><span>([<\/span> \n  <span>:req<\/span><span>,<\/span> \n  <span>{<\/span><span>:jason<\/span><span>,<\/span> <span>\"~> 1.0\"<\/span><span>}<\/span> \n<span>])<\/span>\n\n<span>Req<\/span><span>.<\/span><span>get!<\/span><span>(<\/span><span>\"https:\/\/api.github.com\/repos\/elixir-lang\/elixir\"<\/span><span>)<\/span><span>.<\/span><span>body<\/span><span>[<\/span><span>\"description\"<\/span><span>]<\/span>\n<span>|><\/span> <span>dbg<\/span><span>()<\/span>\n\n<\/code><\/pre>\n<\/div>\n<p>Here we install the latest version of the wonderful <a href=\"https:\/\/github.com\/wojtekmach\/req\">req<\/a> HTTP client and version 1 for the perfectly named JSON library <a href=\"https:\/\/github.com\/michalmuskala\/jason\">jason<\/a>. Once installed, you can immediately use them. Technically we didn&#8217;t need to install jason because req included it, but I did as an example.<\/p>\n<h3 id=\"application-put_env-4\"><a href=\"http:\/\/fly.io\/#application-put_env-4\" aria-label=\"Anchor\"><\/a>Application.put_env\/4<\/h3>\n<p>The second function we will need is <a href=\"https:\/\/hexdocs.pm\/elixir\/Application.html#put_env\/4\">Application.put_env\/4<\/a>. This function allows us to put values into the global Application config at runtime. Here is the base environment configuration we need if we want to configure a Phoenix Endpoint:<\/p>\n<div>\n<pre><code><span>Application<\/span><span>.<\/span><span>put_env<\/span><span>(<\/span><span>:sample<\/span><span>,<\/span> <span>SamplePhoenix<\/span><span>.<\/span><span>Endpoint<\/span><span>,<\/span>\n    <span>http:<\/span> <span>[<\/span><span>ip:<\/span> <span>{<\/span><span>127<\/span><span>,<\/span> <span>0<\/span><span>,<\/span> <span>0<\/span><span>,<\/span> <span>1<\/span><span>},<\/span> <span>port:<\/span> <span>5001<\/span><span>],<\/span>\n    <span>server:<\/span> <span>true<\/span><span>,<\/span>\n    <span>live_view:<\/span> <span>[<\/span><span>signing_salt:<\/span> <span>\"aaaaaaaa\"<\/span><span>],<\/span>\n    <span>secret_key_base:<\/span> <span>String<\/span><span>.<\/span><span>duplicate<\/span><span>(<\/span><span>\"a\"<\/span><span>,<\/span> <span>64<\/span><span>)<\/span>\n<span>)<\/span>\n\n<\/code><\/pre>\n<\/div>\n<p>This isn&#8217;t the <em>only<\/em> way to configure something. We could have included an option to Mix.install like so:<\/p>\n<div>\n<pre><code><span>Mix<\/span><span>.<\/span><span>install<\/span><span>([<\/span> \n      <span>:bandit<\/span><span>,<\/span>\n      <span>:phoenix<\/span><span>,<\/span> \n      <span>{<\/span><span>:jason<\/span><span>,<\/span> <span>\"~> 1.0\"<\/span><span>}<\/span> \n    <span>],<\/span>\n    <span>config:<\/span> <span>[<\/span>\n        <span>sample:<\/span> <span>[<\/span>\n            <span>SamplePhoenix<\/span><span>.<\/span><span>Endpoint:<\/span> <span>[<\/span>\n                <span>http:<\/span> <span>[<\/span><span>ip:<\/span> <span>{<\/span><span>127<\/span><span>,<\/span> <span>0<\/span><span>,<\/span> <span>0<\/span><span>,<\/span> <span>1<\/span><span>},<\/span> <span>port:<\/span> <span>5001<\/span><span>],<\/span>\n                <span>server:<\/span> <span>true<\/span><span>,<\/span>\n                <span>live_view:<\/span> <span>[<\/span><span>signing_salt:<\/span> <span>\"aaaaaaaa\"<\/span><span>],<\/span>\n                <span>secret_key_base:<\/span> <span>String<\/span><span>.<\/span><span>duplicate<\/span><span>(<\/span><span>\"a\"<\/span><span>,<\/span> <span>64<\/span><span>)<\/span>\n            <span>]<\/span>\n        <span>]<\/span>\n    <span>]<\/span>\n<span>)<\/span>\n\n<\/code><\/pre>\n<\/div>\n<h2 id=\"now-what\"><a href=\"http:\/\/fly.io\/#now-what\" aria-label=\"Anchor\"><\/a>Now What?<\/h2>\n<p>With those two functions we have the basic foundation to do <em>anything<\/em> Elixir can do but in a single, portable file!<\/p>\n<p>We can do&#8230;<\/p>\n<h2 id=\"system-administration\"><a href=\"http:\/\/fly.io\/#system-administration\" aria-label=\"Anchor\"><\/a>System Administration<\/h2>\n<div>\n<pre><code><span>retirement<\/span> <span>=<\/span> <span>Path<\/span><span>.<\/span><span>join<\/span><span>([<\/span><span>System<\/span><span>.<\/span><span>user_home!<\/span><span>(),<\/span> <span>\"retirement\"<\/span><span>])<\/span>\n<span>File<\/span><span>.<\/span><span>mkrp!<\/span><span>(<\/span><span>retirement<\/span><span>)<\/span>\n\n<span># Get rid of those old .ex files who needs em!<\/span>\n<span>Path<\/span><span>.<\/span><span>wildcard<\/span><span>(<\/span><span>\"**\/*.ex\"<\/span><span>)<\/span>\n<span>|><\/span> <span>Enum<\/span><span>.<\/span><span>filter<\/span><span>(<\/span><span>fn<\/span> <span>f<\/span> <span>-><\/span> \n      <span>{{<\/span><span>year<\/span><span>,<\/span> <span>_<\/span><span>,<\/span> <span>_<\/span><span>,},<\/span> <span>_<\/span><span>}<\/span> <span>=<\/span> <span>File<\/span><span>.<\/span><span>stat!<\/span><span>(<\/span><span>f<\/span><span>)<\/span><span>.<\/span><span>mtime<\/span> \n      <span>year<\/span> <span><<\/span> <span>2023<\/span>\n   <span>end<\/span><span>)<\/span>\n<span>|><\/span> <span>Enum<\/span><span>.<\/span><span>each<\/span><span>(<\/span><span>fn<\/span> <span>compiled_file<\/span> <span>-><\/span> \n    <span>File<\/span><span>.<\/span><span>mv!<\/span><span>(<\/span><span>compiled_file<\/span><span>,<\/span> <span>retirement<\/span><span>)<\/span> \n    <span># we only need .exs files now<\/span>\n<span>end<\/span><span>)<\/span>\n\n<\/code><\/pre>\n<\/div>\n<h2 id=\"data-processing\"><a href=\"http:\/\/fly.io\/#data-processing\" aria-label=\"Anchor\"><\/a>Data Processing<\/h2>\n<div>\n<pre><code><span>Mix<\/span><span>.<\/span><span>install<\/span><span>([<\/span> \n  <span>:req<\/span><span>,<\/span> \n  <span>:nimble_csv<\/span>\n<span>])<\/span>\n<span># Req will parse CSVs for us!<\/span>\n<span>Req<\/span><span>.<\/span><span>get!<\/span><span>(<\/span><span>\"https:\/\/api.covidtracking.com\/v1\/us\/daily.csv\"<\/span><span>)<\/span><span>.<\/span><span>body<\/span>\n<span>|><\/span> <span>Enum<\/span><span>.<\/span><span>reduce<\/span><span>(<\/span><span>0<\/span><span>,<\/span> <span>fn<\/span> <span>row<\/span><span>,<\/span> <span>count<\/span> <span>-><\/span> \n    <span>death_increase<\/span> <span>=<\/span> <span>String<\/span><span>.<\/span><span>to_integer<\/span><span>(<\/span><span>Enum<\/span><span>.<\/span><span>at<\/span><span>(<\/span><span>row<\/span><span>,<\/span> <span>19<\/span><span>))<\/span>\n    <span>count<\/span> <span>+<\/span> <span>death_increase<\/span>\n<span>end<\/span><span>)<\/span>\n<span>|><\/span> <span>IO<\/span><span>.<\/span><span>puts<\/span><span>()<\/span>\n\n<\/code><\/pre>\n<\/div>\n<h2 id=\"report-phoenix-liveview-bugs\"><a href=\"http:\/\/fly.io\/#report-phoenix-liveview-bugs\" aria-label=\"Anchor\"><\/a>Report Phoenix LiveView Bugs<\/h2>\n<p>Let&#8217;s say you&#8217;ve discovered a bug in LiveView and want to report it. You can increase the odds of it getting fixed quickly by providing a bare-bones example. You could <code>mix phx.new<\/code> a project and push it up to GitHub, or you could make a single file example and put it in a gist! In fact, Phoenix core contributor <a href=\"https:\/\/github.com\/Gazler\">Gary Rennie<\/a> does this so often that I affectionately call these files Garyfiles.<\/p>\n<div>\n<pre><code><span>Application<\/span><span>.<\/span><span>put_env<\/span><span>(<\/span><span>:sample<\/span><span>,<\/span> <span>SamplePhoenix<\/span><span>.<\/span><span>Endpoint<\/span><span>,<\/span>\n  <span>http:<\/span> <span>[<\/span><span>ip:<\/span> <span>{<\/span><span>127<\/span><span>,<\/span> <span>0<\/span><span>,<\/span> <span>0<\/span><span>,<\/span> <span>1<\/span><span>},<\/span> <span>port:<\/span> <span>5001<\/span><span>],<\/span>\n  <span>server:<\/span> <span>true<\/span><span>,<\/span>\n  <span>live_view:<\/span> <span>[<\/span><span>signing_salt:<\/span> <span>\"aaaaaaaa\"<\/span><span>],<\/span>\n  <span>secret_key_base:<\/span> <span>String<\/span><span>.<\/span><span>duplicate<\/span><span>(<\/span><span>\"a\"<\/span><span>,<\/span> <span>64<\/span><span>)<\/span>\n<span>)<\/span>\n\n<span>Mix<\/span><span>.<\/span><span>install<\/span><span>([<\/span>\n  <span>{<\/span><span>:plug_cowboy<\/span><span>,<\/span> <span>\"~> 2.5\"<\/span><span>},<\/span>\n  <span>{<\/span><span>:jason<\/span><span>,<\/span> <span>\"~> 1.0\"<\/span><span>},<\/span>\n  <span>{<\/span><span>:phoenix<\/span><span>,<\/span> <span>\"~> 1.7.0-rc.2\"<\/span><span>,<\/span> <span>override:<\/span> <span>true<\/span><span>},<\/span>\n  <span>{<\/span><span>:phoenix_live_view<\/span><span>,<\/span> <span>\"~> 0.18.2\"<\/span><span>}<\/span>\n<span>])<\/span>\n\n<span>defmodule<\/span> <span>SamplePhoenix<\/span><span>.<\/span><span>ErrorView<\/span> <span>do<\/span>\n  <span>def<\/span> <span>render<\/span><span>(<\/span><span>template<\/span><span>,<\/span> <span>_<\/span><span>),<\/span> <span>do<\/span><span>:<\/span> <span>Phoenix<\/span><span>.<\/span><span>Controller<\/span><span>.<\/span><span>status_message_from_template<\/span><span>(<\/span><span>template<\/span><span>)<\/span>\n<span>end<\/span>\n\n<span>defmodule<\/span> <span>SamplePhoenix<\/span><span>.<\/span><span>SampleLive<\/span> <span>do<\/span>\n  <span>use<\/span> <span>Phoenix<\/span><span>.<\/span><span>LiveView<\/span><span>,<\/span> <span>layout:<\/span> <span>{<\/span><span>__MODULE__<\/span><span>,<\/span> <span>:live<\/span><span>}<\/span>\n\n  <span>def<\/span> <span>mount<\/span><span>(<\/span><span>_params<\/span><span>,<\/span> <span>_session<\/span><span>,<\/span> <span>socket<\/span><span>)<\/span> <span>do<\/span>\n    <span>{<\/span><span>:oops<\/span><span>,<\/span> <span>assign<\/span><span>(<\/span><span>socket<\/span><span>,<\/span> <span>:count<\/span><span>,<\/span> <span>0<\/span><span>)}<\/span>\n  <span>end<\/span>\n\n  <span>def<\/span> <span>render<\/span><span>(<\/span><span>\"live.html\"<\/span><span>,<\/span> <span>assigns<\/span><span>)<\/span> <span>do<\/span>\n    <span>~H\"\"<\/span><span>\"\n    <script src=\"<\/span><span>https:<\/span><span>\/\/<\/span><span>cdn<\/span><span>.<\/span><span>jsdelivr<\/span><span>.<\/span><span>net<\/span><span>\/<\/span><span>npm<\/span><span>\/<\/span><span>phoenix<\/span><span>@<\/span><span>1.7<\/span><span>.<\/span><span>0<\/span><span>-<\/span><span>rc<\/span><span>.<\/span><span>2<\/span><span>\/<\/span><span>priv<\/span><span>\/<\/span><span>static<\/span><span>\/<\/span><span>phoenix<\/span><span>.<\/span><span>min<\/span><span>.<\/span><span>js<\/span><span>\"><\/script>\n    <script src=\"<\/span><span>https:<\/span><span>\/\/<\/span><span>cdn<\/span><span>.<\/span><span>jsdelivr<\/span><span>.<\/span><span>net<\/span><span>\/<\/span><span>npm<\/span><span>\/<\/span><span>phoenix_live_view<\/span><span>@<\/span><span>0.18<\/span><span>.<\/span><span>2<\/span><span>\/<\/span><span>priv<\/span><span>\/<\/span><span>static<\/span><span>\/<\/span><span>phoenix_live_view<\/span><span>.<\/span><span>min<\/span><span>.<\/span><span>js<\/span><span>\"><\/script>\n    <script>\n      let liveSocket = new window.LiveView.LiveSocket(\"<\/span><span>\/<\/span><span>live<\/span><span>\", window.Phoenix.Socket)\n      liveSocket.connect()\n    <\/script>\n    <style>\n      * { font-size: 1.1em; }\n    <\/style>\n\n    \"\"\"<\/span>\n  <span>end<\/span>\n\n  <span>def<\/span> <span>render<\/span><span>(<\/span><span>assigns<\/span><span>)<\/span> <span>do<\/span>\n    <span>~H\"\"<\/span><span>\"\n\n    <button phx-click=\"<\/span><span>inc<\/span><span>\">+<\/button>\n    <button phx-click=\"<\/span><span>dec<\/span><span>\">-<\/button>\n    \"\"\"<\/span>\n  <span>end<\/span>\n\n  <span>def<\/span> <span>handle_event<\/span><span>(<\/span><span>\"inc\"<\/span><span>,<\/span> <span>_params<\/span><span>,<\/span> <span>socket<\/span><span>)<\/span> <span>do<\/span>\n    <span>{<\/span><span>:noreply<\/span><span>,<\/span> <span>assign<\/span><span>(<\/span><span>socket<\/span><span>,<\/span> <span>:count<\/span><span>,<\/span> <span>socket<\/span><span>.<\/span><span>assigns<\/span><span>.<\/span><span>count<\/span> <span>+<\/span> <span>1<\/span><span>)}<\/span>\n  <span>end<\/span>\n\n  <span>def<\/span> <span>handle_event<\/span><span>(<\/span><span>\"dec\"<\/span><span>,<\/span> <span>_params<\/span><span>,<\/span> <span>socket<\/span><span>)<\/span> <span>do<\/span>\n    <span>{<\/span><span>:noreply<\/span><span>,<\/span> <span>assign<\/span><span>(<\/span><span>socket<\/span><span>,<\/span> <span>:count<\/span><span>,<\/span> <span>socket<\/span><span>.<\/span><span>assigns<\/span><span>.<\/span><span>count<\/span> <span>-<\/span> <span>1<\/span><span>)}<\/span>\n  <span>end<\/span>\n<span>end<\/span>\n\n<span>defmodule<\/span> <span>Router<\/span> <span>do<\/span>\n  <span>use<\/span> <span>Phoenix<\/span><span>.<\/span><span>Router<\/span>\n  <span>import<\/span> <span>Phoenix<\/span><span>.<\/span><span>LiveView<\/span><span>.<\/span><span>Router<\/span>\n\n  <span>pipeline<\/span> <span>:browser<\/span> <span>do<\/span>\n    <span>plug<\/span><span>(<\/span><span>:accepts<\/span><span>,<\/span> <span>[<\/span><span>\"html\"<\/span><span>])<\/span>\n  <span>end<\/span>\n\n  <span>scope<\/span> <span>\"\/\"<\/span><span>,<\/span> <span>SamplePhoenix<\/span> <span>do<\/span>\n    <span>pipe_through<\/span><span>(<\/span><span>:browser<\/span><span>)<\/span>\n\n    <span>live<\/span><span>(<\/span><span>\"\/\"<\/span><span>,<\/span> <span>SampleLive<\/span><span>,<\/span> <span>:index<\/span><span>)<\/span>\n  <span>end<\/span>\n<span>end<\/span>\n\n<span>defmodule<\/span> <span>SamplePhoenix<\/span><span>.<\/span><span>Endpoint<\/span> <span>do<\/span>\n  <span>use<\/span> <span>Phoenix<\/span><span>.<\/span><span>Endpoint<\/span><span>,<\/span> <span>otp_app:<\/span> <span>:sample<\/span>\n  <span>socket<\/span><span>(<\/span><span>\"\/live\"<\/span><span>,<\/span> <span>Phoenix<\/span><span>.<\/span><span>LiveView<\/span><span>.<\/span><span>Socket<\/span><span>)<\/span>\n  <span>plug<\/span><span>(<\/span><span>Router<\/span><span>)<\/span>\n<span>end<\/span>\n\n<span>{<\/span><span>:ok<\/span><span>,<\/span> <span>_<\/span><span>}<\/span> <span>=<\/span> <span>Supervisor<\/span><span>.<\/span><span>start_link<\/span><span>([<\/span><span>SamplePhoenix<\/span><span>.<\/span><span>Endpoint<\/span><span>],<\/span> <span>strategy:<\/span> <span>:one_for_one<\/span><span>)<\/span>\n<span>Process<\/span><span>.<\/span><span>sleep<\/span><span>(<\/span><span>:infinity<\/span><span>)<\/span>\n\n<\/code><\/pre>\n<\/div>\n<p>Turns out the bug wasn&#8217;t in Phoenix at all and was an oopsie on my part. Can you spot it?<\/p>\n<p>This one is slightly more involved and is based on the <a href=\"https:\/\/github.com\/wojtekmach\/mix_install_examples\/\"><code>wojtekmach\/mix_install_examples<\/code><\/a> project. With this file you have a fully functional Phoenix LiveView application in a single file running on port 5001!<\/p>\n<p>And you can see all of the stuff you <em>need<\/em> to make Phoenix Work, and frankly it&#8217;s not that much. When people say we need a &#8220;lightweight web framework&#8221; ask them what&#8217;s unnecessary in this file!<\/p>\n<h2 id=\"report-fly-io-issues\"><a href=\"http:\/\/fly.io\/#report-fly-io-issues\" aria-label=\"Anchor\"><\/a>Report Fly.io Issues<\/h2>\n<p>Here at Fly.io we try to be super responsive on the questions on our <a href=\"https:\/\/community.fly.io\/\">community forum<\/a>. Let&#8217;s say we have an issue with using <code>mnesia<\/code> and fly volumes, like some users <a href=\"https:\/\/community.fly.io\/t\/using-fly-volumes-with-mnesia-phoenix-and-pow\/1756\/18\">recently posted<\/a>. If we wanted to post an isolated bug report, we could set up a minimal project to help really get the attention of the support team.<\/p>\n<p>First, we&#8217;d want a Dockerfile that can run Elixir scripts<\/p>\n<div>\n<pre><code><span># syntax = docker\/dockerfile:1<\/span>\n<span>FROM<\/span><span> \"hexpm\/elixir:1.14.2-erlang-25.2-debian-bullseye-20221004-slim\"<\/span>\n\n<span># install dependencies<\/span>\n<span>RUN <\/span>apt-get update <span>-y<\/span> <span>&&<\/span> apt-get <span>install<\/span> <span>-y<\/span> build-essential git libstdc++6 openssl libncurses5 locales <span>\n<\/span>    <span>&&<\/span> apt-get clean <span>&&<\/span> <span>rm<\/span> <span>-f<\/span> \/var\/lib\/apt\/lists\/<span>*<\/span>_<span>*<\/span>\n\n<span># Set the locale<\/span>\n<span>RUN <\/span><span>sed<\/span> <span>-i<\/span> <span>'\/en_US.UTF-8\/s\/^# \/\/g'<\/span> \/etc\/locale.gen <span>&&<\/span> locale-gen\n\n<span># Env variables we might want<\/span>\n<span>ENV<\/span><span> LANG en_US.UTF-8<\/span>\n<span>ENV<\/span><span> LANGUAGE en_US:en<\/span>\n<span>ENV<\/span><span> LC_ALL en_US.UTF-8<\/span>\n<span>ENV<\/span><span> ECTO_IPV6 true<\/span>\n<span>ENV<\/span><span> ERL_AFLAGS \"-proto_dist inet6_tcp\"<\/span>\n\n<span>WORKDIR<\/span><span> \"\/app\"<\/span>\n\n<span># Copy our files over<\/span>\n<span>COPY<\/span><span> bug.exs \/app<\/span>\n\n<span># install hex + rebar if you plan on using Mix.install<\/span>\n<span>RUN <\/span>mix local.hex <span>--force<\/span> <span>&&<\/span> <span>\n<\/span>    mix local.rebar <span>--force<\/span>\n\n<span>CMD<\/span><span> elixir \/app\/bug.exs<\/span>\n\n<\/code><\/pre>\n<\/div>\n<p>Finally add our <code>bug.exs<\/code><\/p>\n<div>\n<pre><code><span>vol_dir<\/span> <span>=<\/span> <span>System<\/span><span>.<\/span><span>get_env<\/span><span>(<\/span><span>\"VOL_DIR\"<\/span><span>)<\/span> <span>||<\/span> <span>\"\/data\"<\/span>\n\n<span># Setup mnesiua<\/span>\n<span>Application<\/span><span>.<\/span><span>put_env<\/span><span>(<\/span><span>:mnesia<\/span><span>,<\/span> <span>:dir<\/span><span>,<\/span> <span>to_charlist<\/span><span>(<\/span><span>vol_dir<\/span><span>))<\/span>\n<span>:ok<\/span> <span>=<\/span> <span>Application<\/span><span>.<\/span><span>start<\/span><span>(<\/span><span>:mnesia<\/span><span>)<\/span>\n\n<span># Check that mnesia is working<\/span>\n<span>dbg<\/span><span>(<\/span><span>:mnesia<\/span><span>.<\/span><span>change_table_copy_type<\/span><span>(<\/span><span>:schema<\/span><span>,<\/span> <span>node<\/span><span>(),<\/span> <span>:disc_copies<\/span><span>))<\/span>\n\n<span># Maybe try writing a file to see whatsup<\/span>\n<span>path<\/span> <span>=<\/span> <span>Path<\/span><span>.<\/span><span>join<\/span><span>([<\/span><span>vol_dir<\/span><span>,<\/span> <span>\"hello.txt\"<\/span><span>])<\/span>\n<span>File<\/span><span>.<\/span><span>write!<\/span><span>(<\/span><span>path<\/span><span>,<\/span> <span>\"Hello from elixir!\"<\/span><span>)<\/span>\n<span>IO<\/span><span>.<\/span><span>puts<\/span><span>(<\/span><span>File<\/span><span>.<\/span><span>read!<\/span><span>(<\/span><span>path<\/span><span>))<\/span>\n\n<span>Process<\/span><span>.<\/span><span>sleep<\/span><span>(<\/span><span>:infinity<\/span><span>)<\/span> <span># Keep it running so fly knows its okay<\/span>\n\n<\/code><\/pre>\n<\/div>\n<p>And our <code>fly.toml<\/code><\/p>\n<div>\n<pre><code>app = \"APP NAME\"\n\n[mounts]\nsource = \"data\"\ndestination = \"\/data\"\n\n<\/code><\/pre>\n<\/div>\n<p>Now we can <code>fly create APP_NAME<\/code>, <code>fly volumes create data<\/code>, <code>fly deploy<\/code> and then check the logs <code>fly logs<\/code> to see what failed.<\/p>\n<p>In this case, I couldn&#8217;t reproduce the error they were seeing. But it is helpful to have some code that&#8217;s isolated to only the problem you are having. We could also see starting up a Phoenix server this way and deploying a weekend tiny app. I wouldn&#8217;t recommend it, but you could!<\/p>\n<h2 id=\"in-conclusion\"><a href=\"http:\/\/fly.io\/#in-conclusion\" aria-label=\"Anchor\"><\/a>In Conclusion<\/h2>\n<p>If you take nothing else away from this post, I hope you click around <a href=\"https:\/\/github.com\/wojtekmach\">Wojtek Mach<\/a>&#8216;s FANTASTIC <a href=\"https:\/\/github.com\/wojtekmach\/mix_install_examples\/\"><code>mix_install_examples<\/code><\/a> repository for Elixir script inspiration. You can do just about anything from Machine Learning to low level Systems Programming, all from a single file and the Elixir runtime.<\/p>\n<p>And finally, please don&#8217;t be afraid to use them as a development tools. If you encounter a nasty bug in a library or your code, it can really help to isolate it to JUST the failing code and build out a simple repeatable test case like this.<\/p>\n<p>Or maybe instead of asking ChatGPT to write you a shell script, write it in Elixir, so a human can read it.<\/p>\n<figure><figcaption>\n<h2> Fly.io \u2764\ufe0f Elixir<\/h2>\n<p> Fly.io is a great way to run your Phoenix LiveView app close to your users. It&#8217;s really easy to get started. You can be running in minutes.<\/p>\n<p><a href=\"https:\/\/fly.io\/docs\/elixir\/\"> Deploy a Phoenix app today!\u00a0\u00a0<span>\u2192<\/span> <\/a><\/p>\n<\/figcaption><p><img decoding=\"async\" src=\"http:\/\/fly.io\/static\/images\/cta-kitty.jpg\"  alt><\/p>\n<\/figure>\n<\/section>\n<dl>\n<dt> Previous post\u00a0\u00a0\u2193 <\/dt>\n<dd> <a href=\"http:\/\/fly.io\/phoenix-files\/phoenix-dev-blog-streams\/\"> Phoenix Dev Blog &#8211; Streams <\/a> <\/dd>\n<\/dl>\n<p><a href=\"https:\/\/fly.io\/phoenix-files\/single-file-elixir-scripts\/\" class=\"button purchase\" rel=\"nofollow noopener\" target=\"_blank\">Read More<\/a><br \/>\n Blythe Block<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Author Name Jason Stiebs Social Media View Twitter Profile Image by Annie Ruygt This article&#8217;s about running single file Elixir scripts. We even show a Phoenix LiveView Example! Fly.io is a great place to run your Phoenix applications. Check out how to get started!Elixir has powerful built in scripting functionality, allowing us to write Elixir<\/p>\n","protected":false},"author":1,"featured_media":615976,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[41327,22378,46],"tags":[],"class_list":{"0":"post-615975","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-elixir","8":"category-single","9":"category-technology"},"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/posts\/615975","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/comments?post=615975"}],"version-history":[{"count":0,"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/posts\/615975\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/media\/615976"}],"wp:attachment":[{"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/media?parent=615975"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/categories?post=615975"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/newsycanuse.com\/index.php\/wp-json\/wp\/v2\/tags?post=615975"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}