0
votes

Objective: Print "hello world" on the remote machine.

I want to spawn a process from my computer and print "Hello World" (call Sample.hello) on remote machine. There are ways to connect nodes on a different machine as mentioned here. But this is using iex commands. How to print "Hello World" programmatically on remote machine?

defmodule Sample do


  def hello do
    IO.puts "Hello World"
  end

  def main(args \\ []) do

    # IP address of remote server from command line argument.

    {_, input, _} = OptionParser.parse(args, switches: [])
    ipaddress = List.to_string(input)

    """
      1. spawn new process
      2. print hello world on remote machine - Call Sample.hello
    """
  end
end
3
Can you explain what you mean by "start remote server"? Are you trying to turn a physical (or virtual) computer on? Are you trying to start an Erlang/Elixir node? Something else? - Justin Wood
Sorry for the incorrect representation. I just want to execute hello world program on remote machine. - Sanket Achari
Could you use something like Erlang [rpc][1] module? [1]: erlang.org/doc/man/rpc.html - mpm

3 Answers

0
votes

On REMOTE machine start the VM

$ iex --sname "[email protected]" --cookie mycookie

On LOCAL machine start the VM

$ iex --sname "[email protected]" --cookie mycookie

In the local elixir terminal

Node.connect :"[email protected]"
Main.main(  :"[email protected]" )

Where you have already compiled the source

defmodule Sample do
  def loop  do
    receive do
      {:message, msg} -> IO.puts message
    end   
    loop()
  end
end

defmodule Main do
  def main( node ) do
    pid = Node.spawn( node, Sample, :loop, [ ] );
    send pid, {:message, "Hello world"};
  end
end

I haven't run this but it should work as long as you customize the ip address/names

0
votes

There is more than one way to do this. Here is an example.

Remote setup

mix new foo

Edit foo/lib/foo.ex to look like this:

defmodule Foo do
  def connect do
    Node.start(:foo@foohostname, :shortnames)
    Node.set_cookie(:foo@foohostname, :shh_dont_tell)
  end

  def hello do
    IO.puts :world
  end
end

Be sure to put your hostname on your local network in place of foohostname.

Next, start it up. You mentioned you want to avoid iex, so you can start your application however you prefer. You could create a mix script to start it and connect, for example. But since that is a digression from the topic at hand, I will start it with iex:

iex -S mix

Followed by:

iex(1)> Foo.connect

Local setup

mix new bar

In bar/lib/bar.ex:

defmodule Bar do
  def connect do
    Node.start(:bar@barhostname, :shortnames)
    Node.set_cookie(:bar@barhostname, :shh_dont_tell)
    Node.connect(:foo@foohostname)
  end
end

Remember to substitute the hostname for bar into barhostname and likewise for foo.

Now, you have a programmatic means to connect your nodes. You can access the other Foo node anywhere in the Bar application.

Let's use iex again for an example. Follow along at the commandline:

iex -S mix

iex(1)> Bar.connect
#PID<16393.795.0>
iex(bar@barhostname)> Node.spawn_link :foo@foohostname, fn -> Foo.hello end
world
#PID<16393.795.0>

Note that connecting the nodes is not necessary for spawning one-off function calls like this, so in this example you could choose not to include the Node.connect line, but it is necessary for more sophisticated node management.

-1
votes

@GavinBrelstaff answer is ok but can be simplified to:

In one terminal:

$ iex --sname node1@localhost

In another terminal:

$ iex --sname node2@localhost
Erlang/OTP 20 [erts-9.0] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (1.5.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(node2@localhost)1> Node.spawn(:"node1@localhost", fn -> IO.puts("Run on #{Node.self}") end)
#PID<9960.95.0>
Run on node1@localhost

You can see the function was run on node1. Note that the IO.puts output is redirected to the console on node2 so it's not printed out on node1 (this could be the source of your confusion maybe?).