1Panel OpenResty 按省份/城市识别访客 IP:从陕西专用到全国通用(完整方案)
之前站点限制只有陕西 IP 能访问,用的是 $is_shaanxi + shaanxi.geo 一套专用配置。数据只有陕西,想加广东、北京甚至城市级判断就得再维护一份,很蠢。今天把整套方案升级成全国省份 + 城市通用体系:基于 ip2region 自动生成 34 个省级 + 数百个城市级 IP 段,OpenResty 用一个 geo 块就能识别 $china_region(SN=陕西 / GD=广东 / BJ=北京 …)和 $china_city(西安市 / 深圳市 …),以后任何地区限制都不需要再单独维护数据库,数据还能每天自动更新。这篇文章给出完整可落地的全套代码,按顺序执行即可。
总体架构
ip2region 仓库
↓ ipv4_source.txt / ipv6_source.txt
build-china-region.py (生成器,按省/市归并 CIDR)
↓
┌────────────────────┬────────────────────┐
│ china-region.geo │ china-city.geo │
│ 省级: CIDR SN; │ 城市: CIDR "西安市";│
└────────────────────┴────────────────────┘
↓ include 进 geo 块
OpenResty
↓
$china_region = SN $china_city = 西安市
关键点:生成器把 ip2region 的原始地址段用 ipaddress.collapse_addresses 归并成最小的 CIDR 集合,同一个省/市的段合并后体量小很多;全国总表 + 分省目录(china_regions/SN.geo)+ 分城市目录(china_cities/SN/西安市.geo)一次性生成,想用哪个用哪个。
第 1 步:清理旧陕西专用配置
先检查有没有站点还引用旧变量:
grep -RniE '\$is_shaanxi|shaanxi\.geo' /opt/1panel/www/conf.d || true
如果某个网站里还有:
if ($is_shaanxi = 0) {
return 403;
}
以后改成(继续只允许陕西,但改用全国通用变量):
if ($china_region != SN) {
return 403;
}
然后删除旧的陕西专用文件:
rm -f /opt/1panel/www/conf.d/00-shaanxi-geo.conf
rm -f /opt/1panel/www/conf.d/shaanxi.geo
rm -f /usr/local/bin/build-shaanxi-ip.py
rm -f /usr/local/bin/update-shaanxi-ip.sh
再次确认:
grep -RniE '\$is_shaanxi|shaanxi\.geo' /opt/1panel/www/conf.d || true
最好没有输出。
第 2 步:安装全国省份 + 城市生成器
创建 build-china-region.py(完整源码):
cat >/usr/local/bin/build-china-region.py <<'PY'
#!/usr/bin/env python3
import ipaddress
import os
import re
import shutil
import tempfile
from collections import defaultdict
# ==========================================================
# 配置
# ==========================================================
SOURCES = [
"/opt/ip2region/data/ipv4_source.txt",
"/opt/ip2region/data/ipv6_source.txt",
]
BASE_DIR = "/opt/1panel/www/conf.d"
REGION_FILE = os.path.join(BASE_DIR, "china-region.geo")
CITY_FILE = os.path.join(BASE_DIR, "china-city.geo")
REGION_DIR = os.path.join(BASE_DIR, "china_regions")
CITY_DIR = os.path.join(BASE_DIR, "china_cities")
# ==========================================================
# 中国省级行政区代码
# ==========================================================
REGION_CODES = {
"北京市": "BJ", "天津市": "TJ", "河北省": "HE", "山西省": "SX",
"内蒙古自治区": "NM", "辽宁省": "LN", "吉林省": "JL", "黑龙江省": "HL",
"上海市": "SH", "江苏省": "JS", "浙江省": "ZJ", "安徽省": "AH",
"福建省": "FJ", "江西省": "JX", "山东省": "SD", "河南省": "HA",
"湖北省": "HB", "湖南省": "HN", "广东省": "GD", "广西壮族自治区": "GX",
"海南省": "HI", "重庆市": "CQ", "四川省": "SC", "贵州省": "GZ",
"云南省": "YN", "西藏自治区": "XZ", "陕西省": "SN", "甘肃省": "GS",
"青海省": "QH", "宁夏回族自治区": "NX", "新疆维吾尔自治区": "XJ",
"台湾省": "TW", "香港特别行政区": "HK", "澳门特别行政区": "MO",
}
# ==========================================================
# ip2region 省份字段兼容
# ==========================================================
ALIASES = {
"北京": "北京市", "天津": "天津市", "河北": "河北省", "山西": "山西省",
"内蒙古": "内蒙古自治区", "辽宁": "辽宁省", "吉林": "吉林省", "黑龙江": "黑龙江省",
"上海": "上海市", "江苏": "江苏省", "浙江": "浙江省", "安徽": "安徽省",
"福建": "福建省", "江西": "江西省", "山东": "山东省", "河南": "河南省",
"湖北": "湖北省", "湖南": "湖南省", "广东": "广东省", "广西": "广西壮族自治区",
"海南": "海南省", "重庆": "重庆市", "四川": "四川省", "贵州": "贵州省",
"云南": "云南省", "西藏": "西藏自治区", "陕西": "陕西省", "甘肃": "甘肃省",
"青海": "青海省", "宁夏": "宁夏回族自治区", "新疆": "新疆维吾尔自治区",
"台湾": "台湾省", "香港": "香港特别行政区", "澳门": "澳门特别行政区",
# ip2region 当前数据中的异常省份字段
"广州": "广东省", "广州市": "广东省", "武汉": "湖北省", "武汉市": "湖北省",
}
# ==========================================================
# 数据容器
# ==========================================================
region_v4 = defaultdict(list)
region_v6 = defaultdict(list)
city_v4 = defaultdict(list)
city_v6 = defaultdict(list)
region_raw_count = defaultdict(int)
city_raw_count = defaultdict(int)
unknown_regions = set()
total_region_ranges = 0
total_city_ranges = 0
# ==========================================================
# 工具函数
# ==========================================================
def normalize_region(name):
name = name.strip()
if name in REGION_CODES:
return name
return ALIASES.get(name)
def valid_city(city):
city = city.strip()
if not city:
return False
invalid = {"0", "未知", "Unknown", "unknown", "NULL", "null", "-"}
return city not in invalid
def safe_filename(name):
name = re.sub(r'[^\w\u4e00-\u9fff\-]+', "_", name)
return name.strip("_") or "unknown"
def nginx_quote(value):
value = value.replace("\\", "\\\\")
value = value.replace('"', '\\"')
return f'"{value}"'
def atomic_write(path, content):
directory = os.path.dirname(path)
os.makedirs(directory, exist_ok=True)
fd, tmp = tempfile.mkstemp(prefix=".tmp-", dir=directory, text=True)
try:
with os.fdopen(fd, "w", encoding="utf-8") as f:
f.write(content)
os.replace(tmp, path)
except Exception:
try:
os.unlink(tmp)
except FileNotFoundError:
pass
raise
# ==========================================================
# 读取 ip2region
# 格式: start|end|country|province|city|isp|country_code
# ==========================================================
for source in SOURCES:
print(f"读取: {source}")
if not os.path.exists(source):
print(f"ERROR: 数据文件不存在: {source}")
raise SystemExit(1)
with open(source, "r", encoding="utf-8") as f:
for lineno, raw in enumerate(f, 1):
line = raw.strip()
if not line or line.startswith("#"):
continue
fields = line.split("|")
if len(fields) < 5:
continue
start_ip = fields[0].strip()
end_ip = fields[1].strip()
country = fields[2].strip()
region_raw = fields[3].strip()
city = fields[4].strip()
# 这里只处理中国
if country != "中国":
continue
if not region_raw or region_raw == "0":
continue
region_name = normalize_region(region_raw)
if not region_name:
unknown_regions.add(region_raw)
continue
region_code = REGION_CODES[region_name]
try:
start = ipaddress.ip_address(start_ip)
end = ipaddress.ip_address(end_ip)
except ValueError as e:
print(f"忽略非法 IP: {source}:{lineno}: {e}")
continue
if start.version != end.version:
continue
networks = list(ipaddress.summarize_address_range(start, end))
if start.version == 4:
region_v4[region_code].extend(networks)
else:
region_v6[region_code].extend(networks)
region_raw_count[region_code] += 1
total_region_ranges += 1
if valid_city(city):
key = (region_code, city)
if start.version == 4:
city_v4[key].extend(networks)
else:
city_v6[key].extend(networks)
city_raw_count[key] += 1
total_city_ranges += 1
# ==========================================================
# 合并省级 CIDR
# ==========================================================
collapsed_region_v4 = {}
collapsed_region_v6 = {}
all_region_codes = set(region_v4.keys()) | set(region_v6.keys())
for code in all_region_codes:
collapsed_region_v4[code] = list(ipaddress.collapse_addresses(region_v4[code]))
collapsed_region_v6[code] = list(ipaddress.collapse_addresses(region_v6[code]))
# ==========================================================
# 合并城市级 CIDR
# ==========================================================
collapsed_city_v4 = {}
collapsed_city_v6 = {}
all_city_keys = set(city_v4.keys()) | set(city_v6.keys())
for key in all_city_keys:
collapsed_city_v4[key] = list(ipaddress.collapse_addresses(city_v4[key]))
collapsed_city_v6[key] = list(ipaddress.collapse_addresses(city_v6[key]))
# ==========================================================
# 清理旧分拆目录
# ==========================================================
if os.path.exists(REGION_DIR):
shutil.rmtree(REGION_DIR)
if os.path.exists(CITY_DIR):
shutil.rmtree(CITY_DIR)
os.makedirs(REGION_DIR, exist_ok=True)
os.makedirs(CITY_DIR, exist_ok=True)
# ==========================================================
# 每个省单独生成(SN.geo / GD.geo ...)
# ==========================================================
for region_name, code in REGION_CODES.items():
v4 = collapsed_region_v4.get(code, [])
v6 = collapsed_region_v6.get(code, [])
lines = [f"# {region_name} / {code}\n", "# Generated from ip2region\n", "# DO NOT EDIT MANUALLY\n\n", "# IPv4\n"]
for net in v4:
lines.append(f"{net} 1;\n")
lines.append("\n# IPv6\n")
for net in v6:
lines.append(f"{net} 1;\n")
atomic_write(os.path.join(REGION_DIR, f"{code}.geo"), "".join(lines))
# ==========================================================
# 全国省份总表
# 输出: 113.140.64.0/18 SN;
# ==========================================================
region_entries_v4 = []
region_entries_v6 = []
for code in all_region_codes:
for net in collapsed_region_v4.get(code, []):
region_entries_v4.append((int(net.network_address), net, code))
for net in collapsed_region_v6.get(code, []):
region_entries_v6.append((int(net.network_address), net, code))
region_entries_v4.sort(key=lambda x: (x[0], x[1].prefixlen))
region_entries_v6.sort(key=lambda x: (x[0], x[1].prefixlen))
lines = ["# ==========================================\n", "# China province/region IP database\n", "# Generated from ip2region\n", "# DO NOT EDIT MANUALLY\n", "# ==========================================\n\n", "# IPv4\n"]
for _, net, code in region_entries_v4:
lines.append(f"{net} {code};\n")
lines.append("\n# IPv6\n")
for _, net, code in region_entries_v6:
lines.append(f"{net} {code};\n")
atomic_write(REGION_FILE, "".join(lines))
# ==========================================================
# 每个城市单独生成(china_cities/SN/西安市.geo ...)
# ==========================================================
for region_code, city in sorted(all_city_keys):
key = (region_code, city)
v4 = collapsed_city_v4.get(key, [])
v6 = collapsed_city_v6.get(key, [])
province_dir = os.path.join(CITY_DIR, region_code)
os.makedirs(province_dir, exist_ok=True)
lines = [f"# Region: {region_code}\n", f"# City: {city}\n", "# Generated from ip2region\n", "# DO NOT EDIT MANUALLY\n\n", "# IPv4\n"]
for net in v4:
lines.append(f"{net} 1;\n")
lines.append("\n# IPv6\n")
for net in v6:
lines.append(f"{net} 1;\n")
filename = safe_filename(city) + ".geo"
atomic_write(os.path.join(province_dir, filename), "".join(lines))
# ==========================================================
# 全国城市总表
# 输出: 113.140.64.0/18 "西安市";
# ==========================================================
city_entries_v4 = []
city_entries_v6 = []
for region_code, city in all_city_keys:
key = (region_code, city)
for net in collapsed_city_v4.get(key, []):
city_entries_v4.append((int(net.network_address), net, region_code, city))
for net in collapsed_city_v6.get(key, []):
city_entries_v6.append((int(net.network_address), net, region_code, city))
city_entries_v4.sort(key=lambda x: (x[0], x[1].prefixlen))
city_entries_v6.sort(key=lambda x: (x[0], x[1].prefixlen))
lines = ["# ==========================================\n", "# China city IP database\n", "# Generated from ip2region\n", "# DO NOT EDIT MANUALLY\n", "# ==========================================\n\n", "# IPv4\n"]
for _, net, region_code, city in city_entries_v4:
lines.append(f"{net} {nginx_quote(city)};\n")
lines.append("\n# IPv6\n")
for _, net, region_code, city in city_entries_v6:
lines.append(f"{net} {nginx_quote(city)};\n")
atomic_write(CITY_FILE, "".join(lines))
# ==========================================================
# 输出统计
# ==========================================================
reverse_names = {code: name for name, code in REGION_CODES.items()}
print()
print("========================================")
print("全国 IP 地区库生成完成")
print("========================================")
print(f"省级原始地址段: {total_region_ranges}")
print(f"城市有效地址段: {total_city_ranges}")
print()
print(f"省级总表: {REGION_FILE}")
print(f"城市总表: {CITY_FILE}")
print(f"分省目录: {REGION_DIR}")
print(f"分城市目录: {CITY_DIR}")
print()
print(f"{'代码':<6}{'地区':<12}{'IPv4':>10}{'IPv6':>10}{'城市数':>10}")
print("-" * 58)
for code in sorted(REGION_CODES.values()):
region_name = reverse_names[code]
cities = {city for rc, city in all_city_keys if rc == code}
print(f"{code:<6}{region_name:<12}{len(collapsed_region_v4.get(code, [])):>10}{len(collapsed_region_v6.get(code, [])):>10}{len(cities):>10}")
if unknown_regions:
print()
print("WARNING: 发现未识别的省级名称:")
for name in sorted(unknown_regions):
print(f" - {name}")
print()
print("请把这些名称加入 ALIASES。")
PY
chmod +x /usr/local/bin/build-china-region.py
核心逻辑:读取 ip2region 的 ipv4/ipv6 source → normalize 省份别名(ip2region 里有些字段是”广州""武汉”这种异常写法,映射回广东省/湖北省)→ 分省/分城归集 → ipaddress.collapse_addresses 合并 → 原子写出 china-region.geo(格式 113.140.64.0/18 SN;)+ china-city.geo(格式 113.140.64.0/18 "西安市";),并生成分省目录 china_regions/SN.geo 与分城市目录 china_cities/SN/西安市.geo。
先运行一次:
/usr/local/bin/build-china-region.py
第 3 步:1Panel OpenResty 全局配置
覆盖写入 /opt/1panel/www/conf.d/00-china-region.conf:
cat >/opt/1panel/www/conf.d/00-china-region.conf <<'EOF'
# ==========================================================
# 中国 IP 省份 / 城市识别
#
# 变量:
#
# $china_region
# SN = 陕西
# SX = 山西
# BJ = 北京
# GD = 广东
# XX = 未识别 / 非中国
#
# $china_city
# 西安市
# 深圳市
# 北京市
# Unknown = 无城市数据
#
# ==========================================================
# ----------------------------------------------------------
# 省级定位
# ----------------------------------------------------------
geo $china_region {
default XX;
# 本机
127.0.0.1/32 LOCAL;
::1/128 LOCAL;
include /usr/local/openresty/nginx/conf/conf.d/china-region.geo;
}
# ----------------------------------------------------------
# 城市级定位
# ----------------------------------------------------------
geo $china_city {
default Unknown;
# 本机
127.0.0.1/32 Localhost;
::1/128 Localhost;
include /usr/local/openresty/nginx/conf/conf.d/china-city.geo;
}
EOF
最终结构应该是:
/opt/1panel/www/conf.d/
├── 00-china-region.conf
├── china-region.geo
├── china-city.geo
├── china_regions/
│ ├── BJ.geo
│ ├── GD.geo
│ ├── SN.geo
│ ├── SX.geo
│ └── ...
└── china_cities/
├── SN/
│ ├── 西安市.geo
│ ├── 宝鸡市.geo
│ ├── 咸阳市.geo
│ └── ...
├── GD/
│ ├── 广州市.geo
│ ├── 深圳市.geo
│ └── ...
└── ...
第 4 步:检查 OpenResty 能否读取并 reload
OPENRESTY=$(
docker ps --format '{{.Names}}' |
grep -i openresty |
head -1
)
echo "$OPENRESTY"
确认两个数据文件在容器里(注意 geo 文件在容器内挂载路径是 /usr/local/openresty/nginx/conf/conf.d/):
docker exec "$OPENRESTY" \
ls -lh \
/usr/local/openresty/nginx/conf/conf.d/china-region.geo \
/usr/local/openresty/nginx/conf/conf.d/china-city.geo
检查配置:
docker exec "$OPENRESTY" \
/usr/local/openresty/nginx/sbin/nginx -t
成功后 reload:
docker exec "$OPENRESTY" \
/usr/local/openresty/nginx/sbin/nginx -s reload
临时测试接口
在 1Panel 某个网站的 server {} 里临时加:
location = /__geo_test {
default_type text/plain;
return 200
"ip=$remote_addr\n"
"region=$china_region\n"
"city=$china_city\n";
}
你之前的:
113.140.84.102
应该类似:
ip=113.140.84.102
region=SN
city=西安市
如果某个陕西 IP 没有城市信息:
region=SN
city=Unknown
这是正常的。
第 5 步:用法示例
只允许陕西
以前的:
if ($is_shaanxi = 0) {
return 403;
}
全部不要了,现在直接:
if ($china_region != SN) {
return 403;
}
只允许西安
if ($china_city != "西安市") {
return 403;
}
不过更严谨的是同时判断省+市。全局配置中增加:
map "$china_region:$china_city" $allow_xian {
default 0;
"SN:西安市" 1;
}
站点:
if ($allow_xian = 0) {
return 403;
}
第 6 步:自动更新脚本(每天凌晨)
创建 /usr/local/bin/update-china-region.sh(完整源码):
cat >/usr/local/bin/update-china-region.sh <<'SH'
#!/bin/bash
set -Eeuo pipefail
REPO="/opt/ip2region"
BUILD_SCRIPT="/usr/local/bin/build-china-region.py"
REGION_FILE="/opt/1panel/www/conf.d/china-region.geo"
CITY_FILE="/opt/1panel/www/conf.d/china-city.geo"
echo
echo "========================================"
echo "$(date '+%F %T') 开始更新中国 IP 数据"
echo "========================================"
echo
# ==========================================================
# 检查仓库
# ==========================================================
if [ ! -d "$REPO/.git" ]; then
echo "ERROR: ip2region 仓库不存在:"
echo "$REPO"
exit 1
fi
cd "$REPO"
OLD_HEAD=$(git rev-parse HEAD)
echo "当前版本:"
echo "$OLD_HEAD"
echo
# ==========================================================
# 拉取最新数据
# ==========================================================
echo "检查 ip2region 更新..."
git pull --ff-only
NEW_HEAD=$(git rev-parse HEAD)
echo
if [ "$OLD_HEAD" = "$NEW_HEAD" ]; then
echo "ip2region 仓库没有变化"
else
echo "ip2region 已更新:"
echo
echo "$OLD_HEAD"
echo "↓"
echo "$NEW_HEAD"
fi
# ==========================================================
# 备份当前运行中的 geo 文件
# ==========================================================
TMP_DIR=$(mktemp -d)
trap 'rm -rf "$TMP_DIR"' EXIT
HAD_REGION=0
HAD_CITY=0
if [ -f "$REGION_FILE" ]; then
cp "$REGION_FILE" "$TMP_DIR/china-region.geo"
HAD_REGION=1
fi
if [ -f "$CITY_FILE" ]; then
cp "$CITY_FILE" "$TMP_DIR/china-city.geo"
HAD_CITY=1
fi
# ==========================================================
# 重新生成
# ==========================================================
echo
echo "重新生成全国省份 / 城市数据..."
echo
"$BUILD_SCRIPT"
# ==========================================================
# 判断运行文件有没有变化
# ==========================================================
REGION_CHANGED=1
CITY_CHANGED=1
if [ "$HAD_REGION" -eq 1 ] &&
cmp -s \
"$TMP_DIR/china-region.geo" \
"$REGION_FILE"
then
REGION_CHANGED=0
fi
if [ "$HAD_CITY" -eq 1 ] &&
cmp -s \
"$TMP_DIR/china-city.geo" \
"$CITY_FILE"
then
CITY_CHANGED=0
fi
echo
if [ "$REGION_CHANGED" -eq 0 ] &&
[ "$CITY_CHANGED" -eq 0 ]
then
echo "省份和城市 IP 数据均没有变化"
echo "无需 reload OpenResty"
echo
echo "========================================"
echo "更新完成"
echo "========================================"
exit 0
fi
if [ "$REGION_CHANGED" -eq 1 ]; then
echo "省份 IP 数据发生变化"
fi
if [ "$CITY_CHANGED" -eq 1 ]; then
echo "城市 IP 数据发生变化"
fi
# ==========================================================
# 找 1Panel OpenResty 容器
# ==========================================================
echo
echo "查找 OpenResty 容器..."
OPENRESTY=$(
docker ps --format '{{.Names}}' |
grep -i openresty |
head -1 || true
)
if [ -z "$OPENRESTY" ]; then
echo "ERROR: 没找到运行中的 OpenResty 容器"
exit 1
fi
echo "OpenResty: $OPENRESTY"
# ==========================================================
# nginx -t
# ==========================================================
echo
echo "检查 OpenResty 配置..."
if ! docker exec "$OPENRESTY" \
/usr/local/openresty/nginx/sbin/nginx -t
then
echo
echo "ERROR: 新 IP 数据导致 OpenResty 配置检查失败"
echo "恢复旧 IP 数据..."
if [ "$HAD_REGION" -eq 1 ]; then
cp \
"$TMP_DIR/china-region.geo" \
"$REGION_FILE"
else
rm -f "$REGION_FILE"
fi
if [ "$HAD_CITY" -eq 1 ]; then
cp \
"$TMP_DIR/china-city.geo" \
"$CITY_FILE"
else
rm -f "$CITY_FILE"
fi
echo
echo "旧数据已恢复"
if docker exec "$OPENRESTY" \
/usr/local/openresty/nginx/sbin/nginx -t
then
echo "恢复后的 OpenResty 配置正常"
else
echo "WARNING: 恢复后 nginx -t 仍失败"
echo "请手动检查其他 OpenResty 配置"
fi
exit 1
fi
# ==========================================================
# reload
# ==========================================================
echo
echo "配置检查成功"
echo "重新加载 OpenResty..."
docker exec "$OPENRESTY" \
/usr/local/openresty/nginx/sbin/nginx -s reload
echo
echo "OpenResty reload 成功"
echo
echo "========================================"
echo "$(date '+%F %T') 更新完成"
echo "========================================"
echo
SH
chmod +x /usr/local/bin/update-china-region.sh
这个版本的特性:
git pull --ff-only拉最新 ip2region;- 自动重新生成省市数据库;
- 用
cmp -s比较是否真的发生变化:没变化不 reload; - 有变化先
nginx -t;配置正确才 reload; - 如果
nginx -t失败,会自动恢复旧数据库,再试一次,仍失败就报警告; - 不生成日志,全部直接打印。
手动测试一次
/usr/local/bin/update-china-region.sh
如果仓库和数据库都没变化,会类似:
========================================
2026-09-01 12:00:00 开始更新中国 IP 数据
========================================
检查 ip2region 更新...
Already up to date.
ip2region 仓库没有变化
重新生成全国省份 / 城市数据...
...
省份和城市 IP 数据均没有变化
无需 reload OpenResty
========================================
更新完成
========================================
如果数据变化:
省份 IP 数据发生变化
城市 IP 数据发生变化
查找 OpenResty 容器...
OpenResty: 1Panel-openresty-xxxx
检查 OpenResty 配置...
nginx: configuration file ... test is successful
配置检查成功
重新加载 OpenResty...
OpenResty reload 成功
1Panel 定时任务
1Panel → 计划任务 → 创建计划任务 → Shell 脚本,命令:
/usr/local/bin/update-china-region.sh
建议每天一次,例如每天凌晨 04:17。因为不写日志、直接打印,1Panel 自己的任务执行记录里就能看到结果。
第 7 步:最后检查旧配置是否彻底消失
grep -RniE '\$is_shaanxi|shaanxi\.geo' \
/opt/1panel/www/conf.d || true
如果没有输出,就说明已经彻底清理。再检查新的变量:
grep -RniE '\$china_region|\$china_city' \
/opt/1panel/www/conf.d
最后:
OPENRESTY=$(
docker ps --format '{{.Names}}' |
grep -i openresty |
head -1
)
docker exec "$OPENRESTY" \
/usr/local/openresty/nginx/sbin/nginx -t
成功后:
docker exec "$OPENRESTY" \
/usr/local/openresty/nginx/sbin/nginx -s reload
这样最终你只有一套通用体系:
ip2region
↓
ipv4_source.txt
ipv6_source.txt
↓
build-china-region.py
↓
┌──────────────────┬──────────────────┐
│ china-region.geo │ china-city.geo │
│ 省份 │ 城市 │
└──────────────────┴──────────────────┘
↓
OpenResty
↓
$china_region = SN
$china_city = 西安市
以后陕西、广东、北京、西安、深圳等都不需要再单独维护数据库。