2025年8月

以下是一个同时支持IPv4和IPv6的Cloudflare DDNS更新脚本:

#!/bin/sh

# Cloudflare API配置
API_TOKEN="xxx"
ZONE_ID="xxx"
# IPv4记录配置
RECORD_ID_V4="xxx"
RECORD_NAME_V4="xxx"
# IPv6记录配置(如果没有可以留空)
RECORD_ID_V6="xxx"
RECORD_NAME_V6="xxx"

# 获取当前IPv4地址
CURRENT_IPV4=$(curl -s http://ipv4.icanhazip.com)
echo "当前IPv4地址: $CURRENT_IPV4"

# 获取当前IPv6地址(如果有)
CURRENT_IPV6=$(curl -s http://ipv6.icanhazip.com || echo "")
if [ -n "$CURRENT_IPV6" ]; then
    echo "当前IPv6地址: $CURRENT_IPV6"
else
    echo "未检测到IPv6地址"
fi

# 更新DNS记录函数
update_dns_record() {
    local record_id=$1
    local record_name=$2
    local current_ip=$3
    local record_type=$4
    
    if [ -z "$record_id" ] || [ -z "$current_ip" ]; then
        echo "跳过${record_type}记录更新(未配置记录ID或未检测到IP地址)"
        return
    fi

    # 获取DNS记录当前IP
    local dns_record_response=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${record_id}" \
         -H "Authorization: Bearer ${API_TOKEN}" \
         -H "Content-Type: application/json")

    local dns_record_ip=$(echo "$dns_record_response" | sed -n 's/.*"content":"\([^"]*\)".*/\1/p')
    echo "DNS记录${record_type}当前IP: $dns_record_ip"

    # 检查IP是否需要更新
    if [ "$current_ip" == "$dns_record_ip" ]; then
        echo "${record_type}记录IP地址无需更新"
    else
        echo "${record_type}记录IP地址需要更新"

        # 更新DNS记录
        local response=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${record_id}" \
             -H "Authorization: Bearer ${API_TOKEN}" \
             -H "Content-Type: application/json" \
             --data "{\"type\":\"${record_type}\",\"name\":\"${record_name}\",\"content\":\"${current_ip}\",\"ttl\":120,\"proxied\":false}")

        # 检查更新结果
        if echo "$response" | grep -q "\"success\":true"; then
            echo "${record_type}记录更新成功,新IP: ${current_ip}"
        else
            echo "${record_type}记录更新失败,错误信息: $response"
        fi
    fi
}

# 更新IPv4记录
update_dns_record "$RECORD_ID_V4" "$RECORD_NAME_V4" "$CURRENT_IPV4" "A"

# 更新IPv6记录(如果配置了)
if [ -n "$RECORD_ID_V6" ] && [ -n "$CURRENT_IPV6" ]; then
    update_dns_record "$RECORD_ID_V6" "$RECORD_NAME_V6" "$CURRENT_IPV6" "AAAA"
fi

使用说明:

  1. 需要配置以下参数:

    • API_TOKEN: Cloudflare API令牌
    • ZONE_ID: 区域ID
    • IPv4记录相关参数:

      • RECORD_ID_V4: IPv4记录的ID
      • RECORD_NAME_V4: IPv4记录的名称(如subdomain.example.com)
    • IPv6记录相关参数(可选):

      • RECORD_ID_V6: IPv6记录的ID(如果没有可以留空)
      • RECORD_NAME_V6: IPv6记录的名称
  2. 脚本功能:

    • 自动检测当前IPv4和IPv6地址
    • 分别检查Cloudflare DNS记录是否需要更新
    • 支持IPv4(A记录)和IPv6(AAAA记录)更新
    • 详细的日志输出
  3. 注意事项:

    • 如果没有IPv6地址或不需要IPv6支持,可以不配置IPv6相关参数
    • 确保API令牌有足够的权限(需要Zone.DNS编辑权限)
    • 建议设置cron定时任务自动运行此脚本
  4. 获取记录ID的方法:
    可以通过API获取:curl -X GET "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/dns_records" -H "Authorization: Bearer YOUR_API_TOKEN"

问题背景

最近在 CentOS 7 上编译安装 Python 3.9,按照官方推荐的方式执行:

./configure --prefix=/usr/local/python3 --enable-optimizations
make -j$(nproc)
sudo make install

结果编译到一半,突然报错:

Could not import runpy module
Traceback (most recent call last):
  File "/opt/Python-3.10.0/Lib/runpy.py", line 15, in <module>
    import importlib.util
  File "/opt/Python-3.10.0/Lib/importlib/util.py", line 14, in <module>
    from contextlib import contextmanager
  File "/opt/Python-3.10.0/Lib/contextlib.py", line 4, in <module>
    import _collections_abc
SystemError: <built-in function compile> returned NULL without setting an exception
generate-posix-vars failed
make: *** [pybuilddir.txt] Error 1

折腾了半天,最终发现 --enable-optimizations 是罪魁祸首!删掉这个参数后,编译顺利通过。


为什么 --enable-optimizations 会导致编译失败?

--enable-optimizations 是 Python 官方推荐的编译选项,用于启用 PGO(Profile-Guided Optimization)优化,让 Python 运行更快。但它在某些旧系统(如 CentOS 7)上可能会引发问题,原因包括:

  1. GCC 版本过低
    CentOS 7 默认的 GCC 4.8.5 对 PGO 支持不完善,而 Python 3.9+ 的优化编译需要更高版本 GCC(建议 ≥ 8)。
  2. 依赖库不兼容
    PGO 优化会额外编译测试用例,如果系统缺少某些依赖(如 zlib-devellibffi-devel),可能导致 runpy 等核心模块编译失败。
  3. 内存不足
    PGO 优化会占用更多内存,如果服务器内存较小(< 2GB),可能导致编译崩溃。

正确编译 Python 3.9 的步骤

1. 安装编译依赖

sudo yum install -y gcc make openssl-devel bzip2-devel libffi-devel zlib-devel \
ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel xz-devel

2. 下载 Python 3.9 源码

wget https://www.python.org/ftp/python/3.9.16/Python-3.9.16.tgz
tar xzf Python-3.9.16.tgz
cd Python-3.9.16

3. 配置编译选项(关键!不要加 --enable-optimizations

./configure --prefix=/usr/local/python3  # 不加 --enable-optimizations

4. 编译并安装

make -j$(nproc)        # 并行编译加速
sudo make install      # 安装到 /usr/local/python3

5. 验证安装

/usr/local/python3/bin/python3 --version
# 应输出: Python 3.9.16

如果仍想启用 PGO 优化怎么办?

如果确实需要优化性能,可以尝试以下方法:

方案 1:升级 GCC

sudo yum install centos-release-scl
sudo yum install devtoolset-9
scl enable devtoolset-9 bash
gcc --version  # 确认版本 ≥ 9

然后重新编译:

./configure --prefix=/usr/local/python3 --enable-optimizations
make -j$(nproc)

方案 2:改用 --enable-shared

如果 PGO 仍然失败,可以改用动态链接库优化:

./configure --prefix=/usr/local/python3 --enable-shared
make -j$(nproc)

总结

编译选项适用场景风险
--prefix=/usr/local/python3默认编译,兼容性最好✅ 推荐
--enable-shared支持动态链接库⚠️ 需设置 LD_LIBRARY_PATH
--enable-optimizations高性能优化(PGO)❌ 旧系统易失败

最终建议

  • 生产环境 → 直接去掉 --enable-optimizations,优先保证稳定性。
  • 开发环境 → 可尝试升级 GCC 后再启用 PGO。

希望这篇踩坑记录能帮你少走弯路!如果有其他问题,欢迎留言讨论。 🚀

问题描述

最近在服务器上安装了轻量级 Kubernetes 发行版 K3s,并部署了一个简单的 Nginx 服务,希望通过 http://服务器IP:80 访问。然而,浏览器始终返回 404 Not Found,而 curl localhost:80 却能正常返回 Nginx 的欢迎页面。

经过排查,发现 K3s 默认安装的 Traefik 组件劫持了 80 端口,导致 Nginx 虽然监听 80 端口,但外部请求被 Traefik 拦截,最终返回 404。

问题分析

1. 为什么 Nginx 的 80 端口“失效”?

  • ss -tulnp 显示 Nginx 在监听 80 端口,但外部请求被 Traefik 拦截。
  • Traefik 是 K3s 默认的 Ingress 控制器,它会自动绑定 80 和 443 端口,接管所有 HTTP/HTTPS 流量。
  • Nginx 虽然运行,但 Traefik 优先处理请求,由于没有匹配的 Ingress 规则,返回 404。

2. Traefik 的工作原理

Traefik 是一个 云原生反向代理和 Ingress 控制器,主要功能:

  1. 自动发现 Kubernetes 服务,并根据 Ingress 规则路由流量。
  2. 默认监听 80(HTTP)和 443(HTTPS),拦截所有进入集群的 Web 请求。
  3. 动态配置路由,无需重启即可生效。

在 K3s 中,Traefik 会:

  • 自动创建 LoadBalancer 类型的 Service,绑定 80/443 端口。
  • 如果没有配置 Ingress 规则,访问任何路径都会返回 404

解决方案

方法 1:禁用 Traefik(推荐)

如果不需要 Traefik,可以在安装 K3s 时直接禁用:

curl -sfL https://get.k3s.io | sh -s - --disable traefik

这样 K3s 不会安装 Traefik,80 端口由 Nginx 直接接管。

方法 2:配置 Traefik 路由(适合需要 Ingress 的场景)

如果仍想使用 Traefik,可以创建 Ingress 规则,将流量正确路由到 Nginx:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service  # 替换为你的 Nginx Service 名称
            port:
              number: 80

然后应用配置:

kubectl apply -f ingress.yaml

最终解决

由于我的需求只是运行一个简单的 Nginx,不需要 Kubernetes Ingress 功能,因此选择 卸载并重装 K3s,禁用 Traefik

# 卸载 K3s
/usr/local/bin/k3s-uninstall.sh

# 重新安装,禁用 Traefik
curl -sfL https://get.k3s.io | sh -s - --disable traefik

安装完成后,Nginx 成功接管 80 端口,浏览器访问正常!

总结

  • K3s 默认安装 Traefik,它会劫持 80/443 端口,导致 Nginx 无法直接接收外部请求。
  • 解决方案

    • 如果不需要 Ingress,安装时加 --disable traefik
    • 如果需要 Traefik,必须配置 Ingress 规则,否则会返回 404。
  • K3s 适合轻量级 Kubernetes,但需注意默认组件的影响

希望这篇博文能帮你解决类似问题!🚀