mirror of
https://github.com/wnlen/clash-for-linux.git
synced 2026-03-21 22:06:45 +08:00
Update clashctl
This commit is contained in:
147
clashctl
147
clashctl
@ -273,7 +273,7 @@ cmd_stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd_update() {
|
cmd_update() {
|
||||||
local branch remote_name dirty
|
local branch remote_name dirty pull_ok=1
|
||||||
|
|
||||||
if ! has_git_repo; then
|
if ! has_git_repo; then
|
||||||
err "当前目录不是 Git 仓库: $PROJECT_DIR"
|
err "当前目录不是 Git 仓库: $PROJECT_DIR"
|
||||||
@ -288,17 +288,55 @@ cmd_update() {
|
|||||||
|
|
||||||
remote_name="origin"
|
remote_name="origin"
|
||||||
|
|
||||||
dirty="$(git -C "$PROJECT_DIR" status --porcelain --untracked-files=no)"
|
# 保护本地 .env(如果你已经把 .env 忽略掉,这段也保留,兜底更稳)
|
||||||
if [ -n "${dirty:-}" ]; then
|
if [ -f "$PROJECT_DIR/.env" ]; then
|
||||||
err "检测到本地已修改但未提交的文件,已停止更新"
|
cp -f "$PROJECT_DIR/.env" "$PROJECT_DIR/.env.bak" 2>/dev/null || true
|
||||||
echo "请先提交、stash 或恢复后再执行 clashctl update" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "[INFO] pulling latest code from ${remote_name}/${branch} ..."
|
dirty="$(git -C "$PROJECT_DIR" status --porcelain --untracked-files=no)"
|
||||||
if ! git -C "$PROJECT_DIR" pull --ff-only "$remote_name" "$branch"; then
|
if [ -n "${dirty:-}" ]; then
|
||||||
err "git pull 失败"
|
echo "[WARN] 检测到本地已修改但未提交的文件,自动切换到安全强制更新模式"
|
||||||
exit 1
|
pull_ok=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$pull_ok" -eq 1 ]; then
|
||||||
|
echo "[INFO] pulling latest code from ${remote_name}/${branch} ..."
|
||||||
|
if ! git -C "$PROJECT_DIR" pull --ff-only "$remote_name" "$branch"; then
|
||||||
|
echo "[WARN] git pull 失败,自动切换到强制更新模式"
|
||||||
|
pull_ok=0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$pull_ok" -eq 0 ]; then
|
||||||
|
echo "[INFO] fetching latest code from ${remote_name}/${branch} ..."
|
||||||
|
if ! git -C "$PROJECT_DIR" fetch "$remote_name" "$branch"; then
|
||||||
|
err "git fetch 失败"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[WARN] resetting local code to ${remote_name}/${branch}"
|
||||||
|
if ! git -C "$PROJECT_DIR" reset --hard "${remote_name}/${branch}"; then
|
||||||
|
err "git reset --hard 失败"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 恢复 .env
|
||||||
|
if [ -f "$PROJECT_DIR/.env.bak" ]; then
|
||||||
|
mv -f "$PROJECT_DIR/.env.bak" "$PROJECT_DIR/.env" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 修复脚本权限,避免 203/EXEC
|
||||||
|
echo "[INFO] fixing executable permissions ..."
|
||||||
|
chmod +x "$PROJECT_DIR"/scripts/*.sh 2>/dev/null || true
|
||||||
|
chmod +x "$PROJECT_DIR"/bin/* 2>/dev/null || true
|
||||||
|
sed -i 's/\r$//' "$PROJECT_DIR"/scripts/*.sh 2>/dev/null || true
|
||||||
|
|
||||||
|
# 先停服务,避免 generate 时误判端口占用导致漂移
|
||||||
|
echo "[INFO] stopping service before regenerate ..."
|
||||||
|
if has_systemd; then
|
||||||
|
systemctl stop clash-for-linux.service 2>/dev/null || true
|
||||||
|
sleep 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "[INFO] regenerating config ..."
|
echo "[INFO] regenerating config ..."
|
||||||
@ -309,19 +347,35 @@ cmd_update() {
|
|||||||
|
|
||||||
echo "[INFO] restarting service ..."
|
echo "[INFO] restarting service ..."
|
||||||
if has_systemd; then
|
if has_systemd; then
|
||||||
if ! systemctl restart clash-for-linux.service; then
|
if ! systemctl start clash-for-linux.service; then
|
||||||
err "systemd 重启失败"
|
err "systemd 启动失败"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "[INFO] waiting for service to be active ..."
|
||||||
|
local i state
|
||||||
|
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||||
|
state="$(systemctl is-active clash-for-linux.service 2>/dev/null || true)"
|
||||||
|
if [ "$state" = "active" ]; then
|
||||||
|
ok "更新完成"
|
||||||
|
cmd_status
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
err "服务启动未就绪"
|
||||||
|
systemctl status clash-for-linux.service -l --no-pager || true
|
||||||
|
exit 1
|
||||||
else
|
else
|
||||||
if ! "$PROJECT_DIR/scripts/run_clash.sh" --daemon; then
|
if ! "$PROJECT_DIR/scripts/run_clash.sh" --daemon; then
|
||||||
err "脚本模式启动失败"
|
err "脚本模式启动失败"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
ok "更新完成"
|
ok "更新完成"
|
||||||
cmd_status
|
cmd_status
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_update_force() {
|
cmd_update_force() {
|
||||||
@ -389,18 +443,53 @@ cmd_update_force() {
|
|||||||
cmd_status
|
cmd_status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# === 修复执行权限 ===
|
||||||
|
fix_exec_permissions() {
|
||||||
|
local dir="${PROJECT_DIR:-$(pwd)}"
|
||||||
|
|
||||||
|
chmod +x "$dir"/scripts/*.sh 2>/dev/null || true
|
||||||
|
chmod +x "$dir"/bin/* 2>/dev/null || true
|
||||||
|
|
||||||
|
# 可选:修复 CRLF(防止 Windows 换行)
|
||||||
|
sed -i 's/\r$//' "$dir"/scripts/*.sh 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
# === 等待 service 进入 active ===
|
||||||
|
wait_for_service_active() {
|
||||||
|
local svc="${1:-clash-for-linux.service}"
|
||||||
|
local timeout="${2:-10}"
|
||||||
|
|
||||||
|
for ((i=0; i<timeout; i++)); do
|
||||||
|
state=$(systemctl is-active "$svc" 2>/dev/null || true)
|
||||||
|
if [ "$state" = "active" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# === 获取实际端口(从 runtime/config.yaml 解析)===
|
||||||
|
get_actual_ports() {
|
||||||
|
local cfg="$PROJECT_DIR/runtime/config.yaml"
|
||||||
|
|
||||||
|
if [ ! -f "$cfg" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
ACTUAL_HTTP_PORT=$(grep -E '^mixed-port:' "$cfg" | awk '{print $2}' | tr -d '\r')
|
||||||
|
ACTUAL_CTRL_PORT=$(grep -E '^external-controller:' "$cfg" | awk -F':' '{print $NF}' | tr -d '\r')
|
||||||
|
|
||||||
|
export ACTUAL_HTTP_PORT ACTUAL_CTRL_PORT
|
||||||
|
}
|
||||||
|
|
||||||
cmd_restart() {
|
cmd_restart() {
|
||||||
cmd_generate
|
cmd_generate
|
||||||
cmd_stop "${1:-false}" || true
|
cmd_stop "${1:-false}" || true
|
||||||
cmd_start
|
cmd_start
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_update() {
|
|
||||||
git -C "$PROJECT_DIR" pull
|
|
||||||
cmd_restart
|
|
||||||
ok "Project updated"
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd_ui() {
|
cmd_ui() {
|
||||||
local raw="${1:-}"
|
local raw="${1:-}"
|
||||||
local controller host port secret base_url
|
local controller host port secret base_url
|
||||||
@ -1039,7 +1128,12 @@ main() {
|
|||||||
cmd_status
|
cmd_status
|
||||||
;;
|
;;
|
||||||
update)
|
update)
|
||||||
cmd_update
|
shift
|
||||||
|
cmd_update "$@"
|
||||||
|
;;
|
||||||
|
update-force)
|
||||||
|
shift
|
||||||
|
cmd_update_force "$@"
|
||||||
;;
|
;;
|
||||||
generate)
|
generate)
|
||||||
cmd_generate
|
cmd_generate
|
||||||
@ -1058,14 +1152,7 @@ main() {
|
|||||||
shift || true
|
shift || true
|
||||||
cmd_sub "${1:-show}"
|
cmd_sub "${1:-show}"
|
||||||
;;
|
;;
|
||||||
update)
|
|
||||||
shift
|
|
||||||
cmd_update "$@"
|
|
||||||
;;
|
|
||||||
update-force)
|
|
||||||
shift
|
|
||||||
cmd_update_force "$@"
|
|
||||||
;;
|
|
||||||
tun)
|
tun)
|
||||||
shift || true
|
shift || true
|
||||||
cmd_tun "${1:-status}"
|
cmd_tun "${1:-status}"
|
||||||
|
|||||||
Reference in New Issue
Block a user