#!/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