Packages
nerves_runtime
0.7.0
0.13.13
0.13.12
0.13.11
retired
0.13.10
0.13.9
0.13.8
0.13.7
0.13.6
0.13.5
0.13.4
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.10
0.11.9
0.11.8
0.11.7
0.11.6
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
retired
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.0
0.7.0
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.3
0.5.2
0.5.1
0.5.0
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.1
0.3.0
0.2.0
0.1.2
0.1.1
0.1.0
Small, general runtime utilities for Nerves devices
Current section
Files
Jump to
Current section
Files
lib/nerves_runtime.ex
defmodule Nerves.Runtime do
require Logger
alias Nerves.Runtime.OutputLogger
@revert_fw_path "/usr/share/fwup/revert.fw"
@typedoc """
Options for `Nerves.Runtime.revert/1`.
* `:reboot` - Call `Nerves.Runtime.reboot/0` after reverting (defaults to `true`)
"""
@type revert_options :: {:reboot, boolean()}
@moduledoc """
Nerves.Runtime contains functions useful for almost all Nerves-based devices.
"""
@doc """
Reboot the device and gracefully shutdown the Erlang VM.
This calls `:init.stop/0` internally. If `:init.stop/0` takes longer than the
`erlinit.config`'s `--graceful-powerdown` setting (likely 10 seconds) then
the system will be hard rebooted.
"""
@spec reboot() :: :ok
def reboot(), do: logged_shutdown("reboot")
@doc """
Power off the device.
This calls `:init.stop/0` internally. If `:init.stop/0` takes longer than the
`erlinit.config`'s `--graceful-powerdown` setting (likely 10 seconds) then
the system will be hard rebooted.
"""
@spec poweroff() :: :ok
def poweroff(), do: logged_shutdown("poweroff")
@doc """
Halt the device (meaning hang, not power off, nor reboot).
Note: this is different than :erlang.halt(), which exits BEAM, and may end up
rebooting the device if `erlinit.config` settings allow reboot on exit.
"""
@spec halt() :: :ok
def halt(), do: logged_shutdown("halt")
@doc """
Revert the device to running the previous firmware.
This requires a specially constructed fw file.
"""
@spec revert([revert_options]) :: :ok | {:error, reason :: any}
def revert(opts \\ []) do
reboot? = if opts[:reboot] != nil, do: opts[:reboot], else: true
if File.exists?(@revert_fw_path) do
cmd("fwup", [@revert_fw_path, "-t", "revert", "-d", "/dev/rootdisk0"], :info)
if reboot?, do: reboot()
else
{:error, "Unable to locate revert firmware at path: #{@revert_fw_path}"}
end
end
@doc """
Run system command and log output into logger.
"""
@spec cmd(binary(), [binary()], :debug | :info | :warn | :error | :return) ::
{Collectable.t(), exit_status :: non_neg_integer()}
def cmd(cmd, params, :return), do: System.cmd(cmd, params, stderr_to_stdout: true)
def cmd(cmd, params, out),
do: System.cmd(cmd, params, into: OutputLogger.new(out), stderr_to_stdout: true)
def target() do
target = Application.get_env(:nerves_runtime, :target)
if target == "host", do: "host", else: "target"
end
# private helpers
defp logged_shutdown(cmd) do
Logger.info("#{__MODULE__} : device told to #{cmd}")
# Invoke the appropriate command to tell erlinit that a shutdown
# of the Erlang VM is imminent. Once this returns, the Erlang has
# about 10 seconds to exit unless `--graceful-powerdown` is used
# in the `erlinit.config` to modify the timeout.
cmd(cmd, [], :info)
# Gracefully shut down
:init.stop()
end
end