mountx logomountx

mountx CLI

#The mountx CLI

One command that mounts something real, and prints every request the kernel makes.

npx mountx                       # an in-memory tree at ~/mountx
npx mountx /tmp/scratch -t nfs   # somewhere else, over a named transport
npx mountx --help

No root on either platform (unprivileged FUSE wants fusermount3; macOS NFS wants a mountpoint you own), and nothing to clean up but the mountpoint.

Note

It is a demonstration and a test bench, not a mount tool. What it serves is always the bundled memory driver's tree, which exists for exactly as long as the process does. The library is what mounts a real driver.

#What it does

Seeds an in-memory filesystem with a file or two, wraps it in a request logger, and mounts it through mountx/auto — so it picks FUSE on Linux and NFSv3 on macOS. Then it narrates: every lookup, open, read and write the kernel sends, as it happens.

That log is the point. It is the fastest way to see how much traffic a ls -l really is, what the attribute cache absorbs, and how many FUSE requests one syscall becomes.

The metadata polls — lstat, stat, statfs — are the exception, and --verbose puts them back. There is one lstat per listed entry and a desktop session asks statfs on a timer, so by default they are logged only when they fail, where an ENOENT is usually the whole story of the command that caused it. Turn them on when the question is how much traffic there really is.

#Options

flagdefault
[mountpoint] or -m, --mountpoint <path>where to mount~/mountx, or $MOUNTX_MOUNTPOINT
-t, --transport <name>auto, fuse or nfsauto
-q, --quietdo not log filesystem requestsoff
-v, --verboselog the metadata polls too (lstat, stat, statfs)off
-r, --read-onlymount read-onlyoff
--emptystart with an empty tree instead of the seeded oneoff
--allow-otherlet other users see the mount (FUSE; implied under root)off
-h, --helpusage

A leading ~ in the mountpoint is expanded the way a shell would. Ctrl-C unmounts and exits.

#Using it

From another terminal — never from the one serving it, and never from the serving process, for the reason in Troubleshooting:

ls -l ~/mountx
head ~/mountx/README.md
echo 'written from outside' > ~/mountx/note.txt
cat ~/mountx/note.txt

Every one of those shows up in the first terminal as the requests it actually became.

#If it dies without unmounting

A run that was killed rather than Ctrl-C'd leaves the mountpoint in the mount table, answering ENOTCONN — and that is enough for a later mount() to refuse to stack on it. The CLI clears a stale entry at that exact path on the next run, and prints the command to do it by hand if the route needs privileges it does not have:

fusermount3 -u ~/mountx      # FUSE, unprivileged
sudo umount -l ~/mountx      # FUSE, mounted as root
umount -f ~/mountx           # NFS on macOS
sudo umount -l ~/mountx      # NFS on Linux

There is one case it hands back rather than handling: a stale NFS mount on Linux, where umount(8) is neither setuid nor a BSD, so clearing it needs a sudo the CLI will not run for you. The two it does handle are unprivileged for unrelated reasons — fusermount3 -u is setuid, and macOS lets the user who mounted a filesystem unmount it, the same rule that lets NFS mount there without root.

#From source

Working in the repository rather than on the published package:

pnpm mountx          # node src/cli/index.ts
pnpm mountx --help

Source: src/cli/index.ts.

mountx logo

mountx  Write a filesystem in JavaScript, mount it as a real folder.