runv-server

server tooling for runv.club
Log | Files | Refs | README

commit e203a8e4b3ffa2e7d104ef0683efc149eade640f
parent f2732bd78e052572dd2ad915070018980dd162cd
Author: Pablo Murad <pblmrd@gmail.com>
Date:   Wed, 13 May 2026 22:08:22 -0300

Mariela Boca Murcha

Diffstat:
Mscripts/admin/remove_runv_jails.py | 21+++++++++++++++------
Mscripts/admin/runv_jail.py | 23+++++++++++++++++++++--
2 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/scripts/admin/remove_runv_jails.py b/scripts/admin/remove_runv_jails.py @@ -106,6 +106,7 @@ def main(argv: list[str] | None = None) -> int: users = [args.user.strip()] if args.user else group_members() users = [u for u in users if u and not runv_jail.jail_skip_username(u)] + failures = 0 if not users: log.info("nenhum membro em %s", runv_jail.RUNV_JAILED_GROUP) for username in users: @@ -115,12 +116,17 @@ def main(argv: list[str] | None = None) -> int: log.warning("%s não existe em passwd; ignorado", username) continue log.info("--- removendo jail de %s", username) - runv_jail.teardown_runv_jail_for_user( - username, - Path(pw.pw_dir), - log, - dry_run=bool(args.dry_run), - ) + try: + runv_jail.teardown_runv_jail_for_user( + username, + Path(pw.pw_dir), + log, + dry_run=bool(args.dry_run), + ) + except Exception as e: + failures += 1 + log.error("%s: falha ao remover jail: %s", username, e) + continue if not args.keep_sshd_dropin: try: @@ -129,6 +135,9 @@ def main(argv: list[str] | None = None) -> int: log.error("%s", e) return 1 + if failures: + log.error("concluído com %d falha(s)", failures) + return 1 log.info("concluído") return 0 diff --git a/scripts/admin/runv_jail.py b/scripts/admin/runv_jail.py @@ -22,6 +22,18 @@ def _run(cmd: list[str], *, log: logging.Logger) -> subprocess.CompletedProcess[ return subprocess.run(cmd, capture_output=True, text=True, timeout=600) +def is_mounted(path: Path, log: logging.Logger) -> bool: + """Detecta mountpoint usando findmnt quando disponível; fallback para os.path.ismount.""" + p = str(path.resolve()) + if shutil.which("findmnt") is not None: + r = _run(["findmnt", "-R", "--target", p], log=log) + if r.returncode == 0 and (r.stdout or "").strip(): + return True + if r.returncode not in (0, 1): + log.debug("findmnt %s: %s", p, (r.stderr or r.stdout or "").strip()) + return os.path.ismount(path) + + def ensure_runv_jailed_group(log: logging.Logger) -> None: r = _run(["groupadd", "-f", RUNV_JAILED_GROUP], log=log) if r.returncode != 0: @@ -146,13 +158,19 @@ def remove_user_from_jailed_group(username: str, log: logging.Logger) -> None: def unbind_jail_home(jail_home: Path, log: logging.Logger) -> None: """Desmonta o bind em ``jail_home`` se estiver montado.""" - if not os.path.ismount(jail_home): + if not is_mounted(jail_home, log): log.debug("jail: %s não está montado", jail_home) return r = _run(["umount", str(jail_home.resolve())], log=log) if r.returncode != 0: err = (r.stderr or r.stdout or "").strip() - raise RuntimeError(f"umount {jail_home}: {err}") + log.warning("umount %s falhou (%s); tentando lazy umount", jail_home, err) + lazy = _run(["umount", "-l", str(jail_home.resolve())], log=log) + if lazy.returncode != 0: + lazy_err = (lazy.stderr or lazy.stdout or "").strip() + raise RuntimeError(f"umount {jail_home}: {err}; umount -l: {lazy_err}") + log.info("jail: lazy umount em %s", jail_home) + return log.info("jail: desmontado bind em %s", jail_home) @@ -274,6 +292,7 @@ def teardown_runv_jail_for_user( remove_fstab_bind(real_home, jail_home, log) remove_user_from_jailed_group(username, log) if jail_root.is_dir(): + unbind_jail_home(jail_home, log) shutil.rmtree(jail_root, ignore_errors=False) log.info("jail: removido %s", jail_root) elif jail_root.exists():