How to create and run a custom task in Phoenix? Like "rake something" in Ruby

How to create and run a custom task on a server in Phoenix? Manually and once, that is. In Ruby I’d use rake my_test_task

You need to create a module that is prefixed by Mix.Tasks., is your taskname with caps and implements Mix.Task-behaviour.

The process in general is explained there as well.

5 Likes

How to manually, from the command line run my task on a server?

If your mix task module is named Mix.Tasks.App.Foo you can run it as mix app.foo.

1 Like

@NobbZ already provided you great answers, but please take a look on this article. Basically it’s very easy.

Also you have to remember that whenever you would like to use any application, which is project dependency, in the mix task, you have to use ensure_started/2, example of using Repo is also here.

4 Likes

Have you tried to run a task on a server this way?

This is how you run a mix task. If it doesn’t work, please tell us more about your environment.

If by server you mean a computer that runs a release, build for production without mix Bering bundled then of course you can’t run mix tasks. For such scenarios you need to create escripts that connect to your nose and call maintenance functions or do a remsh and call those maintenance functions manually, the latter were the way I’d prefer since it doesn’t require an elixir or Erlang installation besides the one bundled in the release.

If by server you mean something else, please elaborate.

3 Likes

server = production server where my website runs

How exactly should I create a task for a production server ?

So you are running a release there? As I said, write maintenance functions, connect via remote shell and then run the functions.

Mix is usually not available on those systems, since it is a build tool and on the prod you usually do not build.

2 Likes

yes
my question is - how exactly?

It depends of the release tool you’ll use. When using distillery, you have to live without mix at all. Consider this example for replacing Repo migrations.

1 Like

I didn’t say “migrations”. I said - task. I want to login to my server via ssh and run a task in the terminal, the same way I’d do in ruby – “rake my_task”

It was an example :wink: You can do it as we already explained you how, just make sure that any part of your app that you want to use, it’s started.

rake is a ruby tool and independant from phoenix, elixir or whatnot. If you want to use rake you need to install it.

If though you want to run maintanance functions, then just create them in your application, eg:

defmodule MyApp.Maintanance do
  def foo(), do: :bar
end

Remote-Shell into your app:

$ iex --remsh your@node --cookie $your_cookie --name your@ip
[elixir header]
iex(1)> MyApp.Maintanace.foo()
:bar

Well, at least roughly. Can’t test right now, since I’ve no elixir machine, but thats the rough theory.

If you use destillery, you can use this example from the docs, explaining how to run migrations and change it that it suites your needs.

Basically it involves these steps:

  1. Write maintance functionality in your app
  2. write a shell script which wraps your command
  3. register a subcommand in your release config

Also as far as I remember, destillery has a command for a shell built-in: myapp shell (after SSHing into your server) should open up an iex prompt which runs in the context of your application.


edit

It’s not shell, it’s remote_console:

Once started, you can connect a shell to the running release with bin/<name> remote_console or bin/<name> attach, though I would avoid the latter unless you have good reason to use it, as exiting with CTRL+C will kill the running node, while doing so with remote_console will simply exit the shell.

From https://github.com/bitwalker/distillery/blob/master/docs/Walkthrough.md


edit2

And if you are not using distillery, but something else to build your release, you should tell, then we can answer more tailored to your release tool.

2 Likes

Your server like bin/<name> has an RPC command for calling functions straight, like bin/<name> rpc The.Module function_to_call args....

So you make the function in your system, then you can call it like that. Quite simple and easily wrappable into single-line scripts. :slight_smile:

2 Likes

I’m using distillery.
I’ll try that out, thx.

That’s a semi-hackery approach, the one similar to editing data directly in database or running REPL on server to patch something in a dirty and fast way, isn’t it?

No, it’s not hackish. It’s functionally equivalent to doing the remote console approach and typing the command, but it just does it all in one from the unix shell.

Mooodi, I see you have a rails background. As superficially similar as the syntax of Elixir may look to Ruby, things are a whole lot different under the hood. In a distillery release on a server, bin/yourappname is the closest thing to rake you’re going to get. Distillery’s hexdocs are very good and will show you how you can write custom commands for your release (https://hexdocs.pm/distillery/custom-commands.html)

1 Like

Not even remotely, that ‘is’ the way to call something in a running system from the system shell.

That’s not. What if I have a user whom I delegate this job and whom I don’t want to call anything else but a certain module#method? What will prevent him from calling something else? Even by making a typo.

What if I accidentally call “MyModule#reset_db2” instead of “MyModule#reset_db1”? Assuming that “MyModule#reset_db2” has no task associated with it – it’s merely a module and function, whereas “MyModule#reset_db1” does.

console won’t prevent such type of mistakes.