多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
========
