- docs/did_you_know/: one short tip per feature added since May 2026 (<date>-<slug>.md, YAML front matter: added/tags/details), listed newest first; index.md describes the format for adding more. - New pages for features that had none: launching, command_history, tab_completion, live_gui, tweak, scanning, status_server, channel_access, shared_files, schematic_panels. Wired into index.rst together with the existing queues page. - Fix archiver_stripchart/listening_monitor: the method is archiver.strip_plot (strip_chart does not exist on DataHub); document the per-device .strip_plot(). - NAMESPACE_MONITOR_FORMAT.md: scan monitoring is wired into Daq's scan callbacks since 2026-09-09. - scripts/eco-docs (+ -install-user-service): build the docs from an own clone and serve them over HTTP as user systemd units, rebuilt by a timer; a failed build never replaces the served site.
2.8 KiB
Shared files: group permissions on results and configuration
Several accounts write to the same trees: the shared gac-bernina account and
personal ones. That applies to the results under /sf/<instrument>/data/<pgroup>/res
(run data, run tables, scan info, presets, ...) and to the shared configuration
under /sf/<instrument>/code/<account>/. Everyone in the group must be able to
add to and rewrite these, which needs directories at 2775 (group-writable
plus setgid) and files at 664. Python's defaults (mkdir → 755,
open(..., "w") → 644) silently produce files nobody else can change.
Typically you only notice when the next person can't store a run.
eco now creates everything it writes with the right mode and group, and warns
(without failing) when it meets something wrong. The warning names the
account that owns the offending path, since only that account (or root)
can fix it, and gives the chgrp/chmod command.
Finding out what is wrong
from eco.utilities import datafiles
datafiles.check_group_writable("/sf/bernina/data/p23415/res/run_data")
This lists every level that is not group-writable or has the wrong group, together with its owner. It changes nothing.
Repairing a tree
Run this as the account that owns the tree. A personal account cannot
repair gac-bernina's directories.
datafiles.repair_tree("/sf/bernina/code/gac-bernina/eco_cnf_bernina/memory")
It fixes everything this account can fix below the path, and lists the owner of everything it cannot.
replace_unowned=True goes further: it replaces entries owned by another
account with identical copies owned by this one. That changes ownership and
cannot be undone without root, so try dry_run=True first. dry_run only
affects that ownership step; the ordinary chmod/chgrp fixes are still applied.
Which group?
Inside a pgroup tree, the pgroup. Elsewhere, the group of the enclosing directory (what setgid would have given). Only groups this account belongs to can be set.
For code that writes files
Use these instead of the plain calls, rather than adding a chmod by hand:
| Instead of | Use |
|---|---|
Path(p).mkdir(parents=True) |
datafiles.ensure_dir(p): applies 2775 to every level it creates |
open(p, "w") |
datafiles.open_group_writable(p, "w") |
a file written by another library (to_pickle, shutil.copyfile, ...) |
datafiles.ensure_group_writable(p) afterwards |
Never chmod(0o775) a directory: that clears the setgid bit, after which new
files get the creator's primary group instead of the pgroup.
If an existing file is not writable by this session but its directory is,
open_group_writable replaces the file (write to a temporary file, then
rename) instead of failing, so a second account can still store a value. This
is reported once, since it changes the file's owner.