Files
dashboard/scripts/upload.sh
T
2026-07-17 17:17:22 +08:00

191 lines
4.5 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -euo pipefail
SERVER="ubuntu@ec2-3-71-153-45.eu-central-1.compute.amazonaws.com"
REMOTE_ROOT="/data/project/dashboard"
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
SSH_KEY="$HOME/.ssh/aws_eafon.pem"
SSH_OPTS=(-i "$SSH_KEY" -o StrictHostKeyChecking=no)
FRONTEND_PATHS=(
./frontend/dist/
)
BACKEND_PATHS=(
./backend/src/
./backend/package.json
./backend/pnpm-lock.yaml
)
COMPOSE_PATHS=(
./docker-compose.yml
)
DEFAULT_PATHS=(
"${FRONTEND_PATHS[@]}"
"${BACKEND_PATHS[@]}"
"${COMPOSE_PATHS[@]}"
)
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
info() { echo -e "${CYAN}[INFO]${NC} $1"; }
ok() { echo -e "${GREEN}[OK]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
show_help() {
cat <<EOF
用法: $(basename "$0") [选项] [目标|路径...]
将本地代码同步到远程服务器(rsync)。
远程: ${SERVER}:${REMOTE_ROOT}/
选项:
-n 虚拟执行,不实际传输或删除远程文件
-h, --help 显示此帮助信息
目标:
frontend, f 同步前端 dist/(不含 nginx.conf
backend, b 同步后端 src/、package.json、pnpm-lock.yaml(不含 Dockerfile
compose, c 同步 docker-compose.yml
all, a 同步以上全部(默认)
(路径) 同步指定文件或目录,可传多个
默认不同步 nginx.conf 与 Dockerfile,需要时请显式指定,例如:
./frontend/nginx.conf
./backend/Dockerfile
指定路径时,会映射到服务器对应位置,例如:
./frontend/dist/assets -> ${REMOTE_ROOT}/frontend/dist/assets
示例:
$(basename "$0") 同步默认内容到服务器
$(basename "$0") frontend 仅同步前端
$(basename "$0") backend compose 同步后端与 docker-compose
$(basename "$0") ./frontend/nginx.conf 单独同步 nginx.conf
$(basename "$0") ./backend/Dockerfile 单独同步 Dockerfile
$(basename "$0") ./frontend/dist/assets 同步指定目录
$(basename "$0") -n 虚拟执行,预览全部同步
$(basename "$0") -n frontend 虚拟执行,预览前端同步
EOF
}
resolve_preset_paths() {
local preset="$1"
case "$preset" in
frontend|f) printf '%s\n' "${FRONTEND_PATHS[@]}" ;;
backend|b) printf '%s\n' "${BACKEND_PATHS[@]}" ;;
compose|c) printf '%s\n' "${COMPOSE_PATHS[@]}" ;;
all|a) printf '%s\n' "${DEFAULT_PATHS[@]}" ;;
*)
echo "$preset"
;;
esac
}
rsync_item() {
local item="$1"
local rel remote_path local_full
if [[ "$item" == /* ]]; then
if [[ "$item" == "$PROJECT_ROOT"/* ]]; then
rel="${item#"$PROJECT_ROOT"/}"
local_full="$item"
else
warn "路径不在项目内,跳过: $item"
return 1
fi
else
rel="${item#./}"
rel="${rel%/}"
local_full="${PROJECT_ROOT}/${rel}"
fi
remote_path="${REMOTE_ROOT}/${rel}"
if [[ ! -e "$local_full" ]]; then
warn "路径不存在: ${local_full}"
return 1
fi
local rsync_opts=(-avz --progress)
if [[ "$DRY_RUN" = true ]]; then
rsync_opts+=(-n)
fi
if [[ -d "$local_full" ]]; then
if [[ "$DRY_RUN" = true ]]; then
info "预览目录: ${rel}/ -> ${SERVER}:${remote_path}/"
else
info "同步目录: ${rel}/ -> ${SERVER}:${remote_path}/"
fi
rsync "${rsync_opts[@]}" --delete \
-e "ssh ${SSH_OPTS[*]}" \
"${local_full}/" "${SERVER}:${remote_path}/"
else
if [[ "$DRY_RUN" = true ]]; then
info "预览文件: ${rel} -> ${SERVER}:${remote_path}"
else
info "同步文件: ${rel} -> ${SERVER}:${remote_path}"
ssh "${SSH_OPTS[@]}" "$SERVER" "mkdir -p $(dirname "$remote_path")"
fi
rsync "${rsync_opts[@]}" \
-e "ssh ${SSH_OPTS[*]}" \
"$local_full" "${SERVER}:${remote_path}"
fi
}
sync_paths() {
local paths=("$@")
local item
cd "$PROJECT_ROOT"
for item in "${paths[@]}"; do
rsync_item "$item"
done
}
DRY_RUN=false
ARGS=()
for arg in "$@"; do
case "$arg" in
-n)
DRY_RUN=true
;;
-h|--help)
show_help
exit 0
;;
*)
ARGS+=("$arg")
;;
esac
done
PATHS=()
if [[ ${#ARGS[@]} -eq 0 ]]; then
PATHS=("${DEFAULT_PATHS[@]}")
else
for arg in "${ARGS[@]}"; do
while IFS= read -r path; do
PATHS+=("$path")
done < <(resolve_preset_paths "$arg")
done
fi
if [[ "$DRY_RUN" = true ]]; then
info "虚拟同步至 ${SERVER}:${REMOTE_ROOT}/"
else
info "同步至 ${SERVER}:${REMOTE_ROOT}/"
fi
sync_paths "${PATHS[@]}"
echo ""
ok "完成!"