Support docker containers

This commit is contained in:
Taoyu Yang
2026-02-14 08:35:35 +00:00
parent 48d2d90ee5
commit 87397bb62e
3 changed files with 64 additions and 25 deletions

View File

@ -35,7 +35,9 @@ PID_FILE="$CLASH_HOME/temp/clash.pid"
SUBSCRIPTION_FILE="$CLASH_HOME/conf/subscriptions.list" SUBSCRIPTION_FILE="$CLASH_HOME/conf/subscriptions.list"
use_systemd() { use_systemd() {
command -v systemctl >/dev/null 2>&1 command -v systemctl >/dev/null 2>&1 || return 1
systemctl show --property=Version --value >/dev/null 2>&1 || return 1
return 0
} }
action_with_systemd() { action_with_systemd() {
@ -78,10 +80,11 @@ set_env_var() {
echo "[ERROR] 未找到 .env 文件: $ENV_FILE" >&2 echo "[ERROR] 未找到 .env 文件: $ENV_FILE" >&2
exit 1 exit 1
fi fi
local escaped local escaped escaped_sed
escaped=$(printf "%s" "$value" | sed "s/'/'\"'\"'/g") escaped=$(printf "%s" "$value" | sed "s/'/'\"'\"'/g")
escaped_sed=$(printf "%s" "$escaped" | sed 's/[\\&@]/\\&/g')
if grep -q "^export ${key}=" "$ENV_FILE"; then if grep -q "^export ${key}=" "$ENV_FILE"; then
sed -i "s@^export ${key}=.*@export ${key}='${escaped}'@" "$ENV_FILE" sed -i "s@^export ${key}=.*@export ${key}='${escaped_sed}'@" "$ENV_FILE"
else else
echo "export ${key}='${escaped}'" >> "$ENV_FILE" echo "export ${key}='${escaped}'" >> "$ENV_FILE"
fi fi

View File

@ -351,35 +351,57 @@ read_secret_from_config() {
printf '%s' "$s" printf '%s' "$s"
} }
# 判断 systemd 是否可用(仅有 systemctl 命令但 PID 1 不是 systemd 时视为不可用)
systemd_ready() {
command -v systemctl >/dev/null 2>&1 || return 1
systemctl show --property=Version --value >/dev/null 2>&1 || return 1
return 0
}
# ========================= # =========================
# systemd 安装与启动 # systemd 安装与启动
# ========================= # =========================
Service_Enabled="unknown" Service_Enabled="unknown"
Service_Started="unknown" Service_Started="unknown"
Systemd_Usable="false"
if command -v systemctl >/dev/null 2>&1; then if systemd_ready; then
CLASH_SERVICE_USER="$Service_User" CLASH_SERVICE_GROUP="$Service_Group" "$Install_Dir/scripts/install_systemd.sh" Systemd_Usable="true"
fi
if [ "${CLASH_ENABLE_SERVICE:-true}" = "true" ]; then if [ "$Systemd_Usable" = "true" ]; then
systemctl enable "${Service_Name}.service" >/dev/null 2>&1 || true if [ "${CLASH_ENABLE_SERVICE:-true}" = "true" ] || [ "${CLASH_START_SERVICE:-true}" = "true" ]; then
fi CLASH_SERVICE_USER="$Service_User" CLASH_SERVICE_GROUP="$Service_Group" "$Install_Dir/scripts/install_systemd.sh"
if [ "${CLASH_START_SERVICE:-true}" = "true" ]; then
systemctl start "${Service_Name}.service" >/dev/null 2>&1 || true
fi
if systemctl is-enabled --quiet "${Service_Name}.service" 2>/dev/null; then if [ "${CLASH_ENABLE_SERVICE:-true}" = "true" ]; then
Service_Enabled="enabled" systemctl enable "${Service_Name}.service" >/dev/null 2>&1 || true
fi
if [ "${CLASH_START_SERVICE:-true}" = "true" ]; then
systemctl start "${Service_Name}.service" >/dev/null 2>&1 || true
fi
if systemctl is-enabled --quiet "${Service_Name}.service" 2>/dev/null; then
Service_Enabled="enabled"
else
Service_Enabled="disabled"
fi
if systemctl is-active --quiet "${Service_Name}.service" 2>/dev/null; then
Service_Started="active"
else
Service_Started="inactive"
fi
else else
info "已按配置跳过 systemd 服务安装与启动CLASH_ENABLE_SERVICE=false 且 CLASH_START_SERVICE=false"
Service_Enabled="disabled" Service_Enabled="disabled"
fi
if systemctl is-active --quiet "${Service_Name}.service" 2>/dev/null; then
Service_Started="active"
else
Service_Started="inactive" Service_Started="inactive"
fi fi
else else
warn "未检测到 systemd已跳过服务单元生成" if command -v systemctl >/dev/null 2>&1; then
warn "检测到 systemctl 命令,但当前环境不可用 systemd常见于 Docker 容器),已跳过服务单元生成"
else
warn "未检测到 systemd已跳过服务单元生成"
fi
fi fi
# ========================= # =========================
@ -394,7 +416,7 @@ install_profiled() {
[ "$http_port" = "auto" ] && http_port="7890" [ "$http_port" = "auto" ] && http_port="7890"
# 只写 IPv4 loopback避免某些环境 ::1 解析问题 # 只写 IPv4 loopback避免某些环境 ::1 解析问题
sudo tee "$PROFILED_FILE" >/dev/null <<EOF tee "$PROFILED_FILE" >/dev/null <<EOF
# Clash for Linux proxy helpers # Clash for Linux proxy helpers
# Auto-generated by clash-for-linux installer. # Auto-generated by clash-for-linux installer.
@ -425,7 +447,7 @@ proxy_status() {
} }
EOF EOF
sudo chmod 644 "$PROFILED_FILE" chmod 644 "$PROFILED_FILE"
} }
install_profiled || true install_profiled || true
@ -448,7 +470,7 @@ log "📦 安装目录:$(path "${Install_Dir}")"
log "👤 运行用户:${Service_User}:${Service_Group}" log "👤 运行用户:${Service_User}:${Service_Group}"
log "🔧 服务名称:${Service_Name}.service" log "🔧 服务名称:${Service_Name}.service"
if command -v systemctl >/dev/null 2>&1; then if [ "$Systemd_Usable" = "true" ]; then
section "服务状态" section "服务状态"
se="${Service_Enabled:-unknown}" se="${Service_Enabled:-unknown}"
@ -464,6 +486,11 @@ if command -v systemctl >/dev/null 2>&1; then
log "${C_BOLD}常用命令:${C_NC}" log "${C_BOLD}常用命令:${C_NC}"
log " $(cmd "sudo systemctl status ${Service_Name}.service")" log " $(cmd "sudo systemctl status ${Service_Name}.service")"
log " $(cmd "sudo systemctl restart ${Service_Name}.service")" log " $(cmd "sudo systemctl restart ${Service_Name}.service")"
else
section "服务状态"
warn "当前环境未启用 systemd如 Docker 容器),请使用 clashctl 管理进程"
log " $(cmd "sudo clashctl start")"
log " $(cmd "sudo clashctl restart")"
fi fi
# ========================= # =========================
@ -514,7 +541,11 @@ else
log " $(cmd "sudo bash -c 'echo \"CLASH_URL=<订阅地址>\" > ${ENV_FILE}'")" log " $(cmd "sudo bash -c 'echo \"CLASH_URL=<订阅地址>\" > ${ENV_FILE}'")"
log "" log ""
log "配置完成后重启服务:" log "配置完成后重启服务:"
log " $(cmd "sudo systemctl restart ${Service_Name}.service")" if [ "$Systemd_Usable" = "true" ]; then
log " $(cmd "sudo systemctl restart ${Service_Name}.service")"
else
log " $(cmd "sudo clashctl restart")"
fi
fi fi
# ========================= # =========================
@ -535,9 +566,9 @@ fi
# 启动后快速诊断 # 启动后快速诊断
# ========================= # =========================
sleep 1 sleep 1
if command -v journalctl >/dev/null 2>&1; then if [ "$Systemd_Usable" = "true" ] && command -v journalctl >/dev/null 2>&1; then
if journalctl -u "${Service_Name}.service" -n 50 --no-pager 2>/dev/null \ if journalctl -u "${Service_Name}.service" -n 50 --no-pager 2>/dev/null \
| grep -q "Clash订阅地址不可访问"; then | grep -q "Clash订阅地址不可访问"; then
warn "服务启动异常:订阅不可用,请检查 CLASH_URL可能过期 / 404 / 被墙)。" warn "服务启动异常:订阅不可用,请检查 CLASH_URL可能过期 / 404 / 被墙)。"
fi fi
fi fi

View File

@ -88,6 +88,7 @@ URL="${CLASH_URL:-}"
# 清理可能的 CRLFWindows 写 .env 很常见) # 清理可能的 CRLFWindows 写 .env 很常见)
URL="$(printf '%s' "$URL" | tr -d '\r')" URL="$(printf '%s' "$URL" | tr -d '\r')"
URL="$(printf '%s' "$URL" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')"
#让 bash 子进程能拿到 #让 bash 子进程能拿到
export CLASH_URL="$URL" export CLASH_URL="$URL"
@ -97,6 +98,10 @@ if [ -z "$URL" ] && [ "${SYSTEMD_MODE:-false}" != "true" ]; then
echo "[ERR] CLASH_URL 为空(未配置订阅地址)" echo "[ERR] CLASH_URL 为空(未配置订阅地址)"
exit 2 exit 2
fi fi
if [ -n "$URL" ] && ! printf '%s' "$URL" | grep -Eq '^https?://'; then
echo "[ERR] CLASH_URL 格式无效:必须以 http:// 或 https:// 开头" >&2
exit 2
fi
# 获取 CLASH_SECRET 值:优先 .env其次读取旧 config占位符视为无效最后生成随机值 # 获取 CLASH_SECRET 值:优先 .env其次读取旧 config占位符视为无效最后生成随机值
Secret="${CLASH_SECRET:-}" Secret="${CLASH_SECRET:-}"