多shell脚本嵌套调用的环境 向外访问网络时暂停 使用者进行替代操作

前言

上一篇我们将 向外访问网络时暂停 使用者进行替代操作 的方案应用在了 安装233boy 脚本上面

进一步的, 能不能继续拓展应用范围, 用在, 比如, 我自己的 极简一键脚本中?
bash <(curl -L https://github.com/crazypeace/xray-vless-reality/raw/main/install.sh)

试试

发现有问题.

我的脚本调用了xray官方安装脚本, 在这个嵌套调用的场景下, 被嵌套调用的脚本里的网络访问就没有被抓到.

去问了好多个GPT, 回答了一堆什么线程啊, 进程啊, 环境啊, 继承啊, ... 
给了我几个解决方案, 试了一下也是不行. 说明回答的那些理论就是狗屁.

改进

那就来个根本的方案, 在系统PATH中安插假的 curl 和 wget.

我们上个方案里的 curl, wget, __fake_net_common 函数, 都变成可执行文件, 放到 PATH里去. 逻辑都是现成的, 不用大改.
最终我们得到这样的 4 个脚本
fake-curl-wget-v2.sh
#!/usr/bin/env bash
# ==========================================
# 拦截 curl 和 wget 调用,用于调试/离线测试
# ==========================================

# 在PATH中设置假命令 curl wget mkdir -p /tmp/fakebin if [[ ":$PATH:" != *:/tmp/fakebin:* ]]; then   export PATH="/tmp/fakebin:$PATH" fi
# 清理调用记数文件 rm /tmp/fakebin/*
# 放入假命令文件 cp __fake_net_common.sh /tmp/fakebin/fake_net_common chmod +x $_ cp __fake_curl.sh /tmp/fakebin/curl chmod +x $_ cp __fake_wget.sh /tmp/fakebin/wget chmod +x $_
# ------------------------------------------ # 提示加载成功 # ------------------------------------------ echo "[INFO] 所有 curl / wget 调用将被拦截"

__fake_net_common.sh
#!/usr/bin/env bash

# 调用计数文件(全局共享) COUNT_FILE="/tmp/fakebin/fake_curl_wget_count.tmp" # 如果文件不存在, 初始化为0 if [[ ! -f "$COUNT_FILE" ]]; then     echo "0" > "$COUNT_FILE" fi
# 锁文件 LOCK_FILE="${COUNT_FILE}.lock"
# 使用文件锁保护整个执行过程 {     flock 200 || {         echo "[ERROR] 无法获取锁,超时" >&2         return 1     }
    cmd="$1"; shift
    fake_net_call_count=$(cat "$COUNT_FILE")     fake_net_call_count=$((fake_net_call_count + 1))     echo "$fake_net_call_count" > "$COUNT_FILE"
    echo "[DEBUG] curl/wget call # $fake_net_call_count" >&2     echo "[DEBUG] Current directory: $(pwd)" >&2
    printf '[DEBUG] Command: %s ' "$cmd" >&2     printf '%q ' "$@" >&2     printf '\n' >&2
    # 是否找到预设命令     has_preset=0          # 根据调用序号执行预设命令     case "$fake_net_call_count" in #           1) #               # 示例:第1次调用的预设命令 #               # echo "preset response for call 1" #               has_preset=1 #               ;;         *)             # 未设置预设命令             echo "[DEBUG] 未设置预设命令" >&2             has_preset=0             ;;     esac
    echo >&2
    # 如果没有预设命令,进入交互模式     if [[ "$has_preset" -eq 0 ]]; then         echo "[WARN] 序号 $fake_net_call_count 未设置预设命令" >&2         echo "" >&2         echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" >&2         echo "请根据 curl/wget的原始命令及参数 进行操作:" >&2         echo " - 如需保存文件:请手动上传文件到目标位置,然后输入空行继续" >&2         echo ' - 如需输出到stdout:请输入替代命令(如: echo "something" 或 cat /path/file)' >&2         echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" >&2         echo "[INPUT] 请输入替代命令(或按回车表示文件已上传): " >&2
        # 读取用户输入         read -r user_input </dev/tty
        # 用户输入空行,表示文件已手动上传         # 什么都不用做
        # 用户输入非空行, 则视为替代命令,执行它         if [[ -n "$user_input" ]]; then             # 临时移除fake路径,使用真实的curl/wget             export PATH=$(echo "$PATH" | sed 's|^\(/tmp/fakebin:\)\+||')                          eval "$user_input"             echo >&2                          # 恢复PATH 加入fake路径             export PATH="/tmp/fakebin:$PATH"         fi     fi
} 200>"$LOCK_FILE"
# 永远返回成功 exit 0

__fake_curl.sh
fake_net_common curl "$@"

__fake_wget.sh
fake_net_common wget "$@"

我们把它们4个都上传到VPS上, 再试试.

搞定!


Github



========

相关推荐


评论