The posix
Hex package gives the Erlang Runtime System access to POSIX features of the build environment.
The API of the posix
library is portable, using Erlang atoms rather than OS-dependent magic constants. However, a release built using posix
is not portable: a NIF is generated which "burns in" the properties of the build environment.
The posix
package is thus best suited for use in SaaS server software that does not require redistribution.
System.POSIX.SignalListener
allows your Elixir release to modify the behavior of ERTS in response to POSIX signals. You can use this to:
-
refresh configuration on
SIGHUP
, like a regular daemon; -
shut down gracefully on
SIGINT
; -
allow users to poll for progress information using
SIGINFO
(Ctrl+T), likedd(1)
In your config.exs
, specify one or more signal-handling modules:
config :posix, :signals,
handlers: [HandlerFoo, HandlerBar]
System.POSIX.SignalListener
is implemented as a GenEvent
server; the modules you register should look like GenEvent
handlers, and should just react to the signals they care about:
defmodule System.GracefulShutdownHandler do
use GenEvent
# handle SIGTERM -- the default signal from kill(1)
def handle_event({:caught, :term}, state) do
:init.stop
{:ok, state}
end
def handle_event(_, state), do: {:ok, state}
end
By default, the set of signals System.POSIX.Signal
registers for is [:info, :winch, :term, :hup, :usr1, :usr2]
. You can define your own set:
config :posix, :signals,
listen: [:pipe, :alrm, :urg, :abrt]
Don't be surprised, though, if overriding signals ERTS expected to catch itself causes strange behavior. The default set is safe; other signals may not be.
System.POSIX.Errno
gives your Elixir programs (portable!) access to the constants from errno.h
, and to the strerror(3)
function. This enables you to:
-
understand the exit statuses of spawned programs, and
-
use
:erlang.halt/1
to tell other POSIX programs why Erlang died.
Interpreting exit codes:
import System.POSIX.Errno
too_many_args = "1234567890" |> List.duplicate(100_000)
{_, exit_code} = System.cmd("true", too_many_args)
IO.puts ["Process failed: ", errno(exit_code).description]
# => Process failed: Argument list too long
Emitting exit codes:
# something terrible has happened to a process we're doing IPC with!
errno(:EPIPE).code |> :erlang.halt
System.POSIX
is implemented as a NIF written in Rust. To compile this package, you therefore need Rust to be available in your build environment. Use rustup to install.
Presuming a Rust installation, just add posix
to your list of dependencies in mix.exs
:
def deps do
[{:posix, "~> 0.1.0"}]
end