note/tech/autoupdatepac.sh
2025-11-19 10:16:05 +08:00

153 lines
6.8 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# ** 自动更新 Shadowrocket 配置文件 **
#
# 脚本功能:
# 1. 从 Git 仓库拉取最新的 PAC 文件。
# 2. 下载已存在的 Shadowrocket 配置文件。
# 3. 从 PAC 文件中提取规则并插入到已存在的 Shadowrocket 配置文件中。
# 4. 将合并后的配置文件保存为新的文件。
# ** 切换到脚本所在目录 **
cd "$(dirname "$0")"
# 定义 PAC 文件路径 (假设 PAC 文件在当前 Git 仓库的 pac_file.pac), 已存在配置文件URL, 已存在配置文件名, 输出的自定义配置文件名, 代理组名称, 日志文件名
pac_file="gfw2.pac" # 假设 PAC 文件名为 pac_file.pac 且在当前目录
sr_cnip_ad_conf_url="https://johnshall.github.io/Shadowrocket-ADBlock-Rules-Forever/sr_cnip_ad.conf" # 已存在的 Shadowrocket 配置文件 URL
sr_cnip_ad_conf="sr_cnip_ad.conf" # 下载的已存在的 Shadowrocket 配置文件名 (本地保存文件名)
sr_cnip_ad_custom_conf="sr_cnip_ad_custom.conf" # 输出的自定义 Shadowrocket 配置文件名
#proxy_group_name="select_group" # 默认代理组名称,可根据需要修改
https_proxy_address="http://127.0.0.1:1099" # 代理服务器地址,可根据需要修改
log_file="update.log" # 日志文件名
direct_keyword="var directDomains"
proxy_keyword="var domainsUsingProxy"
# 定义日志输出函数,方便记录日志并同时输出到终端 (可选)
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$log_file"
}
# 记录日志开始标记
log "# --- BEGIN SHADOWROCKET LOG --- $(date '+%Y-%m-%d %H:%M:%S') --- #"
# 设置 HTTPS 代理
export https_proxy="$https_proxy_address"
export http_proxy="$https_proxy_address" # 建议同时设置 http_proxy
log "已设置 HTTPS 代理: $https_proxy"
# Git pull 拉取最新的 PAC 文件
log "正在从 Git 仓库拉取最新的 PAC 文件..."
git pull 2>&1 | tee -a "$log_file" # 将 git pull 的输出也记录到日志
git_pull_status=$?
if [ $git_pull_status -ne 0 ]; then
log "错误Git pull 命令执行失败,请检查 Git 仓库状态或网络连接。"
log "# --- END LOG --- $(date '+%Y-%m-%d %H:%M:%S') --- #" # 记录日志结束标记,即使出错也要记录
exit 1
fi
log "PAC 文件 Git pull 完成。"
# 检查 PAC 文件是否存在 (Git pull 后PAC 文件应该存在于指定位置)
if [ ! -f "$pac_file" ]; then
log "错误PAC 文件未找到:$pac_file,请确认 Git 仓库中存在此文件。"
log "# --- END SHADOWROCKET LOG --- $(date '+%Y-%m-%d %H:%M:%S') --- #" # 记录日志结束标记,即使出错也要记录
exit 1
fi
# 下载 sr_cnip_ad.conf 文件
log "正在下载 sr_cnip_ad.conf 文件..."
curl -m 30 -sSL -o "$sr_cnip_ad_conf" "$sr_cnip_ad_conf_url" 2>&1 | tee -a "$log_file" # 将 curl 的输出也记录到日志
curl_status=$?
if [ $curl_status -ne 0 ]; then
log "错误:下载 sr_cnip_ad.conf 文件失败,请检查网络连接或 URL 是否正确:$sr_cnip_ad_conf_url"
log "# --- END LOG --- $(date '+%Y-%m-%d %H:%M:%S') --- #" # 记录日志结束标记,即使出错也要记录
exit 1
fi
log "sr_cnip_ad.conf 文件下载完成。"
# 初始化用于存储规则的变量
rule_content=""
# 提取 directDomains 列表 (优化 sed 命令,减少反斜杠)
direct_domains_str=$(awk -v direct_keyword="$direct_keyword" '
$0 ~ direct_keyword {flag=1; next}
/}/ {flag=0}
flag
' $pac_file)
# direct_domains_str=$(grep -oP 'var directDomains = \{\K[^\}]*' "$pac_file")
if [ -n "$direct_domains_str" ]; then
while IFS= read -r -d ',' domain_line; do # 使用逗号作为分隔符逐行读取对象内的内容
# 优化后的 sed 命令:使用单引号包裹 sed 命令,并假设域名用双引号包裹,减少转义
domain=$(echo "$domain_line" | awk -F '"' '/:/ {print $2}')
# domain=$(echo "$domain_line" | sed -E 's/^\s*"([^"]+)":.*/\1/;s/^\s+//;s/\s+$//')
if [[ -n "$domain" && "$domain" != "}" ]]; then # 确保域名非空且不是对象结束符
rule_content+="DOMAIN-SUFFIX,$domain,Direct\n"
# rule_content+=",DOMAIN,$domain,direct\n"
fi
done <<< "$(echo "$direct_domains_str" | tr '\n' ',' )" # 将换行符替换为逗号,方便循环处理
fi
# 提取 domainsUsingProxy 列表 (优化 sed 命令,减少反斜杠)
proxy_domains_str=$(awk -v proxy_keyword="$proxy_keyword" '
$0 ~ proxy_keyword {flag=1; next}
/}/ {flag=0}
flag
' $pac_file)
# proxy_domains_str=$(grep -oP 'var domainsUsingProxy = \{\K[^\}]*' "$pac_file")
if [ -n "$proxy_domains_str" ]; then
while IFS= read -r -d ',' domain_line; do # 使用逗号作为分隔符逐行读取对象内的内容
# 优化后的 sed 命令:使用单引号包裹 sed 命令,并假设域名用双引号包裹,减少转义
domain=$(echo "$domain_line" | awk -F '"' '/:/ {print $2}')
#domain=$(echo "$domain_line" | sed -E 's/^\s*"([^"]+)":.*/\1/;s/^\s+//;s/\s+$//')
if [[ -n "$domain" && "$domain" != "}" ]]; then # 确保域名非空且不是对象结束符
rule_content+="DOMAIN-SUFFIX,$domain,Proxy\n"
#rule_content+=",DOMAIN,$domain,$proxy_group_name\n"
fi
done <<< "$(echo "$proxy_domains_str" | tr '\n' ',' )" # 将换行符替换为逗号,方便循环处理
fi
# 去除 rule_content 变量开头多余的逗号 (如果存在)
rule_content=$(echo "$rule_content" | sed 's/^,//g')
# 读取已下载的配置文件内容并插入规则
existing_conf_content=""
rule_section_found=false
while IFS= read -r line; do
existing_conf_content+="$line\n"
if [[ "$line" == "[Rule]" ]]; then
rule_section_found=true
existing_conf_content+="#自定义规则\n"
existing_conf_content+="$rule_content"
fi
done < "$sr_cnip_ad_conf"
if ! $rule_section_found; then
log "警告:在已下载的配置文件中未找到 [Rule] 区块,规则将添加到文件末尾。"
existing_conf_content+="\n[Rule]\n#自定义规则\n$rule_content"
fi
# 将合并后的配置内容写入新的文件
echo -e "$existing_conf_content" > "$sr_cnip_ad_custom_conf"
log "Shadowrocket 规则已合并到 '$sr_cnip_ad_conf' 并保存为 '$sr_cnip_ad_custom_conf'"
log "已将自定义规则插入到 [Rule] 区块下方,并添加了 '#自定义规则' 备注。"
log "请检查新的配置文件 '$sr_cnip_ad_custom_conf' 是否符合您的预期。"
log "开始执行 Git push..."
git add .
git commit -m "update $sr_cnip_ad_custom_conf"
git push 2>&1 | tee -a "$log_file" # 将 git push 的输出也记录到日志
git_push_final_status=$?
if [ $git_push_final_status -ne 0 ]; then
log "错误Git push 命令执行失败。"
log "# --- END LOG --- $(date '+%Y-%m-%d %H:%M:%S') --- #" # 记录日志结束标记,即使出错也要记录
exit 1
fi
log "Git push 命令执行完成。"
log "脚本执行完毕,日志记录在 '$log_file' 文件中。"
# 记录日志结束标记
log "# --- END LOG --- $(date '+%Y-%m-%d %H:%M:%S') --- #"
exit 0