# `Toolshed`

Making the IEx console friendlier one command at a time

To use the helpers, run:

    iex> use Toolshed

Add this to your `.iex.exs` to load automatically.

The following is a list of helpers:

  * `cat/1`          - print out a file
  * `cmd/1`          - run a system command and print the output
  * `date/0`         - print out the current date and time
  * `dmesg/0`        - print kernel messages (Nerves-only)
  * `exit/0`         - exit out of an IEx session
  * `fw_validate/0`  - marks the current image as valid (check Nerves system if supported)
  * `geo/1`          - print out a rough physical location
  * `grep/2`         - print out lines that match a regular expression
  * `hex/1`          - print a number as hex
  * `history/0`      - print out the IEx shell history
  * `httpget/2`      - print or download the results of a HTTP GET request
  * `hostname/0`     - print our hostname
  * `ifconfig/0`     - print info on network interfaces
  * `inspect_bits/1` - pretty print numbers in hex, octal, and binary
  * `load_term!/1`   - load a term that was saved by `save_term!/2`
  * `log_attach/1`   - send log messages to the current group leader
  * `log_detach/0`   - stop sending log messages to the current group leader
  * `lsof/0`         - print out open file handles by OS process
  * `lsmod/0`        - print out what kernel modules have been loaded (Nerves-only)
  * `lsusb/0`        - print info on USB devices
  * `multicast_addresses/0` - print out all multicast addresses
  * `nslookup/1`     - query DNS to find an IP address
  * `ping/2`         - ping a remote host
  * `qr_encode/1`    - create a QR code (requires networking)
  * `reboot/0`       - reboots gracefully (Nerves-only)
  * `reboot!/0`      - reboots immediately  (Nerves-only)
  * `save_value/3`   - save a value to a file as Elixir terms (uses inspect)
  * `save_term!/2`   - save a term as a binary
  * `speed_test/1`   - run a simple network speed test
  * `top/2`          - list out the top processes
  * `tcping/2`       - check if a host can be reached (like ping, but uses TCP)
  * `tree/1`         - pretty print a directory tree
  * `uptime/0`       - print out the current Erlang VM uptime
  * `uname/0`        - print information about the running system (Nerves-only)
  * `weather/0`      - get the local weather (requires networking)

# `speed_test_options`

```elixir
@type speed_test_options() :: [
  duration: pos_integer(),
  ifname: String.t(),
  url: String.t() | URI.t()
]
```

Options for speed_test/1

# `cat`

```elixir
@spec cat(Path.t()) :: :&quot;do not show this result in output&quot;
```

Reads and prints out the contents of a file

# `cmd`

```elixir
@spec cmd(String.t() | charlist()) :: integer()
```

Run a command and return the exit code. This function is intended to be run
interactively.

# `date`

```elixir
@spec date() :: String.t()
```

Return the date and time in UTC

# `dmesg`

```elixir
@spec dmesg() :: :&quot;do not show this result in output&quot;
```

Print out kernel log messages

# `exit`

```elixir
@spec exit() :: true
```

Exit the current IEx session

# `fw_validate`

```elixir
@spec fw_validate() :: :ok | {:error, String.t()}
```

Validate a firmware image

All official Nerves Systems automatically validate newly installed firmware.
For some systems, it's possible to disable this so that new firmware gets
one chance to boot. If it's not "validated" before a reboot, then the device
reverts to the old firmware.

# `geo`

```elixir
@spec geo(keyword()) :: :&quot;do not show this result in output&quot;
```

Geo-locate this Elixir instance

Options:

* `:ifname` - Network interface to use (e.g., `"eth0"`)
* `:whenwhere_url` - URL for the whenwhere server to query. Defaults to http://whenwhere.nerves-project.org
* `:timeout` - Milliseconds to wait for a response. Defaults to 10_000.
* `:connect_timeout` - Milliseconds to wait for the connection. Defaults to `:timeout` value

# `grep`

```elixir
@spec grep(Regex.t(), Path.t()) :: :&quot;do not show this result in output&quot;
```

Run a regular expression on a file and print the matching lines.

    iex> grep ~r/video/, "/etc/mime.types"

If colored is enabled for the shell, the matches will be highlighted red.

# `hex`

```elixir
@spec hex(integer()) :: String.t()
```

Inspect a value with all integers printed out in hex. This is useful for
one-off hex conversions. If you're doing a lot of work that requires
hexadecimal output, you should consider running:

`IEx.configure(inspect: [base: :hex])`

The drawback of doing the above is that strings print out as hex binaries.

# `history`

```elixir
@spec history(pid()) :: :&quot;do not show this result in output&quot;
```

Print out the IEx shell history

The default is to print the history from the current group leader, but
any group leader can be passed in if desired.

# `hostname`

```elixir
@spec hostname() :: String.t()
```

Return the hostname

## Examples

    iex> hostname
    "nerves-1234"

# `httpget`

```elixir
@spec httpget(String.t(), dest: Path.t(), verbose: boolean()) ::
  :&quot;do not show this result in output&quot;
```

Perform a HTTP GET request for the specified URL

By default, the results are printed or you can optionally choose to download
it to a specific location on the file system.

Options:

* `:dest` - File path to write the response to. Defaults to printing to the terminal.
* `:ifname` - Network interface to use (e.g., `"eth0"`)
* `:timeout` - Download timeout. Defaults to 30_000 ms
* `:verbose` - Display request and response headers. Disabled by default.

# `ifconfig`

```elixir
@spec ifconfig() :: :&quot;do not show this result in output&quot;
```

Print out the network interfaces and their addresses.

# `inspect_bits`

```elixir
@spec inspect_bits(number() | binary()) :: :&quot;do not show this result in output&quot;
```

Pretty prints a number in hex, octal and binary

Example:

```
iex> Toolshed.inspect_bits(123)
Decimal     : 123
Hexadecimal : 0000_007B
Octal       : 173
Binary      : 01111011
```

# `load_term!`

```elixir
@spec load_term!(Path.t()) :: term()
```

Load an Erlang term from the filesystem.

## Examples

    iex> save_term!({:some_interesting_atom, ["some", "list"]}, "/root/some_atom.term")
    {:some_interesting_atom, ["some", "list"]}
    iex> load_term!("/root/some_atom.term")
    {:some_interesting_atom, ["some", "list"]}

# `log_attach`

```elixir
@spec log_attach(keyword()) :: :ok
```

Attach the current session to the Elixir logger

This forwards incoming log messages to the terminal. Call `log_detach/0` to
stop the messages.

Behind the scenes, this uses Erlang's `logger_std_h` and Elixir's log
formatter. Options include all of the ones from
[Logger.Formatter](https://hexdocs.pm/logger/main/Logger.Formatter.html#new/1)
and the ability to set the level.

For ease of use, here are the common options:

* `:level` - the minimum log level to report. E.g., specify `level: :warning`
  to only see warnings and errors.
* `:metadata` - a list of metadata keys to show or `:all`

# `log_detach`

```elixir
@spec log_detach() :: :ok | {:error, :not_attached}
```

Detach the current session from the Elixir logger

# `lsmod`

```elixir
@spec lsmod() :: :&quot;do not show this result in output&quot;
```

Print out the loaded kernel modules

Aside from printing out whether the kernel has been tainted, the
Linux utility of the same name just dump the contents of "/proc/modules"
like this one.

Some kernel modules may be built-in to the kernel image. To see
those, run `cat "/lib/modules/x.y.z/modules.builtin"` where `x.y.z` is
the kernel's version number.

# `lsof`

```elixir
@spec lsof() :: :ok
```

List out open files by process

This is an simple version of lsof that works on Linux and
Nerves. While running the normal version of lsof provides
more information, this can be convenient when lsof isn't
easily available or can't be run due to `:emfile` errors
from starting port processes due to too many files being open..

# `lsusb`

```elixir
@spec lsusb() :: :&quot;do not show this result in output&quot;
```

Print out information on all of the connected USB devices.

# `multicast_addresses`

```elixir
@spec multicast_addresses() :: :ok
```

List all active multicast addresses

This lists out multicast addresses by network interface
similar to `ip maddr show`. It currently only works on
Linux.

# `nslookup`

```elixir
@spec nslookup(String.t()) :: :&quot;do not show this result in output&quot;
```

Lookup the specified hostname in the DNS and print out the addresses.

## Examples

    iex> nslookup "google.com"
    Name:     google.com
    Address:  172.217.7.238
    Address:  2607:f8b0:4004:804::200e

# `ping`

```elixir
@spec ping(
  String.t(),
  keyword()
) :: :&quot;do not show this result in output&quot;
```

Ping an IP address using ICMP.

NOTE: Specifying an `:ifname` only sets the source IP address for the
connection. This is only a hint to use the specified interface and not a
guarantee. For example, if you have two interfaces on the same LAN, the OS
routing tables may send traffic out one interface in preference to the one
that you want. On Linux, you can enable policy-based routing and add source
routes to guarantee that packets go out the desired interface.

Options:

* `:count` - number of pings to send (defaults to 3)
* `:identifier` - the identifier to use in the ICMP packets (default is to generate one)
* `:ifname`  - network interface to use (e.g., "eth0")
* `:timeout` - time in seconds to wait for a host to respond (defaults to 10 seconds)

## Examples

```
iex> ping "nerves-project.org"
Response from nerves-project.org (185.199.108.153): icmp_seq=0 time=14.908ms
Response from nerves-project.org (185.199.108.153): icmp_seq=1 time=9.057ms
Response from nerves-project.org (185.199.108.153): icmp_seq=2 time=21.099ms

iex> ping "google.com", ifname: "wlp5s0"
Response from google.com (172.217.7.206): icmp_seq=0 time=88.602ms
```

# `poweroff`

```elixir
@spec poweroff() :: no_return()
```

Helper for gracefully powering off

Not all Nerves devices support powering themselves off. These devices reboot
instead.

# `qr_encode`

```elixir
@spec qr_encode(String.t()) :: :&quot;do not show this result in output&quot;
```

Generate an ASCII art QR code

See https://github.com/chubin/qrenco.de for more information.

# `reboot`

```elixir
@spec reboot() :: no_return()
```

Shortcut to reboot a board. This is a graceful reboot, so it takes some time
before the real reboot.

# `reboot!`

```elixir
@spec reboot!() :: no_return()
```

Reboot immediately without a graceful shutdown. This is for the impatient.

# `save_term!`

```elixir
@spec save_term!(term(), Path.t()) :: term()
```

Save an Erlang term to the filesystem for easy loading later

This function returns the `value` passed in to allow easy piping.

## Examples

    iex> :sys.get_state(MyServer) |> save_term!("/root/my_server.term")
    # Reboot board
    iex> :sys.replace_state(&load_term!("/root/my_server.term"))

# `save_value`

```elixir
@spec save_value(any(), Path.t(), keyword()) :: :ok | {:error, File.posix()}
```

Save a value to a file as Elixir terms

## Examples

    # Save the contents of SystemRegistry to a file
    iex> SystemRegistry.match(:_) |> save_value("/root/sr.txt")
    :ok

# `speed_test`

```elixir
@spec speed_test(speed_test_options()) :: :ok
```

Perform a download speed test

Calling this with no options measures the download speed of a small test
file. The test file may not be large enough or close enough to you to
produce a good measurement. To fix this, pass a `:url` to a better file. To
change the default, add the following to your application environment:

```elixir
config :toolshed, speed_test_url: "http://my_company.com/speed_test_file.bin"
```

Commercial users are encouraged to specify their own files to minimize our
bandwidth costs.

Please be aware that this function is somewhat simplistic in how it measures
download performance.

Options:

* `:duration` - Maximum duration in milliseconds (defaults to 5 seconds)
* `:ifname` - Interface to use (e.g., `"wwan0"` or `"eth0"`)
* `:url` - File to download for the test

# `tcping`

```elixir
@spec tcping(
  String.t(),
  keyword()
) :: :&quot;do not show this result in output&quot;
```

Ping an IP address using TCP

This tries to connect to the remote host using TCP instead of sending an ICMP
echo request like normal ping. This sometimes works better than ping
if the remote server or any machine in between drops ICMP messages.

Options:

* `:count` - number of pings to send (defaults to 3)
* `:ifname` - Specify a network interface to use. (e.g., "eth0")
* `:port` - Which TCP port to try (defaults to 80)

## Examples

    iex> tcping "nerves-project.org"
    Response from nerves-project.org (185.199.108.153:80): time=4.155ms
    Response from nerves-project.org (185.199.108.153:80): time=10.385ms
    Response from nerves-project.org (185.199.108.153:80): time=12.458ms

    iex> tcping "google.com", ifname: "wlp5s0"
    Response from google.com (172.217.7.206:80): time=88.602ms

# `top`

```elixir
@spec top(keyword()) :: :&quot;do not show this result in output&quot;
```

Interactively show the top Elixir processes

This is intended to be called from the IEx prompt and will periodically
update the console with the top processes. Press enter to exit.

Options:

* `:order` - the sort order for the results (`:reductions`, `:delta_reductions`,
  `:mailbox`, `:delta_mailbox`, `:total_heap_size`, `:delta_total_heap_size`, `:heap_size`,
  `:delta_heap_size`, `:stack_size`, `:delta_stack_size`)

# `tree`

```elixir
@spec tree(Path.t()) :: :&quot;do not show this result in output&quot;
```

Print out directories and files in tree form.

# `uname`

```elixir
@spec uname() :: :&quot;do not show this result in output&quot;
```

Print out information about the running software

This is similar to the Linux `uname` to help people remember what to type.

# `uptime`

```elixir
@spec uptime() :: :&quot;do not show this result in output&quot;
```

Print out the current uptime.

# `weather`

```elixir
@spec weather() :: :&quot;do not show this result in output&quot;
```

Display the local weather

See http://wttr.in/:help for more information.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
