<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>monitord - know how happy your systemd is!</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Heebo:wght@400;600&display=swap" rel="stylesheet">
<style>
:root {
--sd-brand-black: hsl(270, 19%, 13%);
--sd-brand-green: hsl(145, 66%, 51%);
--sd-brand-white: #fff;
--sd-black: hsl(270, 7%, 13%);
--sd-green: hsl(145, 66%, 43%);
--sd-gray-extralight: hsl(30, 10%, 96%);
--sd-gray-light: hsl(30, 10%, 92%);
--sd-gray: hsl(30, 10%, 85%);
--sd-gray-dark: hsl(257, 23%, 20%);
--sd-gray-extradark: hsl(257, 23%, 16%);
--sd-font-weight-normal: 400;
--sd-font-weight-bold: 600;
--sd-foreground-color: var(--sd-gray-extradark);
--sd-background-color: var(--sd-gray-extralight);
--sd-link-color: var(--sd-green);
--sd-link-font-weight: var(--sd-font-weight-bold);
}
@media (prefers-color-scheme: dark) {
:root {
color-scheme: dark;
--sd-foreground-color: var(--sd-gray);
--sd-background-color: var(--sd-black);
--sd-link-color: var(--sd-brand-green);
--sd-link-font-weight: var(--sd-font-weight-normal);
}
}
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
font-size: 1rem;
font-family: "Heebo", sans-serif;
font-weight: 400;
line-height: 1.6;
}
body {
color: var(--sd-foreground-color);
background-color: var(--sd-background-color);
}
.container {
width: 80%;
max-width: 720px;
margin: 0 auto;
text-align: center;
}
.page-logo {
display: block;
padding: 5rem 0 3rem;
color: var(--sd-foreground-color);
}
.page-logo > svg {
display: block;
width: 16em;
height: auto;
margin: 0 auto;
}
h1 {
text-align: center;
font-size: 1.87rem;
font-weight: 400;
font-style: normal;
margin: 0 0 2rem;
line-height: 1.25;
}
@media screen and (min-width: 650px) {
h1 {
font-size: 2.375em;
}
}
hr {
margin: 3rem auto 4rem;
width: 40%;
opacity: 40%;
}
a {
font-weight: var(--sd-link-font-weight);
text-decoration: none;
color: var(--sd-link-color);
cursor: pointer;
}
a:hover {
text-decoration: underline;
}
ul {
list-style: disc;
display: inline-block;
text-align: left;
padding-left: 1.5em;
margin: 0;
}
li {
margin: 0.25em 0;
font-size: 1.1rem;
}
.readme-content {
text-align: left;
margin-top: 2rem;
}
.readme-content h2 {
font-size: 1.25rem;
margin-top: 2.5em;
}
.readme-content h3 {
font-size: 1.15rem;
}
.readme-content h4 {
font-size: 1.05rem;
}
.readme-content p {
margin: 0.75em 0;
}
.readme-content ul, .readme-content ol {
display: block;
padding-left: 2em;
margin: 0.75em 0;
}
.readme-content li {
font-size: 1rem;
}
.readme-content pre {
padding: 1em;
border-radius: 5px;
overflow-x: auto;
background-color: var(--sd-highlight-bg, rgba(255, 255, 255, 1));
}
.readme-content code {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
font-size: 0.875rem;
}
.readme-content p code,
.readme-content li code {
padding: 2px 6px;
border-radius: 3px;
background-color: var(--sd-highlight-inline-bg, rgba(0, 0, 0, 0.07));
}
.readme-content pre code {
padding: 0;
background-color: transparent;
}
.readme-content strong {
font-weight: 600;
}
@media (prefers-color-scheme: light) {
.readme-content pre {
background-color: rgba(255, 255, 255, 1);
}
.readme-content p code,
.readme-content li code {
background-color: rgba(0, 0, 0, 0.07);
}
}
@media (prefers-color-scheme: dark) {
.readme-content pre {
background-color: rgba(0, 0, 0, 0.6);
}
.readme-content p code,
.readme-content li code {
background-color: rgba(255, 255, 255, 0.1);
}
}
footer {
text-align: center;
padding: 3em 0 3em;
font-size: 1em;
margin-top: 4rem;
}
</style>
</head>
<body>
<div class="container">
<div class="page-logo">
<svg role="img" aria-label="monitord logo" width="800" height="200" viewBox="0 0 800 200" xmlns="http://www.w3.org/2000/svg">
<path fill="currentColor" d="M 34 40 L 50 40 C 51.104568 40 52 40.895432 52 42 L 52 158 C 52 159.104568 51.104568 160 50 160 L 34 160 C 32.895432 160 32 159.104568 32 158 L 32 42 C 32 40.895432 32.895432 40 34 40 Z"/>
<path fill="currentColor" d="M 34 40 L 65 40 C 66.104568 40 67 40.895432 67 42 L 67 58 C 67 59.104568 66.104568 60 65 60 L 34 60 C 32.895432 60 32 59.104568 32 58 L 32 42 C 32 40.895432 32.895432 40 34 40 Z"/>
<path fill="currentColor" d="M 34 140 L 65 140 C 66.104568 140 67 140.895432 67 142 L 67 158 C 67 159.104568 66.104568 160 65 160 L 34 160 C 32.895432 160 32 159.104568 32 158 L 32 142 C 32 140.895432 32.895432 140 34 140 Z"/>
<text x="87" y="130" font-family="Helvetica" font-size="68" fill="#30d158">1</text>
<path fill="#ff453a" stroke="#ff453a" stroke-width="6" d="M 173 85 C 173 94.941124 164.941132 103 155 103 C 145.058868 103 137 94.941124 137 85 C 137 75.058876 145.058868 67 155 67 C 164.941132 67 173 75.058876 173 85 Z"/>
<path fill="#000000" stroke="#ff453a" stroke-width="8" stroke-linecap="round" d="M 168 98 L 185 115"/>
<path fill="currentColor" d="M 220 40 L 236 40 C 237.104568 40 238 40.895432 238 42 L 238 158 C 238 159.104568 237.104568 160 236 160 L 220 160 C 218.895432 160 218 159.104568 218 158 L 218 42 C 218 40.895432 218.895432 40 220 40 Z"/>
<path fill="currentColor" d="M 205 40 L 236 40 C 237.104568 40 238 40.895432 238 42 L 238 58 C 238 59.104568 237.104568 60 236 60 L 205 60 C 203.895432 60 203 59.104568 203 58 L 203 42 C 203 40.895432 203.895432 40 205 40 Z"/>
<path fill="currentColor" d="M 205 140 L 236 140 C 237.104568 140 238 140.895432 238 142 L 238 158 C 238 159.104568 237.104568 160 236 160 L 205 160 C 203.895432 160 203 159.104568 203 158 L 203 142 C 203 140.895432 203.895432 140 205 140 Z"/>
<text x="279" y="132" font-family="Helvetica" font-size="72" fill="currentColor">monitord</text>
</svg>
</div>
<h1>monitord ... know how happy your systemd is! <span role="img" aria-label="smiling face">😊</span></h1>
<hr>
<ul>
<li><a href="https://github.com/cooperlees/monitord">GitHub</a></li>
<li><a href="https://crates.io/crates/monitord">monitord on crates.io</a></li>
<li><a href="https://crates.io/crates/monitord-exporter">monitord-exporter on crates.io</a></li>
<li><a href="monitord/index.html">Rust Docs</a></li>
</ul>
<hr>
<div class="readme-content">
<p>We offer the following run modes:</p>
<ul>
<li>systemd-timer (legacy cron would work too)</li>
<li>Refer to monitord.timer and monitord.service unit files</li>
<li>Ensure no <code>daemon:</code> mode options are set in <code>monitord.conf</code></li>
<li>daemon mode</li>
<li>Enable daemon mode in configuration file</li>
<li>Stats will be written to stdout every <code>daemon_stats_refresh_secs</code></li>
</ul>
<p>Open to more formats / run methods ... Open an issue to discuss. Depends on the dependencies basically.</p>
<p><code>monitord</code> is a config driven binary. We plan to keep CLI arguments to a minimum.</p>
<p><strong>INFO</strong> level logging is enabled to stderr by default. Use <code>-l LEVEL</code> to increase or decrease logging.</p>
<h2>Install</h2>
<p>Install via cargo or use as a dependency in your <code>Cargo.toml</code>.</p>
<ul>
<li><code>cargo install monitord</code></li>
<li>Create (copy from repo) a <code>monitord.conf</code></li>
<li>Defaults to looking for it at /etc/monitord.conf</li>
<li><code>monitord --help</code></li>
</ul>
<pre><code class="language-console">crl-linux:monitord cooper$ monitord --help
monitord: Know how happy your systemd is! 😊
Usage: monitord [OPTIONS]
Options:
-c, --config <CONFIG>
Location of your monitord config
[default: /etc/monitord.conf]
-l, --log-level <LOG_LEVEL>
Adjust the console log-level
[default: Info]
[possible values: error, warn, info, debug, trace]
-h, --help
Print help (see a summary with '-h')
-V, --version
Print version
</code></pre>
<h3>Config</h3>
<p>monitord can have the different components monitored. To enable / disabled set the
following in our monitord.conf. This file is <a href="https://en.wikipedia.org/wiki/INI_file">ini format</a>
to match systemd unit files.</p>
<pre><code class="language-ini"># Pure ini - no yes/no for bools
[monitord]
# Set a custom dbus address to connect to
# OPTIONAL: If not set, we default to the Unix socket below
dbus_address = unix:path=/run/dbus/system_bus_socket
# Timeout in seconds for dbus connection/collections
# OPTIONAL: default is 30 seconds
dbus_timeout = 30
# Run as a daemon or 1 time
daemon = false
# Time to refresh systemd stats in seconds
# Daemon mode only
daemon_stats_refresh_secs = 60
# Prefix flat-json key with this value
# The value automatically gets a '.' appended (so don't put here)
key_prefix = monitord
# cron/systemd timer output format
# Supported: json, json-flat, json-pretty
output_format = json
# Grab as much stats from DBus GetStats call
# we can from running dbus daemon
# More tested on dbus-broker daemon
[dbus]
# Summary counters - both dbus-broker + dbus-daemon
enabled = false
# dbus.user.* metrics: user stats as reported by dbus-broker
user_stats = false
# dbus.oeer.* metrics: peer stats as reported by dbus-broker
peer_stats = false
# dbus.cgroup.* stats is an aggregation of peer_stats by cgroup
# by dbus-broker
cgroup_stats = false
# Grab networkd stats from files + networkctl
[networkd]
enabled = true
link_state_dir = /run/systemd/netif/links
# Enable grabbing PID 1 stats via procfs
[pid1]
enabled = true
# Services to grab extra stats for
# .service is important as that's what DBus returns from `list_units`
[services]
foo.service
[timers]
enabled = true
[timers.allowlist]
foo.timer
[timers.blocklist]
bar.timer
# Grab unit status counts via dbus
[units]
enabled = true
state_stats = true
# Filter what services you want collect state stats for
# If both lists are configured blocklist is preferred
# If neither exist all units state will generate counters
[units.state_stats.allowlist]
foo.service
[units.state_stats.blocklist]
bar.service
# machines config
[machines]
enabled = true
# Same rules apply as state_stats lists above
[machines.allowlist]
foo
[machines.blocklist]
bar
# Boot blame metrics - shows the N slowest units at boot
# Similar to `systemd-analyze blame`
# Disabled by default
[boot]
enabled = false
# Number of slowest units to report
num_slowest_units = 5
# Optional: only include specific units in boot blame (if empty, all units are checked)
# Same rules apply as state_stats lists above
[boot.allowlist]
# slow-startup.service
# Optional: exclude specific units from boot blame
[boot.blocklist]
# noisy-but-expected.service
# Unit verification using systemd-analyze verify
# Disabled by default as it can be slow on large systems
[verify]
enabled = false
# Optional: only verify specific units (if empty, all units are checked)
[verify.allowlist]
# example.service
# example.timer
# Optional: skip verification for specific units
[verify.blocklist]
# noisy.service
# broken.timer
</code></pre>
<h2>Machines support</h2>
<p>From version <code>>=0.11</code> monitord supports obtaining the same set of key from
systemd 'machines' (i.e. <code>machinectl --list</code>).</p>
<p>The keys are the same format as below in <code>json_flat</code> output but are prefixed with
the <code>machine</code> keyword and machine name. For example:</p>
<pre><code class="language-json"># $KEY_PREFIX.machine.$MACHINE_NAME
{
...
"monitord.machine.foo.pid1.fd_count": 69,
...
}
</code></pre>
<h2>Output Formats</h2>
<h3>json</h3>
<p>Normal <code>serde_json</code> non pretty JSON. All on one line. Most compact format.</p>
<h3>json-flat</h3>
<p>Move all key value pairs to the top level and . notate compononets + sub values.
Is semi pretty too + custom. All unittested ...</p>
<pre><code class="language-json">{
"boot.blame.dnf5-automatic.service": 204.159,
"boot.blame.cpe_chef.service": 103.05,
"boot.blame.sys-module-fuse.device": 16.21,
"boot.blame.dev-ttyS0.device": 15.809,
"boot.blame.systemd-networkd-wait-online.service": 1.674,
"dbus.active_connections": 10,
"dbus.bus_names": 16,
"dbus.incomplete_connections": 0,
"dbus.match_rules": 26,
"dbus.peak_bus_names": 33,
"dbus.peak_bus_names_per_connection": 2,
"dbus.peak_match_rules": 33,
"dbus.peak_match_rules_per_connection": 13,
"dbus.cgroup.system.slice-systemd-logind.service.activation_request_bytes": 0,
"dbus.cgroup.system.slice-systemd-logind.service.activation_request_fds": 0,
"dbus.cgroup.system.slice-systemd-logind.service.incoming_bytes": 16,
"dbus.cgroup.system.slice-systemd-logind.service.incoming_fds": 0,
"dbus.cgroup.system.slice-systemd-logind.service.match_bytes": 6942,
"dbus.cgroup.system.slice-systemd-logind.service.matches": 5,
"dbus.cgroup.system.slice-systemd-logind.service.name_objects": 1,
"dbus.cgroup.system.slice-systemd-logind.service.outgoing_bytes": 0,
"dbus.cgroup.system.slice-systemd-logind.service.outgoing_fds": 0,
"dbus.cgroup.system.slice-systemd-logind.service.reply_objects": 0,
"dbus.peer.org.freedesktop.systemd1.activation_request_bytes": 0,
"dbus.peer.org.freedesktop.systemd1.activation_request_fds": 0,
"dbus.peer.org.freedesktop.systemd1.incoming_bytes": 16,
"dbus.peer.org.freedesktop.systemd1.incoming_fds": 0,
"dbus.peer.org.freedesktop.systemd1.match_bytes": 46533,
"dbus.peer.org.freedesktop.systemd1.matches": 33,
"dbus.peer.org.freedesktop.systemd1.name_objects": 1,
"dbus.peer.org.freedesktop.systemd1.outgoing_bytes": 0,
"dbus.peer.org.freedesktop.systemd1.outgoing_fds": 0,
"dbus.peer.org.freedesktop.systemd1.reply_objects": 0,
"dbus.user.cooper.bytes": 919236,
"dbus.user.cooper.fds": 78,
"dbus.user.cooper.matches": 510,
"dbus.user.cooper.objects": 80,
"networkd.eno4.address_state": 3,
"networkd.eno4.admin_state": 4,
"networkd.eno4.carrier_state": 5,
"networkd.eno4.ipv4_address_state": 3,
"networkd.eno4.ipv6_address_state": 2,
"networkd.eno4.oper_state": 9,
"networkd.eno4.required_for_online": 1,
"networkd.managed_interfaces": 2,
"networkd.wg0.address_state": 3,
"networkd.wg0.admin_state": 4,
"networkd.wg0.carrier_state": 5,
"networkd.wg0.ipv4_address_state": 3,
"networkd.wg0.ipv6_address_state": 3,
"networkd.wg0.oper_state": 9,
"networkd.wg0.required_for_online": 1,
"pid1.cpu_time_kernel": 48,
"pid1.cpu_user_kernel": 41,
"pid1.fd_count": 245,
"pid1.memory_usage_bytes": 19165184,
"pid1.tasks": 1,
"services.chronyd.service.active_enter_timestamp": 1683556542382710,
"services.chronyd.service.active_exit_timestamp": 0,
"services.chronyd.service.cpuusage_nsec": 328951000,
"services.chronyd.service.inactive_exit_timestamp": 1683556541360626,
"services.chronyd.service.ioread_bytes": 18446744073709551615,
"services.chronyd.service.ioread_operations": 18446744073709551615,
"services.chronyd.service.memory_available": 18446744073709551615,
"services.chronyd.service.memory_current": 5214208,
"services.chronyd.service.nrestarts": 0,
"services.chronyd.service.restart_usec": 100000,
"services.chronyd.service.state_change_timestamp": 1683556542382710,
"services.chronyd.service.status_errno": 0,
"services.chronyd.service.tasks_current": 1,
"services.chronyd.service.timeout_clean_usec": 18446744073709551615,
"services.chronyd.service.watchdog_usec": 0,
"system-state": 3,
"timers.fstrim.timer.accuracy_usec": 3600000000,
"timers.fstrim.timer.fixed_random_delay": 0,
"timers.fstrim.timer.last_trigger_usec": 1743397269608978,
"timers.fstrim.timer.last_trigger_usec_monotonic": 0,
"timers.fstrim.timer.next_elapse_usec_monotonic": 0,
"timers.fstrim.timer.next_elapse_usec_realtime": 1744007133996149,
"timers.fstrim.timer.persistent": 1,
"timers.fstrim.timer.randomized_delay_usec": 6000000000,
"timers.fstrim.timer.remain_after_elapse": 1,
"timers.fstrim.timer.service_unit_last_state_change_usec": 1743517244700135,
"timers.fstrim.timer.service_unit_last_state_change_usec_monotonic": 639312703,
"unit_states.chronyd.service.active_state": 1,
"unit_states.chronyd.service.loaded_state": 1,
"unit_states.chronyd.service.unhealthy": 0,
"units.activating_units": 0,
"units.active_units": 403,
"units.automount_units": 1,
"units.device_units": 150,
"units.failed_units": 0,
"units.inactive_units": 159,
"units.jobs_queued": 0,
"units.loaded_units": 497,
"units.masked_units": 25,
"units.mount_units": 52,
"units.not_found_units": 38,
"units.path_units": 4,
"units.scope_units": 17,
"units.service_units": 199,
"units.slice_units": 7,
"units.socket_units": 28,
"units.target_units": 54,
"units.timer_units": 20,
"units.total_units": 562,
"verify.failing.device": 43,
"verify.failing.mount": 15,
"verify.failing.service": 31,
"verify.failing.slice": 1,
"verify.failing.total": 97,
"version": "255.7-1.fc40"
}
</code></pre>
<h3>json-pretty</h3>
<p>Normal <code>serde_json</code> pretty representations of each components structs.</p>
<h2>dbus stats</h2>
<p>You're going to need to be root or allow permissiong to pull dbus stats.
For dbus-broker here is example config allow a user <code>monitord</code> to query
<code>getStats</code></p>
<pre><code class="language-xml">[cooper@l33t ~]# cat /etc/dbus-1/system.d/allow_monitord_stats.conf
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="monitord">
<allow send_destination="org.freedesktop.DBus"
send_interface="org.freedesktop.DBus.Debug.Stats"
send_member="GetStats"
send_path="/org/freedesktop/DBus"
send_type="method_call"/>
</policy>
</busconfig>
</code></pre>
<h2>Development</h2>
<p>To do test runs (requires <code>systemd</code> and <code>systemd-networkd</code> <em>installed</em>)</p>
<ul>
<li>
<p>Pending what you have enabled in your config ...</p>
</li>
<li>
<p><code>cargo run -- -c monitord.conf -l debug</code></p>
</li>
</ul>
<p>Ensure the following pass before submitting a PR (CI checks):</p>
<ul>
<li><code>cargo test</code></li>
<li><code>cargo clippy</code></li>
<li><code>cargo fmt</code></li>
</ul>
<h3>Generate codegen APIs</h3>
<ul>
<li><code>cargo install zbus_xmlgen</code></li>
<li><code>zbus-xmlgen system org.freedesktop.systemd1 /org/freedesktop/systemd1/unit/chronyd_2eservice</code></li>
</ul>
<p>Then add the following macros to tell clippy to go away:</p>
<pre><code class="language-rust">#![allow(warnings)]
#![allow(clippy)]
</code></pre>
<h3>Non Linux development</h3>
<p>Sometimes I develop from my Mac OS X laptop. So I thought I'd document and
add the way I build a Fedora Rawhide container and mount the local repo to /repo
in the container to run monitord and test.</p>
<ul>
<li>Build the image (w/git, rust tools and systemd)</li>
<li><code>docker build -t monitord-dev .</code></li>
<li>Start via systemd and mount the monitord repo to /repo</li>
<li><code>docker run --rm --name monitord-dev -it --privileged --tmpfs /run --tmpfs /tmp -v $(pwd):/repo monitord-dev /sbin/init</code><ul>
<li><code>--rm</code> is optional but will remove the container when stopped</li>
</ul>
</li>
</ul>
<p>You can now log into the container to build + run tests and run the binary now against systemd.</p>
<ul>
<li><code>docker exec -it monitord-dev bash</code></li>
<li><code>cd /repo ; cargo run -- -c monitord</code></li>
<li>networkd etc. are not running my default but can be started ...</li>
<li><code>systemctl start systemd-networkd</code><ul>
<li>No interfaces will be managed tho by default in the container ...</li>
</ul>
</li>
</ul>
<h2>API Usage</h2>
<h2>DBus</h2>
<p>All monitord's dbus is done via async (tokio) <a href="https://crates.io/crates/zbus">zbus</a> crate.</p>
<p>systemd Dbus APIs are in use in the following modules:</p>
<ul>
<li>machines</li>
<li><code>ManagerProxy::list_machines()</code></li>
<li>Can do most other calls then on the machine's systemd/dbus</li>
<li>networkd</li>
<li><code>ManagerProxy::list_links()</code></li>
<li>Would love to stop parsing <code>/run/systemd/netif/links</code> and replace via varlink API<ul>
<li>https://github.com/systemd/systemd/issues/36877</li>
</ul>
</li>
<li>system</li>
<li><code>ManagerProxy::get_version()</code></li>
<li><code>ManagerProxy::system_state()</code></li>
<li>timer</li>
<li><code>TimerProxy::unit()</code> - Find service unit of timer</li>
<li><code>ManagerProxy::get_unit()</code></li>
<li><code>UnitProxy::state_change_timestamp()</code></li>
<li><code>UnitProxy::state_change_timestamp_monotonic()</code></li>
<li>units</li>
<li><code>ManagerProxy::list_units()</code> - Main counting of unit stats</li>
<li><code>ServiceProxy::cpuusage_nsec()</code></li>
<li><code>ServiceProxy::ioread_bytes()</code></li>
<li><code>ServiceProxy::ioread_operations()</code></li>
<li><code>ServiceProxy::memory_current()</code></li>
<li><code>ServiceProxy::memory_available()</code></li>
<li><code>ServiceProxy::nrestarts()</code></li>
<li><code>ServiceProxy::get_processes()</code></li>
<li><code>ServiceProxy::restart_usec()</code></li>
<li><code>ServiceProxy::status_errno()</code></li>
<li><code>ServiceProxy::tasks_current()</code></li>
<li><code>ServiceProxy::timeout_clean_usec()</code></li>
<li><code>ServiceProxy::watchdog_usec()</code></li>
<li><code>UnitProxy::active_enter_timestamp</code></li>
<li><code>UnitProxy::active_exit_timestamp</code></li>
<li><code>UnitProxy::inactive_exit_timestamp()</code></li>
<li><code>UnitProxy::state_change_timestamp()</code> - Used for raw stat + time_in_state</li>
</ul>
<p>Some of these modules can be disabled via configuration. Due to this, monitord might not
always be running / calling all these DBus calls per run.</p>
<h2>Varlink</h2>
<p>None yet :(.</p>
<h3>varlink 101</h3>
<p>varlink might one day replace our DBUS usage. Here are some notes on how to work with systemd varlink
as there isn't really documentation outside <code>man</code> pages.</p>
<h4>Checking interfaces</h4>
<ul>
<li>varlinkctl is your friend - https://man7.org/linux/man-pages/man1/varlinkctl.1.html</li>
</ul>
<p>Here is an example with networkd's interfaces:</p>
<pre><code>varlinkctl info unix:/run/systemd/netif/io.systemd.Network
varlinkctl introspect unix:/run/systemd/netif/io.systemd.Network io.systemd.Network
cooper@au:~$ varlinkctl call unix:/run/systemd/netif/io.systemd.Network io.systemd.Network.GetStates '{}' -j | jq
{
"AddressState": "routable",
"IPv4AddressState": "routable",
"IPv6AddressState": "routable",
"CarrierState": "carrier",
"OnlineState": "online",
"OperationalState": "routable"
}
</code></pre>
</div>
<footer>
<small><a href="https://github.com/cooperlees/monitord">Website source on GitHub</a></small>
</footer>
</div>
</body>
</html>