grid-node-watch
A generic process-watcher grid-node
backend plugin -- point it at any program by name via a config file,
instead of writing a dedicated plugin (like
grid-node-gimps) for each one. See
grid_node_watch/backend.py for the implementation and an honest note on
what's been verified so far vs. left untested.
Install
pip install grid-node grid-node-watch
grid-node discovers this package automatically via its
grid_node.backends entry point -- no config-file edit or code change in
grid-node itself.
Configure
Write ~/.local/share/grid-node-watch/targets.json (override the path
with GRIDKEEPER_WATCH_CONFIG):
{
"targets": [
{
"name": "blender-render",
"match": "blender",
"start_cmd": ["/usr/bin/blender", "-b", "render.blend"],
"stop_signal": "SIGTERM"
},
{
"name": "matlab",
"match": "MATLAB"
}
]
}
name-- id used in the hub's start/stop payloads and inget_status().match-- case-insensitive substring matched against each running process's name and its full command line, so a program invoked through a wrapper script or an absolute path is still found.start_cmd-- optional. Omit it for a watch-only target (e.g. MATLAB above): grid-node will report whether it's running but refuse to start it. With it, grid-node can launch the program itself.stop_signal-- optional, defaults toSIGTERM.
What this backend can and can't do
- Reports
running,pid,cpu_percent,mem_percent,uptime_seconds, and the matchedcmdlinefor each configured target, once per status poll -- shows up in the hub dashboard the same as any backend, via the generic fallback UI (GenericBackendBlock.jsx) since it's not a built-in like BOINC/FAH. - Detects a target whether grid-node started it or a human did -- it's a
process-list scan (
psutil.process_iter), not a pidfile grid-node itself wrote. That's the point: it works on a program you're already running by hand. start/stopare the only remote controls (like GIMPS, no live pause/resume) -- and only for targets withstart_cmdconfigured.- No per-program insight (no log tailing, no work-unit status) -- that's
the tradeoff for not needing a bespoke plugin per program.
cpu_percenton the very first poll after a process is (re)matched reads0.0; it's psutil comparing against no prior baseline yet, not a bug -- it becomes meaningful from the next poll onward.
What's actually verified
tests/test_backend.py (12 tests) exercises real psutil process
discovery against real background processes the tests spawn independently
of this plugin, plus a regression test for a real bug found below.
Beyond unit tests, this was live-verified end-to-end on 2026-08-24 against
a real hub+node pair (a scratch hub instance and a scratch-enrolled node,
so the real dev machine's own hub/node setup was untouched): a real
ffmpeg process (1080p libx264 encode, genuinely CPU-bound, not a toy sleep
loop) was started via a hub-issued command, tracked across several live
status polls -- cpu_percent reflected real multi-core load (~650%,
cross-checked against ps directly) and uptime_seconds increased
correctly between polls -- then stopped cleanly via a second hub command,
confirmed both through the hub's status view and by checking the OS
process directly. GET /api/backends was confirmed to report this
backend's label and actions correctly, which is what the dashboard's
GenericBackendBlock.jsx fallback UI renders from -- the actual browser
rendering itself wasn't screenshotted, but the data contract it consumes
was.
A real bug was found and fixed in that session: the first version of
_find_process() matched the target string against the entire command
line, which produced a genuine false positive -- it matched this very
plugin's own test harness, because a shell one-liner being used to test
it happened to contain the word "ffmpeg" as data inside a quoted argument,
not as the actual program. Matching is now restricted to the process's
name, argv[0]'s basename, and (for scripts launched through a known
interpreter) argv[1]'s basename -- see _find_process()'s docstring for
the exact reasoning and its own remaining known gap (a target launched as
python3 -m mymodule, where the identifying name is past argv[1], won't
be found).
Still not tried: a real-world long-running desktop program like an actual MATLAB/Blender install, or two configured targets running concurrently.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file grid_node_watch-0.1.0.tar.gz.
File metadata
- Download URL: grid_node_watch-0.1.0.tar.gz
- Upload date:
- Size: 9.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f96a4ebcb61c4b24290ce8fe0a5352be5ee2f7a05bffe5bee9da61a502f16876
|
|
| MD5 |
025ffdcc620b23455a2cae1f955ca1d4
|
|
| BLAKE2b-256 |
5032451ce409dc571e3abb5825ba428941e04c6785dc144f0ec899bcab5c1e70
|
File details
Details for the file grid_node_watch-0.1.0-py3-none-any.whl.
File metadata
- Download URL: grid_node_watch-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
66774ef7af7c0ac93836885badf3e9cc4ae8595186967ce0ff21143e95691b5c
|
|
| MD5 |
57c93d7501c3c79f0ac2f42d291ece3b
|
|
| BLAKE2b-256 |
99415d2227329d6e7179b0c4459e4e5f9960c6a5c3474870982e62cded8dd53e
|