mirror of
https://github.com/wnlen/clash-for-linux.git
synced 2026-03-21 22:06:45 +08:00
Support docker containers
This commit is contained in:
9
clashctl
9
clashctl
@ -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
|
||||||
|
|||||||
41
install.sh
41
install.sh
@ -351,13 +351,26 @@ 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
|
||||||
|
Systemd_Usable="true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$Systemd_Usable" = "true" ]; then
|
||||||
|
if [ "${CLASH_ENABLE_SERVICE:-true}" = "true" ] || [ "${CLASH_START_SERVICE:-true}" = "true" ]; then
|
||||||
CLASH_SERVICE_USER="$Service_User" CLASH_SERVICE_GROUP="$Service_Group" "$Install_Dir/scripts/install_systemd.sh"
|
CLASH_SERVICE_USER="$Service_User" CLASH_SERVICE_GROUP="$Service_Group" "$Install_Dir/scripts/install_systemd.sh"
|
||||||
|
|
||||||
if [ "${CLASH_ENABLE_SERVICE:-true}" = "true" ]; then
|
if [ "${CLASH_ENABLE_SERVICE:-true}" = "true" ]; then
|
||||||
@ -378,9 +391,18 @@ if command -v systemctl >/dev/null 2>&1; then
|
|||||||
else
|
else
|
||||||
Service_Started="inactive"
|
Service_Started="inactive"
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
info "已按配置跳过 systemd 服务安装与启动(CLASH_ENABLE_SERVICE=false 且 CLASH_START_SERVICE=false)"
|
||||||
|
Service_Enabled="disabled"
|
||||||
|
Service_Started="inactive"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if command -v systemctl >/dev/null 2>&1; then
|
||||||
|
warn "检测到 systemctl 命令,但当前环境不可用 systemd(常见于 Docker 容器),已跳过服务单元生成"
|
||||||
else
|
else
|
||||||
warn "未检测到 systemd,已跳过服务单元生成"
|
warn "未检测到 systemd,已跳过服务单元生成"
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
# Shell 代理快捷命令
|
# Shell 代理快捷命令
|
||||||
@ -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 "配置完成后重启服务:"
|
||||||
|
if [ "$Systemd_Usable" = "true" ]; then
|
||||||
log " $(cmd "sudo systemctl restart ${Service_Name}.service")"
|
log " $(cmd "sudo systemctl restart ${Service_Name}.service")"
|
||||||
|
else
|
||||||
|
log " $(cmd "sudo clashctl restart")"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
@ -535,7 +566,7 @@ 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 / 被墙)。"
|
||||||
|
|||||||
5
start.sh
5
start.sh
@ -88,6 +88,7 @@ URL="${CLASH_URL:-}"
|
|||||||
|
|
||||||
# 清理可能的 CRLF(Windows 写 .env 很常见)
|
# 清理可能的 CRLF(Windows 写 .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:-}"
|
||||||
|
|||||||
Reference in New Issue
Block a user