From 5506b950e390d69476648be9c4c4c56ccc6408b3 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Wed, 22 Oct 2025 19:40:22 +0800 Subject: [PATCH] tmp --- .hub/jupyter_config_backup.py | 58 +++++++++++++++++------------------ 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/.hub/jupyter_config_backup.py b/.hub/jupyter_config_backup.py index 0557042..d1b501a 100644 --- a/.hub/jupyter_config_backup.py +++ b/.hub/jupyter_config_backup.py @@ -1,15 +1,18 @@ +""" +按组挂载 Git 资源(只读) + 自动建用户加组 +资源路径 /home/zhangyi/jupyter-collection +控制文件 /home/zhangyi/jupyter-collection/.hub/resource_map.ini +""" import os, grp, pwd, shutil, subprocess, configparser from pathlib import Path from jupyterhub.spawner import Spawner -# host端的仓库目录 -SHARED_ROOT = Path("/home/zhangyi/jupyter-collection") -# jyputerhub用户home目录 -USER_HOME = Path("/home/jupyter-{username}") -# 分组信息路径 -CTRL_FILE = SHARED_ROOT / ".hub" / "resource_map.ini" +# ---------- 基础路径 ---------- +SHARED_ROOT = Path("/home/zhangyi/jupyter-collection") # Git 仓库 +USER_HOME = Path("/home/jupyter-{username}") +CTRL_FILE = SHARED_ROOT / ".hub" / "resource_map.ini" -# ========== 2. 读控制表 ========== +# ---------- 工具:读控制表 ---------- def load_ctrl(): """返回 组->资源 和 组->用户 两个字典""" cfg = configparser.ConfigParser() @@ -20,26 +23,25 @@ def load_ctrl(): for g, v in cfg.items("users")} return res_map, usr_map -# ========== 3. post_auth_hook:自动建用户+加组 ========== +# ---------- post_auth_hook:自动建用户+加组 ---------- def ensure_user_and_groups(authenticator, handler, authentication): username = authentication['name'] res_map, usr_map = load_ctrl() - # 该用户应属的组 wanted_groups = [g for g, users in usr_map.items() if username in users] - if not wanted_groups: # 控制文件里没写就什么都不做 - return authentication + if not wanted_groups: + return authentication # 控制文件里没有就什么都不做 # 确保组存在 for g in wanted_groups: subprocess.run(["groupadd", "-f", g], check=False) - # 若系统账号不存在则创建(Hub 自己会创 home,这里确保 shell 账号) - #if subprocess.run(["id", "-u", username], capture_output=True).returncode != 0: - # subprocess.run([ - # "useradd", "-m", "-s", "/bin/bash", - # "-d", str(USER_HOME).format(username=username), username - # ], check=False) + # 系统账号不存在就创建(TLJH 会自己建 home,这里只确保用户存在) + if subprocess.run(["id", "-u", username], capture_output=True).returncode != 0: + subprocess.run([ + "useradd", "-m", "-s", "/bin/bash", + "-d", str(USER_HOME).format(username=username), username + ], check=False) # 加组(幂等) for g in wanted_groups: @@ -49,17 +51,17 @@ def ensure_user_and_groups(authenticator, handler, authentication): c.Authenticator.post_auth_hook = ensure_user_and_groups -# ========== 4. pre_spawn_hook:重建干净 home + 只读挂 Git 资源 ========== +# ---------- pre_spawn_hook:只清 shared 并挂载 ---------- def prepare_user(spawner: Spawner): username = spawner.user.name user_dir = Path(str(USER_HOME).format(username=username)) - # 1. 重建空 home(保证无残留) - if user_dir.exists(): - shutil.rmtree(user_dir) - user_dir.mkdir(mode=0o700, parents=True, exist_ok=True) - # 关键:让 systemd 能进去 - shutil.chown(user_dir, user=username, group=username) + # 1. 只清 shared 目录,保留用户其它文件 + shared = user_dir / "shared" + if shared.exists(): + shutil.rmtree(shared) + shared.mkdir(parents=True, exist_ok=True) + shutil.chown(shared, user=username, group=username) # 2. 读控制表 res_map, _ = load_ctrl() @@ -72,10 +74,8 @@ def prepare_user(spawner: Spawner): return user_groups = {grp.getgrgid(g).gr_name for g in gid_list} - # 4. 挂载该用户该看的资源(只读) - shared = user_dir / "shared" - shared.mkdir(exist_ok=True) - bind_list = [] # 先攒列表 + # 4. 组装 bind_mounts(SystemdSpawner 语法) + bind_list = [] for grp_name in user_groups: for res in res_map.get(grp_name, []): res_path = SHARED_ROOT / res @@ -85,6 +85,6 @@ def prepare_user(spawner: Spawner): 'target': str(shared / res), 'read-only': True, }) - spawner.bind_mounts = bind_list + spawner.bind_mounts = bind_list c.Spawner.pre_spawn_hook = prepare_user \ No newline at end of file