Ubunatic Coding

Linux · sync(1) wrapper

psync makes sync visible.

sync(1) blocks until every dirty page is written back, with zero feedback. psync polls /proc/meminfo's Dirty/Writeback counters while it runs, prints a live line and a summary — and with -F can stay running, resyncing a scoped target whenever it changes again.

Early days: no tagged release yet — install from main. Linux only (reads /proc, uses inotify). AGPL-3.0-or-later.

psync -F /mnt/secure
dirty 972.8 MiB, writeback 51.2 MiB  (0s elapsed, -- left)
dirty 520.0 MiB, writeback 27.4 MiB  (1s elapsed, 1s left)
dirty 149.1 MiB, writeback 7.8 MiB   (2s elapsed, 0s left)
dirty 12.2 MiB, writeback 659.5 KiB  (4s elapsed, 0s left)
dirty 0 B, writeback 0 B             (4s elapsed, 0s left)
sync complete
  duration:        4s
  samples taken:   9
  dirty at start:  972.8 MiB
  writeback peak:  51.2 MiB
  unflushed peak:  1024.0 MiB
watching /mnt/secure for changes (Ctrl-C to stop)...
PSYNC(1) General Commands Manual PSYNC(1)

Name

psync — run sync(1) with live write-back progress, a completion summary, and optional follow mode

Synopsis

psync [-d] [-f] [-i interval] [-F] [-w] [--debounce dur] [--min-interval dur] [FILE...]
psync demo [--duration dur] [--size-mb n]

Description

sync(1) flushes every dirty page in the kernel's page cache to disk, blocking until it's done — with no indication of how much data is left or how fast it's draining. psync starts sync(1) in the background and polls Dirty/Writeback from /proc/meminfo while it runs, printing a live progress line and a summary once the flush completes.

On fast local disks a real flush is often too quick to watch — the kernel starts flushing dirty pages in the background well before sync(1) is even called, once vm.dirty_background_ratio is crossed. Run psync demo to see the display in action without needing slow media, root, or leftover files.

Options

-i, --interval duration
Polling interval for /proc/meminfo. Default 500ms.
-d, --data
Sync only file data, no unneeded metadata (passed through to sync(1)).
-f, --file-system
Sync the file systems that contain the given FILEs, instead of just the files.
-F, --follow
Stay running: after each sync, watch FILEs and resync whenever they change again. See FOLLOW MODE below.
-w, --watch
Watch write-back progress without calling sync.
--debounce duration
Follow mode: quiet window after a change before resyncing. Default 500ms.
--min-interval duration
Follow mode: minimum time between resyncs, independent of event volume. Default 1s.

Follow mode (-F)

-F keeps psync running: after each sync it watches the given FILEs (or a directory's direct entries — non-recursive) via inotify(7), and resyncs whenever they change again, until interrupted.

Follow mode always needs a scoped target. There is deliberately no target-less "watch everything" mode: /proc/meminfo's Dirty counter is system-wide, so triggering resyncs off it would fire on unrelated writes from any process — the opposite of what was asked for, and needless extra write cycles on the underlying media. If psync -F is run with no target, it lists real mounted filesystems (from /proc/self/mountinfo) and prompts for one, which becomes an implicit -f target.

Two independent guards keep repeated syncing safe rather than trigger-happy: --debounce coalesces a burst of writes into a single resync, and --min-interval enforces a hard floor between syncs regardless of how often changes arrive.

Commands

demo [--duration dur] [--size-mb n]
Watch a simulated flush — a synthetic, deterministic drain instead of a real sync(1) call. No real disk I/O, no root, no leftover files. Default: ~2GB over 8s.

Examples

$ psync
dirty 21.9 MiB, writeback 0 B  (0s elapsed, -- left)
sync complete
  duration:        142ms
  ...

$ psync -f /mnt/secure
# sync only the file system containing this path

$ psync -F important-file.db
# sync, then keep watching and resync on changes

$ psync -F
# no target: pick a mounted filesystem to watch

$ psync demo --duration 15s --size-mb 4096
# try the live display without touching a real disk

How it works

Key components live in Go packages under internal/:

meminfo
reads Dirty/Writeback from /proc/meminfo; defines the Reader type real and simulated sources satisfy.
monitor
polls a Reader on an interval, tracking the peak unflushed total.
simulate
synthetic Reader that decays a given size to zero over a given duration — backs demo and monitor's tests.
watch
raw inotify wrapper reporting changes to a fixed set of files/directories — the resync trigger for follow mode.
pick
lists real mounted filesystems and prompts for one — backs bare psync -F.
app
orchestration: runs sync(1), drives the monitor, formats output, runs the follow loop.

Installation

# via go install
$ go install codeberg.org/ubunatic/psync@latest

# or from source
$ git clone https://codeberg.org/ubunatic/psync
$ cd psync
$ make install

See also

sync(1), fsync(2), inotify(7), proc(5)

Author

Uwe Jugel <uwe@ubunatic.com>

psync 0.1 2026-08-16 PSYNC(1)