Packages
nerves_runtime
0.6.1
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"
@moduledoc """
"""
@doc """
Reboot the device and gracefully shutdown the Erlang VM.
"""
@spec reboot() :: :ok
def reboot(), do: logged_shutdown("reboot")
@doc """
Power off the device.
"""
@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([any]) :: :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)
# 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