routel turns the kernel's routing table into a compact, labelled view that is far easier to read than raw ip route output. You will filter to IPv4 or IPv6, pick a specific table, and learn to recognise when a strange result is your command rather than a network problem. Allow about ten minutes; these examples only read routing state and normally need no elevated privileges.
This guide describes the Ubuntu package version iproute2 6.1.0-1ubuntu6.4. The installed manual page is dated 1 September 2021, and the script itself is a Python program that asks ip for JSON route data before formatting it nicely. Other package builds can differ, so check your own command first:
$ dpkg-query -W -f='${Package} ${Version}\n' iproute2
iproute2 6.1.0-1ubuntu6.4
$ command -v routel
/usr/bin/routel
On a non-Debian system, use its package manager or just run command -v routel. Missing entirely? Install iproute2 through your normal system-management process. Do not copy the version string above into an installation command: it is a host-specific observation, not an instruction.
Run routel with no arguments:
$ routel
Dst Gateway Prefsrc Protocol Scope Dev Table
default 136.243.171.1 static enp0s31f6
172.17.0.0/16 172.17.0.1 kernel link docker0
127.0.0.0/8 127.0.0.1 kernel host lo local
Your addresses, interfaces and route count will differ. The header is the useful constant. Dst is the destination prefix, Gateway the next hop where one exists, Prefsrc the preferred source address, and Protocol and Scope describe how the route was installed and where it applies. Dev is the outgoing interface and Table identifies the routing table.
Checkpoint: the no-argument form reads table 0, which is what the installed script passes to ip route list table. That is an implementation detail worth remembering, not a request to print every policy-routing table there is.
Use -4 for IPv4 or -6 for IPv6; the long form is --family with inet or inet6:
$ routel -4 | head -5
Dst Gateway Prefsrc Protocol Scope Dev Table
default 136.243.171.1 static enp0s31f6
172.17.0.0/16 172.17.0.1 kernel link docker0
172.18.0.0/16 172.18.0.1 kernel link br-64a4af5f7dec
$ routel --family inet6 | head -5
Dst Gateway Prefsrc Protocol Scope Dev Table
2a01:4f8:171:2009::/64 kernel enp0s31f6
fe80::/64 kernel enp0s31f6
IPv6 gets wider columns so addresses stay readable. An empty gateway is normal for directly connected or local routes. Piping to head only shortens what you see on screen; it changes nothing in the kernel.
Put a numeric table number first, then any raw route arguments. Table main is conventionally number 254 on Linux:
$ routel 254
Dst Gateway Prefsrc Protocol Scope Dev Table
default 136.243.171.1 static enp0s31f6
172.17.0.0/16 172.17.0.1 kernel link docker0
Reach for this when you are investigating policy routing and already know the table number: confirm it in your own routing policy first, do not assume. To pass route-list arguments after the table number, append them as ordinary ip route list arguments:
$ routel 254 match 192.0.2.10
The exact rows depend on the host. Need machine-readable data for automation? Call ip -j route list table 254 directly instead of parsing this presentation-oriented output.
routel --help prints a short usage line and exits with status 64. That is expected for this script's help path, not a failure:
$ routel --help
Usage: /usr/bin/routel [tablenr [raw ip args...]]
$ printf 'exit status: %s\n' "$?"
exit status: 64
For a normal listing, check both the command status and the output:
$ routel -4 > /tmp/routel-ipv4.txt
$ status=$?
$ test "$status" -eq 0 && test -s /tmp/routel-ipv4.txt
$ printf 'status=%s, output=%s\n' "$status" "$(test -s /tmp/routel-ipv4.txt && echo present || echo empty)"
status=0, output=present
An invalid family gets passed straight to ip, so the error can be followed by a Python JSON parsing traceback. routel --family nope is not a valid way to inspect an unknown address family: stick to inet, inet6, -4 or -6.
routel lists routes. It has no add, delete or replace operation of its own. The raw arguments go straight to ip route list, so every example here stays read-only. Do not turn an investigation into a change by swapping list for a write command in a copied pipeline: ip route del can interrupt connectivity and may be hard to recover remotely.
None of this needs sudo. If a restricted environment blocks route data, work out why first and use the least privilege your policy allows. Do not make a persistent routing change just to get a display command working.
iproute2 and routel are installed.-4 or -6 cut out distracting mixed-family output.