Ryan
1
1.Docker Compose 项目每日自动更新一键脚本
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
PATH=/usr/sbin:/usr/bin:/sbin:/bin
# === 配置:你的 Compose 项目目录 ===
DIRS=(
"/home/ryan/gemini-balance"
"/home/ryan/gpt-load"
)
# 如需连数据库服务也更新,把 SKIP_DB_SERVICES 改成 0
SKIP_DB_SERVICES=${SKIP_DB_SERVICES:-1}
# 避免并发(如果上一次没跑完)
exec 9>/var/run/compose-autoupdate.lock
flock -n 9 || { echo "Another run is in progress. Exit."; exit 0; }
# 解析 compose 命令(用数组避免空格问题)
declare -a COMPOSE
if docker compose version >/dev/null 2>&1; then
COMPOSE=(docker compose)
elif command -v docker-compose >/dev/null 2>&1; then
COMPOSE=(docker-compose)
else
echo "docker compose / docker-compose 未安装"; exit 1
fi
git_as_owner() {
local dir="$1"; shift
local owner
owner=$(stat -c '%U' "$dir" 2>/dev/null || echo "")
[ -z "$owner" ] && { echo "无法获取目录所有者:$dir"; return 1; }
sudo -u "$owner" git -C "$dir" "$@"
}
update_one() {
local d="$1"
echo -e "\n=============================="
echo ">>> 更新项目:$d @ $(date -Is)"
echo "=============================="
[ -d "$d" ] || { echo "目录不存在:$d"; return 1; }
cd "$d"
# 1) Git(有仓库且干净才 pull)
if [ -d .git ]; then
if ! git_as_owner "$d" diff --quiet || ! git_as_owner "$d" diff --cached --quiet; then
echo "⚠️ 检测到未提交改动,跳过 git pull:$d"
else
git_as_owner "$d" fetch --all --prune
local branch
branch=$(git_as_owner "$d" symbolic-ref --short HEAD 2>/dev/null || echo "")
if [ -n "$branch" ] && ! git_as_owner "$d" rev-parse --abbrev-ref --symbolic-full-name "@{u}" >/dev/null 2>&1; then
if git_as_owner "$d" ls-remote --exit-code --heads origin "$branch" >/dev/null 2>&1; then
git_as_owner "$d" branch --set-upstream-to "origin/$branch" "$branch" || true
fi
fi
if ! git_as_owner "$d" pull --ff-only; then
echo "⚠️ ff-only pull 失败(可能存在分叉),已跳过 pull。"
fi
fi
else
echo "ℹ️ 非 git 仓库,跳过 git。"
fi
# 2) Compose:只更新应用服务(默认跳过数据库类)
"${COMPOSE[@]}" config >/dev/null
local services
services=$("${COMPOSE[@]}" config --services)
if [ "${SKIP_DB_SERVICES}" = "1" ]; then
services=$(echo "$services" | grep -Ev '^(mysql|mariadb|db|postgres|redis)$' || true)
fi
# 如果未匹配到(例如单服务项目),直接全量
if [ -z "$services" ]; then
services=$("${COMPOSE[@]}" config --services)
fi
echo "[Compose] 目标服务:"
echo "$services" | sed 's/^/ - /'
echo "[Compose] 拉取镜像…"
"${COMPOSE[@]}" pull $services
echo "[Compose] 滚动更新…"
"${COMPOSE[@]}" up -d --remove-orphans $services
echo "[Compose] 状态:"
"${COMPOSE[@]}" ps
echo "[Compose] 最近 80 行日志:"
"${COMPOSE[@]}" logs --tail 80 --no-log-prefix $services || true
echo "✅ 完成:$d"
}
for d in "${DIRS[@]}"; do
update_one "$d"
done
# 可选:清理悬挂镜像,避免磁盘涨太快
docker image prune -f >/dev/null 2>&1 || true
echo -e "\n🎉 自动更新完成:$(date -Is)"
2.sing-box-yg 专用的 SOCKS5 一键部署脚本
# sing-box-yg 专用:复制这一个块,粘贴进终端即可完成 “SOCKS5 入站 → direct 出站” 独立服务
# 适用:已安装 https://github.com/yonggekkk/sing-box-yg 的 VPS(定制二进制通常在 /etc/s-box/sing-box)
# 用法:
# 1) 如需改端口/账号/监听地址,只需改动最上面的四个变量即可;其余保持不变。
# 2) 选中**整段**复制,粘贴到服务器终端回车执行。
# ======= 可按需修改的 4 个变量 =======
LISTEN_ADDR="0.0.0.0" # 若仅本机使用改为 127.0.0.1
SOCKS_PORT=41233 # 端口可改为未占用的,如 41234
SOCKS_USER="ryanvan" # Socks5 用户名
SOCKS_PASS=" " # Socks5 密码
# ======= 以下内容无需改动,直接粘贴执行 =======
CFG_PATH="/etc/sing-box/socks.json"; UNIT_PATH="/etc/systemd/system/sing-box-socks.service"
SING_BOX_BIN=""; for c in \
"/etc/s-box/sing-box" \
"$(command -v sing-box 2>/dev/null || true)" \
"/usr/local/bin/sing-box" \
"/usr/bin/sing-box"; do [ -n "$c" ] && [ -x "$c" ] && SING_BOX_BIN="$c" && break; done; \
if [ -z "$SING_BOX_BIN" ]; then echo "[ERR] 未找到 sing-box 可执行文件,请先在 sb 面板(选项 8)安装/切换内核" >&2; exit 1; fi; \
sudo mkdir -p /etc/sing-box; \
sudo tee "$CFG_PATH" >/dev/null <<EOF
{
"log": { "level": "info" },
"inbounds": [{
"type": "socks",
"tag": "socks-in",
"listen": "$LISTEN_ADDR",
"listen_port": $SOCKS_PORT,
"users": [{ "username": "$SOCKS_USER", "password": "$SOCKS_PASS" }]
}],
"outbounds": [{ "type": "direct", "tag": "direct" }],
"route": { "rules": [{ "inbound": ["socks-in"], "outbound": "direct" }] }
}
EOF
sudo "$SING_BOX_BIN" check -c "$CFG_PATH"; \
sudo tee "$UNIT_PATH" >/dev/null <<EOF
[Unit]
Description=Sing-box SOCKS-only (yg) service
After=network.target
[Service]
ExecStart=$SING_BOX_BIN run -c $CFG_PATH
Restart=always
User=root
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload; \
sudo systemctl enable --now sing-box-socks; \
sleep 0.5; \
sudo systemctl status sing-box-socks --no-pager -l || true; \
if command -v ss >/dev/null 2>&1; then ss -lntp | grep ":$SOCKS_PORT" || true; fi; \
echo "
[OK] SOCKS5 已部署:$LISTEN_ADDR:$SOCKS_PORT 用户: $SOCKS_USER 密码: $SOCKS_PASS"; \
echo "提示:如需限制来源 IP,请执行:sudo ufw allow from <你的公网IP> to any port $SOCKS_PORT proto tcp";
3. 设置虚拟内存一键脚本
# 需 root
cat >/root/init-swap-zram512.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
# ================== 可调参数 ==================
SWAP_FILE=${SWAP_FILE:-/swapfile.new} # 磁盘swap路径
SWAP_SIZE=${SWAP_SIZE:-3G} # 磁盘swap大小
ZRAM_TARGET_MIB=${ZRAM_TARGET_MIB:-512} # 目标 zram 大小(MiB)
ZRAM_PRIORITY=${ZRAM_PRIORITY:-100} # zram 优先级
DISKSWAP_PRIORITY=${DISKSWAP_PRIORITY:-0} # 磁盘swap优先级
# =============================================
log() { echo -e "\e[32m[INFO]\e[0m $*"; }
warn(){ echo -e "\e[33m[WARN]\e[0m $*"; }
err() { echo -e "\e[31m[ERR ]\e[0m $*" >&2; }
[ "$(id -u)" -eq 0 ] || { err "请以 root 运行"; exit 1; }
export DEBIAN_FRONTEND=noninteractive
log "1/4 创建并启用 ${SWAP_SIZE} 磁盘Swap: ${SWAP_FILE}"
if [ ! -f "$SWAP_FILE" ]; then
if ! fallocate -l "$SWAP_SIZE" "$SWAP_FILE" 2>/dev/null; then
dd if=/dev/zero of="$SWAP_FILE" bs=1M count=$(( ${SWAP_SIZE%G} * 1024 )) status=progress
fi
fi
chmod 600 "$SWAP_FILE"
mkswap "$SWAP_FILE" >/dev/null 2>&1 || true
# 以指定优先级启用
swapon -p "$DISKSWAP_PRIORITY" "$SWAP_FILE" 2>/dev/null || swapon "$SWAP_FILE"
# fstab 持久化(移除旧行,新增新行)
sed -i "\|^[[:space:]]*${SWAP_FILE}[[:space:]]\+none[[:space:]]\+swap|d" /etc/fstab
grep -q "^${SWAP_FILE} " /etc/fstab || echo "${SWAP_FILE} none swap sw,pri=${DISKSWAP_PRIORITY} 0 0" >> /etc/fstab
log "2/4 安装并配置 zram-tools,目标≈${ZRAM_TARGET_MIB}MiB(LZ4)"
apt-get update -y >/dev/null
apt-get install -y "linux-modules-extra-$(uname -r)" zram-tools >/dev/null || true
# 计算一个接近目标的百分比(用于大多数机器)
MemTotalKB=$(awk '/MemTotal/{print $2}' /proc/meminfo)
# 四舍五入: 百分比 = 目标MiB *1024*100 / MemTotalKB
Percent=$(( (ZRAM_TARGET_MIB*1024*100 + MemTotalKB/2) / MemTotalKB ))
# 设置合理边界,避免异常
[ "$Percent" -lt 10 ] && Percent=10
[ "$Percent" -gt 200 ] && Percent=200
cat >/etc/default/zramswap <<EOF_CFG
PERCENT=${Percent}
ALGO=lz4
PRIORITY=${ZRAM_PRIORITY}
EOF_CFG
systemctl enable --now zramswap >/dev/null 2>&1 || true
sleep 1
# 读取实际大小(MiB)
zsize_bytes=$(cat /sys/block/zram0/disksize 2>/dev/null || echo 0)
zsize_mib=$(( zsize_bytes/1024/1024 ))
log "zramswap 计算结果:${zsize_mib}MiB(目标≈${ZRAM_TARGET_MIB}MiB)"
# 若偏离过大(<目标-16 或 >目标+128),启用“固定 512MiB”兜底方案(自定义unit,重启后持久)
if [ "$zsize_mib" -lt $((ZRAM_TARGET_MIB-16)) ] || [ "$zsize_mib" -gt $((ZRAM_TARGET_MIB+128)) ]; then
warn "结果偏离较大,改用固定 ${ZRAM_TARGET_MIB}MiB 方案并禁用 zramswap,以确保一致性(含开机自启)"
systemctl disable --now zramswap >/dev/null 2>&1 || true
mkdir -p /usr/local/sbin
cat >/usr/local/sbin/configure-zram-fixed <<'EOSH'
#!/usr/bin/env bash
set -euo pipefail
modprobe zram || true
swapoff /dev/zram0 2>/dev/null || true
echo 1 > /sys/block/zram0/reset 2>/dev/null || true
echo lz4 > /sys/block/zram0/comp_algorithm 2>/dev/null || true
echo __SIZE_BYTES__ > /sys/block/zram0/disksize
mkswap /dev/zram0 >/dev/null
swapon -p __ZPRIORITY__ /dev/zram0
EOSH
sed -i "s/__SIZE_BYTES__/$((ZRAM_TARGET_MIB*1024*1024))/; s/__ZPRIORITY__/${ZRAM_PRIORITY}/" /usr/local/sbin/configure-zram-fixed
chmod +x /usr/local/sbin/configure-zram-fixed
cat >/etc/systemd/system/zram-fixed.service <<'EOFU'
[Unit]
Description=Configure zram0 with fixed size
DefaultDependencies=no
After=local-fs.target
Before=swap.target
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/configure-zram-fixed
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOFU
systemctl daemon-reload
systemctl enable --now zram-fixed.service
fi
log "3/4 设置 vm.swappiness=60(持久)"
echo 'vm.swappiness=60' >/etc/sysctl.d/99-swap-tuning.conf
sysctl --system >/dev/null
log "4/4 最终状态:"
echo
swapon --show
echo
free -h
echo
log "完成!zram 目标≈${ZRAM_TARGET_MIB}MiB,磁盘Swap=${SWAP_SIZE},可重复运行且重启持久。"
EOF
chmod +x /root/init-swap-zram512.sh
bash /root/init-swap-zram512.sh