DEV Community

Cover image for The command a tool tells you to run has to be correct for *your* machine
7sh1d0w7x
7sh1d0w7x

Posted on

The command a tool tells you to run has to be correct for *your* machine

A health checker gave a Bazzite user a dnf command.
Bazzite has no writable root. Here is what I found across five distro families,
and why "advice" is code.

A user sent me this:

Review both with \du -sh ~/.cache/* | sort -rh | head -20…

Two things were wrong with that line, and they were wrong in different ways.

The obvious one: on their machine it errored. ~/.cache/* expands a glob —
fine with 20 entries, "argument list too long" with 20,000, and it silently
skips hidden entries. The second half, ~/.var/app/*/cache, stays literal
when no Flatpak app exists, so du tries to read a directory called *.

The one that took longer to see: the same tool was telling people on
Fedora Atomic desktops to run sudo dnf install akmod-nvidia. On Bazzite,
Silverblue and Kinoite the root filesystem is read-only and the rpm database is
a bind mount. dnf does not install anything there. The NVIDIA driver is in
the image
— you switch images by rebasing. There is no package cache to clean.
The kernel is not a removable package. grub2-mkconfig is not how boot entries
are made.

None of that was a bug in the checks. The checks were right. It was the
advice that was wrong.

Advice is code

Every "recommended next step" is a string like any other, and it was written by
one person on one distribution. If you write sudo dnf install … at 2am while
testing on Fedora, it ships to Arch, Alpine, Void and openSUSE.

So I treated the advice as code and went looking for every place it was
hard-coded. Two patterns came out:

  1. Hard-coded invocations. "Install the driver (e.g. \sudo dnf install akmod-nvidiaon Fedora/Bazzite)" — with Bazzite named in the source, which is how I knew nobody had tested it there.
  2. A wrong mental model. "Clean the package cache" is meaningless on an image-based system. The command isn't wrong, the sentence is.

What the five families actually need

I read the documentation for each family instead of trusting memory. A few
things surprised me:

Situation Fedora Atomic Classic Fedora Debian
install a package last resort; rpm-ostree install, needs reboot dnf install apt install
install NVIDIA not a package — rebase to the -nvidia image RPM Fusion + akmod-nvidia contrib non-free
clear package cache rpm-ostree cleanup -m (repodata); there is no dnf cache dnf clean all apt clean
remove old kernels nothing to remove — the kernel ships with the image dnf remove --oldinstallonly apt autoremove --purge
regenerate GRUB don't — rpm-ostree kargs / ujust configure-grub grub2-mkconfig update-grub

And beyond the package managers: Alpine and Gentoo run OpenRC, Void runs
runit.
Telling those users to run systemctl is not a typo, it's a different
init system. They get rc-service and sv now.

The fix, in three parts

  1. One source of truth. pkgInstall(dist, pkg) already existed; the offenders had bypassed it. Now there are siblings — pkgCacheClean, oldKernelClean, bootloaderRefresh, svcCmd, svcLogs, hasTimers — and detection gained an init field (systemd / openrc / runit).
  2. Say when the concept doesn't apply. On an image-based system, "remove old kernels" is answered with there is nothing to remove, and here is why. A null is more honest than a plausible command.
  3. Test the invariants. There is now a test that reads every command the checks hand to the runner — 145 call sites — and fails on sudo, on a mutating verb, on a service manager told to act, or on a package manager in a non-query mode. The tool's promise is "read-only, and it never changes anything"; that should not be a sentence in a README, it should be a test that fails.

What I'd take away

  • If your tool prints commands, your commands are an API. They run on machines you have never seen.
  • "It works on my distro" is a distribution problem, not an edge case. Fedora, Debian and Arch are maybe half your users.
  • Naming a distro in a string is an admission. (Fedora/Bazzite) in a fix means nobody ran it on Bazzite.
  • A wrong command is worse than no command. "Use your distribution's package manager" is a useless sentence, and it is still better than sudo dnf install on a machine where that fails.

Linux Doctor is a read-only health checker for Linux: it explains every finding
and gives the exact command that fixes it. 0.8.0 also brings a new interface.
Free and open source: https://github.com/7sh1d0w7x/linux-doctor

If you run it on a distro I haven't covered, I'd like the report — especially
if the advice is wrong. That is how this post happened.

Top comments (0)