jupyter服务器创建账户加映射对外账户地址

发布于:2025-08-13 ⋅ 阅读:(20) ⋅ 点赞:(0)

以下是根据需求生成的命令、检查脚本及启动脚本,按步骤执行即可:

一、创建test1-test10用户(跳过已存在的test3)

# 循环创建用户,若用户已存在则跳过
for U in test1 test2 test3 test4 test5 test6 test7 test8 test9 test10; do
  if ! id "$U" &>/dev/null; then
    # 用户不存在时创建,家目录自动生成,默认shell为bash
    useradd -m -s /bin/bash "$U"
    # 为新用户设置密码(可根据需要修改密码)
    echo "$U:StrongPassword123" | chpasswd
    echo "用户 $U 创建完成"
  else
    echo "用户 $U 已存在,跳过创建"
  fi
done

二、检查必要组件是否安装

创建检查脚本 check_dependencies.sh,用于验证 code-serverjupyterlabjupyter-server-proxy 是否安装:

#!/bin/bash

# 检查code-server是否安装
if command -v code-server &>/dev/null; then
  echo "✅ code-server 已安装,版本:$(code-server --version | head -n1)"
else
  echo "❌ code-server 未安装,请先执行安装命令:curl -fsSL https://code-server.dev/install.sh | sh"
fi

# 检查jupyterlab是否安装
if command -v jupyter &>/dev/null && jupyter lab --version &>/dev/null; then
  echo "✅ JupyterLab 已安装,版本:$(jupyter lab --version)"
else
  echo "❌ JupyterLab 未安装,请先执行安装命令:pip install jupyterlab"
fi

# 检查jupyter-server-proxy是否安装
if pip show jupyter-server-proxy &>/dev/null; then
  echo "✅ jupyter-server-proxy 已安装,版本:$(pip show jupyter-server-proxy | grep Version | awk '{print $2}')"
else
  echo "❌ jupyter-server-proxy 未安装,请先执行安装命令:pip install jupyter-server-proxy"
fi

# 检查jupyter-server-proxy扩展是否启用
if jupyter server extension list 2>/dev/null | grep -q "jupyter_server_proxy.*enabled"; then
  echo "✅ jupyter-server-proxy 扩展已启用"
else
  echo "❌ jupyter-server-proxy 扩展未启用,请执行:jupyter server extension enable --sys-prefix jupyter_server_proxy"
fi

执行检查脚本:

chmod +x check_dependencies.sh
./check_dependencies.sh

根据输出提示,安装缺失的组件(若有)。

错误原因:su -c 命令中换行符和引号的组合导致命令被拆分成多行执行,使得 --bind-addr 被误认为独立命令(而非 code-server 的参数)。核心是命令格式的语法问题。

解决方法:用紧凑格式避免换行解析错误

code-server 的启动命令合并为单行(或严格控制换行位置),确保所有参数都属于 code-server 命令。以下是修复后的脚本(直接复制粘贴生成):

cat << 'EOF' > start_multi_user_ide_v2.sh
#!/bin/bash
set -euo pipefail

# 配置参数
USERS=(test1 test2 test3 test4 test5 test6 test7 test8 test9 test10)
BASE_PORT=8890
JUPYTER_PORT=8910
JUPYTER_CONFIG_DIR="/opt/conda/etc/jupyter/jupyter_server_config.d"
CHECK_DELAY=2

# 步骤1:配置Jupyter代理
echo "🔧 配置Jupyter代理允许的端口(${BASE_PORT}-$((BASE_PORT+9)))..."
mkdir -p "$JUPYTER_CONFIG_DIR"
cat > "$JUPYTER_CONFIG_DIR/proxy-allowed-ports.json" << 'EOF_INNER'
{
  "ServerProxy": {
    "allowed_ports": [8890,8891,8892,8893,8894,8895,8896,8897,8898,8899]
  }
}
EOF_INNER
echo "✅ Jupyter代理配置已更新"


# 步骤2:启动各用户Code-Server(修复命令格式)
echo -e "\n🚀 开始启动各用户Code-Server..."
for idx in "${!USERS[@]}"; do
  USER="${USERS[$idx]}"
  PORT=$((BASE_PORT + idx))
  HOME_DIR="/home/${USER}"
  DATA_DIR="${HOME_DIR}/.local/share/code-server"
  EXT_DIR="${HOME_DIR}/.local/share/code-server/extensions"
  LOG_FILE="${HOME_DIR}/code-server.log"
  CONFIG_FILE="${HOME_DIR}/.config/code-server/config.yaml"

  # 检查家目录
  if [ ! -d "$HOME_DIR" ]; then
    echo "❌ 跳过用户${USER}:家目录不存在"
    continue
  fi

  # 备份旧配置
  if [ -f "$CONFIG_FILE" ]; then
    echo "⚠️ 备份用户${USER}旧配置文件..."
    mv "$CONFIG_FILE" "${CONFIG_FILE}.bak"
  fi

  # 创建目录并授权
  echo "📂 准备用户${USER}目录..."
  mkdir -p "${DATA_DIR}" "${EXT_DIR}"
  chown -R "${USER}:${USER}" "${HOME_DIR}/.local" || {
    echo "❌ 用户${USER}目录授权失败"
    continue
  }

  # 停止旧进程
  if ss -ltnp | grep -q ":${PORT} "; then
    echo "🔌 关闭端口${PORT}旧进程..."
    pkill -9 -f "code-server.*:${PORT}" || echo "⚠️ 无旧进程"
    sleep $CHECK_DELAY
  fi

  # 核心修复:用单行紧凑格式传递命令,避免换行解析错误
  echo "▶️ 启动用户${USER}(端口${PORT})..."
  su - "$USER" -c "nohup code-server --auth none --bind-addr 127.0.0.1:${PORT} --user-data-dir '${DATA_DIR}' --extensions-dir '${EXT_DIR}' --config /dev/null '${HOME_DIR}' > '${LOG_FILE}' 2>&1 & sleep 1" || {
    echo "❌ 用户${USER}启动命令执行失败,日志:${LOG_FILE}"
    continue
  }

  # 检查启动状态
  sleep $CHECK_DELAY
  if ss -ltnp | grep -q "127.0.0.1:${PORT}"; then
    echo "✅ 用户${USER}启动成功"
  else
    echo "❌ 用户${USER}启动失败!日志:"
    tail -n 5 "$LOG_FILE"
  fi
done


# 步骤3:启动JupyterLab
echo -e "\n🌐 启动JupyterLab(端口${JUPYTER_PORT})..."
if ss -ltnp | grep -q ":${JUPYTER_PORT} "; then
  echo "🔌 关闭Jupyter旧进程..."
  pkill -9 -f "jupyter-lab.*:${JUPYTER_PORT}"
  sleep $CHECK_DELAY
fi

nohup jupyter lab \
  --ip=0.0.0.0 \
  --port="${JUPYTER_PORT}" \
  --allow-root \
> /var/log/jupyterlab.log 2>&1 &

sleep $((CHECK_DELAY * 2))
if ss -ltnp | grep -q ":${JUPYTER_PORT} "; then
  echo "✅ JupyterLab启动成功"
else
  echo "❌ JupyterLab启动失败,日志:"
  tail -n 5 /var/log/jupyterlab.log
fi


# 汇总结果
echo -e "\n📊 启动结果汇总:"
echo "Code-Server监听情况:"
ss -ltnp | grep -E ":889[0-9] " || echo "⚠️ 未发现监听端口"

echo -e "\n🌐 访问地址:"
echo "JupyterLab:http://36.151.192.85:23589/lab?token=$(grep -oP 'token=\K[^&]+' /var/log/jupyterlab.log | head -n1)"
echo "test1 Code-Server:http://36.151.192.85:23589/proxy/8890/"
EOF

核心修复说明:

su -c 中的 code-server 命令改为单行紧凑格式,避免因换行导致的参数拆分:
原多行命令容易被shell解析为多个独立命令,而单行格式确保 --auth none--bind-addr 等参数都属于 code-server 命令,解决“--bind-addr: command not found”错误。

使用方法:

  1. 复制上面的命令粘贴到终端,自动生成脚本。
  2. 运行脚本:
    chmod +x start_multi_user_ide_v2.sh
    ./start_multi_user_ide_v2.sh
    

此时 code-server 会正确接收所有参数,免密启动并监听对应端口。