Spawning OS Processes in Elixir

You’re building an app that needs to present a calendar of the current month to the user, where do you start?

You could write this implementation yourself by working out the dates and days in a month and come up with your own algorithm to present that information but there’s an easier way. cal is a standard program on Unix and Unix-like operating systems that prints an ASCII calendar of the given month or year.

Calendar command output

We can ask our operating system to run the cal program and get the output, from there we can simply display it to our user with no need to write our own algorithm or download another date library dependency.

The answer in Elixir is ports. After we open a port, the Elixir process that owns the port will recieve all sorts of messages that we can listen for such as {port, {:data, data}} when the program outputs some information or {port, {:exit_status, status}} when the program terminates.

# calendar.exs

# Start a new process and run the `cal` command with `-h` flag
# to not output highlighting of the current day. The second
# argument is a list of options used to configure the port
cal_port = Port.open({:spawn, "cal -h"}, [:binary])

# Once the port has been opened we can start a receive block
# to capture any messages/events.
receive do
  {^cal_port, {:data, cal}} ->
    IO.puts(cal)
end

If we run this script we will see a calendar that’s is identical to the calendar we seen from running cal directly from our terminal (excluding the highlighting we disabled)

Calendar port output

Obviously we are not limited to just displaying calendars though, we can start any program installed on the host machine or maybe you have a shell script that accomplishes something already then there’s no need to re-write it again, instead we can re-use it.

Here’s a few ideas where you might want to resort to ports

  • System profiler application could display the output of ps or top
  • Continuous integration application could git clone a repository
  • File management application might make use of mv, rm and cp commands to manage files

Matthew Henley

🖥 Software engineer. React, Elm and Elixir enthusiast 🐣

Tags
Elixir