#!/usr/bin/with-contenv bash # 等待微信主界面登录完成(检测到足够大的主窗口),避免未登录时 bridge # 狂刷日志/任务失败。超时 10 分钟仍未登录则放弃启动。 WAITED=0 MAX_WAIT=600 while true; do # 通过 wechat 进程 PID 查找窗口,过滤出面积足够大的主窗口 wid="" area=0 pid=$(pgrep -f "/config/wechat/opt/wechat/wechat" | head -1) if [ -n "$pid" ]; then for candidate in $(xdotool search --pid "$pid" 2>/dev/null); do info=$(xdotool getwindowgeometry --shell "$candidate" 2>/dev/null) if [ -n "$info" ]; then eval "$info" a=$((WIDTH * HEIGHT)) if [ "$a" -gt "$area" ]; then area=$a wid=$candidate fi fi done fi # 登录后主窗口面积通常 > 300000;登录窗口/扫码窗口面积较小 if [ "$area" -ge 300000 ]; then echo "woc-bridge: 检测到微信已登录主窗口(area=${area}),等待 60s 让微信完全就绪后再启动 bridge" >&2 sleep 60 echo "woc-bridge: 等待结束,启动 bridge" >&2 break fi sleep 3 WAITED=$((WAITED + 3)) if [ "$WAITED" -ge "$MAX_WAIT" ]; then echo "woc-bridge: 等待微信登录超时(${WAITED}s),暂不启动 bridge" >&2 # s6 服务退出码 0 会被视为正常结束并自动重启;用 sleep + 退出 0 # 让服务进入休眠,用户登录后可通过重启容器或手动 s6-svc -u 唤醒 sleep infinity exit 0 fi done # 以 abc 用户身份运行(与微信同 X 会话,才能操作微信窗口) # s6-setuidgid 不接受 VAR=value 参数,须先用 s6-env 设环境变量再切用户 # 校验 ptrace 权限(key_extractor 读微信进程内存需要) PTRACE_SCOPE="/proc/sys/kernel/yama/ptrace_scope" if [ -e "$PTRACE_SCOPE" ]; then if echo 0 > "$PTRACE_SCOPE" 2>/dev/null; then echo "woc-bridge: ptrace_scope 已设置为 0" >&2 else echo "woc-bridge: 无法写入 ptrace_scope(可能需要 --privileged 或 SYS_PTRACE capability)" >&2 fi else # 通过 CapEff 检查是否持有 SYS_PTRACE (bit 12) CAP_EFF=$(awk '/^CapEff:/{print $2}' /proc/self/status 2>/dev/null) if [ -n "$CAP_EFF" ] && [ $((0x${CAP_EFF} & 0x1000)) -ne 0 ]; then echo "woc-bridge: 宿主机未启用 YAMA,但容器已持有 SYS_PTRACE,key 提取仍可尝试" >&2 else echo "woc-bridge: 宿主机未启用 YAMA 且容器未持有 SYS_PTRACE,自动 key 提取可能不可用" >&2 fi fi exec s6-env DISPLAY=${DISPLAY:-:1} XAUTHORITY=/config/.Xauthority \ s6-setuidgid abc \ python3 /opt/woc-bridge/server.py \ --listen 0.0.0.0:8088 \ --wechat-db /config \ --display ${DISPLAY:-:1}