
功能定位:为什么要在命令行做定时更新
在桌面端点击“刷新订阅”确实简单,但外贸公司或 CI 环境常把 Ubuntu 服务器当出口网关,需要无人值守、可审计、可回滚的节点更新方案。cron 是 Ubuntu 默认内置的定时引擎,无需额外安装,就能把“拉取—校验—重载”三步串成闭环,并把日志留给 systemd-journald 统一收集,方便后续合规抽查。
与桌面客户端相比,命令行方案的核心差异是:无图形依赖、可放进 Docker、可版本化配置。代价是你得自己处理订阅格式转换、异常重试、以及节点可用性探针。下文给出一条最小可复现路径,并标注“经验性观察”带来的取舍点。
前置准备:检查系统环境与依赖
1. 确认 Ubuntu 版本与 cron 状态
lsb_release -a # 查看发行版,20.04 及以上自带 cron systemctl status cron # Active: active (running) 即可
若看到 inactive,执行 sudo systemctl enable --now cron 一次性激活。
2. 安装必要工具
快连官方只提供“订阅地址”,返回格式为 base64 编码的 ssr:// 或 https:// 链接。我们需要 curl 拉取、base64 -d 解码,再用 jq 做 JSON 化(可选)。
sudo apt update && sudo apt install -y curl base64 jq
3. 创建低权专用用户
为降低密钥泄露后的影响面,建议新建 kuailian 用户,并禁止登录 shell:
sudo adduser --system --group --shell /usr/sbin/nologin kuailian
sudo mkdir -p /opt/kuailian/{subs,logs,configs}
sudo chown -R kuailian:kuailian /opt/kuailian
获取订阅地址:桌面端最短路径
由于快连并未公开“API 文档”,订阅地址只能在登录后的客户端内提取。下面给出截至当前的最新版本的通用入口,若 UI 调整,请以实际为准。
- Windows/macOS:主界面右上角「≡」→「订阅设置」→「复制订阅链接」
- Android:底栏「我的」→「订阅管理」→长按「快连节点」→「复制地址」
- iOS:由于系统限制,需先开启“开发者模式”才能在同一入口看到地址;若未出现,可临时用桌面端扫码登录后复制。
警告
订阅地址包含 UID 与 token,等同于账号密码,切勿提交到公共代码仓库。
脚本拆解:拉取、解码、校验、重载四步
把四步写成单个 bash 脚本,方便 cron 调用,也方便手动回滚。以下示例保存为 /opt/kuailian/update-sub.sh。
#!/usr/bin/env bash
# 更新时间:见日志
set -euo pipefail
SUB_URL="https://sub.quicklink/example/$(cat /opt/kuailian/token.file)"
BACKUP_DIR="/opt/kuailian/configs/$(date +%Y%m%d-%H%M%S)"
LOG_FILE="/opt/kuailian/logs/update.log"
mkdir -p "$BACKUP_DIR"
# 1. 拉取
curl -fsSL "$SUB_URL" -o /tmp/sub.base64
# 2. 解码
base64 -d /tmp/sub.base64 > "$BACKUP_DIR/nodes.txt"
# 3. 基础校验:非空且含 ssr://
if grep -q "ssr://" "$BACKUP_DIR/nodes.txt"; then
cp "$BACKUP_DIR/nodes.txt" /opt/kuailian/configs/latest.txt
echo "$(date '+%F %T') 节点更新成功,共 $(wc -l < "$BACKUP_DIR/nodes.txt") 条" >> "$LOG_FILE"
else
echo "$(date '+%F %T') 订阅内容异常,已放弃" >> "$LOG_FILE"
exit 1
fi
# 4. 重载(示例:如本地跑了 redsocks2,可 SIGHUP 进程)
pkill -HUP redsocks2 || true
给脚本加可执行权限:
sudo chmod +x /opt/kuailian/update-sub.sh sudo chown kuailian:kuailian /opt/kuailian/update-sub.sh
cron 入口:三种调度策略对比
| 策略 | crontab 写法 | 适用场景 | 风险点 |
|---|---|---|---|
| 固定间隔 | 0 */6 * * * | 个人 VPS,节点变化不频繁 | 高峰时段可能撞上官方限速 |
| 错峰随机 | 0 3-6 * * * | 外贸公司,避开国内晚高峰 | 脚本执行时间拉长,需锁机制 |
| 守护+失败退避 | systemd timer | CI 网关,失败立即重试 | 配置复杂,需写 service 单元 |
以下以最常用的“固定间隔”为例,演示如何落地。
落地:添加 cron 并验证日志
1. 编辑 kuailian 用户的 crontab
sudo -u kuailian crontab -e # 插入下行,每 6 小时执行一次 0 */6 * * * /opt/kuailian/update-sub.sh
2. 观测首次运行
sudo -u kuailian /opt/kuailian/update-sub.sh # 手动触发 cat /opt/kuailian/logs/update.log
看到“节点更新成功”即表示链路打通;若提示 403,请检查 token 是否过期——桌面端重新复制订阅地址即可。
3. 设置日志留存
Ubuntu 默认使用 systemd-journald,但 cron 任务输出会被截断。建议让脚本自行写文件,再用 logrotate 轮转:
sudo tee /etc/logrotate.d/kuailian <<'EOF'
/opt/kuailian/logs/*.log {
daily
rotate 30
compress
missingok
notifempty
}
EOF
异常分支: token 失效、节点为空、格式变异
- token 失效:返回 403,脚本以 exit 1 终止;cron 会发邮件(若系统配置了 MTA)。解决:桌面端重新复制订阅地址,更新
token.file。 - 节点为空:官方偶尔维护,返回 200 但 body 为空。脚本已用
grep -q兜底,避免覆盖旧配置。 - 格式变异:经验性观察,官方在 2025 年底曾把 base64 拆成段,中间插入换行。可在解码前加
tr -d '\n'兼容。
与 systemd 协同:用 timer 替代 cron(可选)
若你对“失败退避”有强需求,可改用 systemd timer,支持 RestartSec=5min 退避。创建单元文件:
sudo tee /etc/systemd/system/kuailian-update.service <<'EOF' [Unit] Description=Kuailian sub update After=network-online.target Wants=network-online.target [Service] Type=oneshot User=kuailian ExecStart=/opt/kuailian/update-sub.sh EOF sudo tee /etc/systemd/system/kuailian-update.timer <<'EOF' [Unit] Description=Run kuailian-update every 6 hours [Timer] OnCalendar=*:0/6:00 Persistent=true [Install] WantedBy=timers.target EOF sudo systemctl daemon-reload sudo systemctl enable --now kuailian-update.timer
timer 优势:日志统一进 journalctl -u kuailian-update,且支持 AccuracySec=1h 做错峰抖动。
监控与验收:如何证明“自动更新”真的跑了
1. 指标选取
合规场景下,老板最关心“有没有跑”与“节点能不能用”。推荐把 /opt/kuailian/logs/update.log 最后一条时间戳与“当前时间”差值当 KPI,例如:
#!/bin/bash
last=$(tail -1 /opt/kuailian/logs/update.log | awk '{print $1" "$2}')
last_ts=$(date -d "$last" +%s)
now_ts=$(date +%s)
diff=$(( (now_ts - last_ts) / 3600 ))
[[ $diff -le 7 ]] && echo "OK: 上次更新在 ${diff}h 前" || echo "WARN: 已 ${diff}h 未更新"
2. 可用性探针(可选)
若你本地跑了 redsocks2/shadowsocks-libev,可在脚本尾部加 timeout 5 nc -z 127.0.0.1 1080,探测 SOCKS 端口是否仍通;不通则 systemctl restart redsocks2,实现“配置更新+服务自愈”双保险。
不适用场景与边界
- 节点需二次验证:部分企业订阅要求短信动态码,命令行无法交互,只能回退到桌面端。
- 网络出口被 DNS 污染:curl 阶段就 443 超时,需先解决连通性,再谈定时更新。
- 明文法规禁止:在明文要求“境外链路需审批”的区域,自动更新可能被认定为“擅自变更路由”,请事前完成合规备案。
FAQ:脚本、权限与日志
Q1: 能否把 token 直接写进脚本?
可以,但不推荐。单独放在 token.file 方便 logrotate 排除,也降低误提交 Git 的风险。
Q2: 脚本解码报错 “base64: invalid input”?
经验性观察,官方偶尔在返回体里插入换行。可在 base64 -d 前加 tr -d '\n' 清理。
Q3: cron 邮件堆积怎么办?
在 crontab 首行加 MAILTO="" 可关闭邮件;或把输出重定向到日志文件:>> /opt/kuailian/logs/cron.log 2>&1。
Q4: 如何回滚到上一版节点?
脚本每次更新前按时间戳新建目录,回滚只需 cp /opt/kuailian/configs/20260419-120001/nodes.txt /opt/kuailian/configs/latest.txt 然后重启代理进程。
Q5: systemd timer 会不会和 cron 重复?
会。两者选其一即可。若已启用 timer,请把对应用户的 crontab 注释掉,避免 6 小时内双次更新。
最佳实践清单(可打印)
- 永远用低权用户跑脚本,
nologin防 ssh 误用。 - token 单独文件、600 权限、定期轮换。
- 脚本内用
set -euo pipefail,出错即退,避免空配置覆盖旧文件。 - 每次更新先备份,用日期目录,保留 30 天。
- 日志落盘 + logrotate,审计时能用
journalctl也能用cat *.log。 - 监控“最后更新距现在的小时数”而非“是否成功”,可提前发现静默失败。
- 若本地代理进程依赖节点,更新后加探针端口,不通即重启,实现自愈。
- 在法规要求备案的场景,更新前后各生成一次
ip route快照,留档备查。
收尾:下一步行动建议
至此,你已在 Ubuntu 服务器上跑通“cron 定时拉取快连订阅节点”的最小闭环,并具备日志审计与回滚能力。建议先用 watch -n 3600 人工观察一天,确认节点可用性探针无误后,再把间隔缩到 4 小时;同时把“最后更新小时数”监控推送到 Prometheus 或自建 Telegram 机器人,实现真正的无人值守。若后续官方推出正式 REST API,可无缝把脚本中的 curl 部分替换为带 OAuth2 的调用,复用同一套日志与回滚框架。