#!/usr/bin/env sh set -eu ROOT_DIR="$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)" CALENDAR_DIR="$ROOT_DIR/calendar" DIST_DIR="$CALENDAR_DIR/dist" OUTPUT_DIR="" INTERVAL_MINUTES=60 RUN_ONCE=false print_usage() { cat <<'EOF' 用法: sh scripts/publish-calendar-dist.sh --output-dir [选项] 作用: 1. 调用 calendar 现有导出链路生成最新背景图与主题资源 2. 把 calendar/dist 整体发布到指定目录 3. 默认每 60 分钟自动重跑一次;加 --once 只跑一轮 选项: -o, --output-dir 发布目标目录,通常是 Web 服务器实际对外提供静态文件的目录 --interval-minutes 自动生成间隔,默认 60 分钟 --once 只生成并发布一轮 -h, --help 查看帮助 示例: sh scripts/publish-calendar-dist.sh --output-dir /srv/calendar-dashboard --once sh scripts/publish-calendar-dist.sh --output-dir /srv/calendar-dashboard EOF } log() { printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$1" } validate_positive_integer() { value=$1 name=$2 case "$value" in ''|*[!0-9]*) echo "$name 必须是正整数:$value" >&2 exit 1 ;; esac if [ "$value" -le 0 ]; then echo "$name 必须大于 0:$value" >&2 exit 1 fi } publish_once() { temp_publish_dir=$(mktemp -d "${TMPDIR:-/tmp}/kindle-dash-publish.XXXXXX") publish_status=0 log "开始生成 Web 端背景图与主题资源" ( cd "$CALENDAR_DIR" npm run export:themes ) || publish_status=$? if [ "$publish_status" -ne 0 ]; then rm -rf "$temp_publish_dir" return "$publish_status" fi log "开始发布到目标目录:$OUTPUT_DIR" mkdir -p "$OUTPUT_DIR" # 先把本轮导出结果完整复制到临时目录,确认结构无误后再整体 rsync 到目标目录, # 避免 Web 根目录在导出过程中暴露半成品文件。 rsync -a --delete "$DIST_DIR"/ "$temp_publish_dir"/ || publish_status=$? if [ "$publish_status" -eq 0 ]; then rsync -a --delete "$temp_publish_dir"/ "$OUTPUT_DIR"/ || publish_status=$? fi rm -rf "$temp_publish_dir" if [ "$publish_status" -ne 0 ]; then return "$publish_status" fi log "发布完成:$OUTPUT_DIR" } sleep_until_next_run() { interval_seconds=$((INTERVAL_MINUTES * 60)) now_epoch=$(date '+%s') next_epoch=$(( ((now_epoch / interval_seconds) + 1) * interval_seconds )) sleep_seconds=$((next_epoch - now_epoch)) if [ "$sleep_seconds" -le 0 ]; then sleep_seconds=$interval_seconds fi log "等待 ${sleep_seconds} 秒后执行下一轮生成" sleep "$sleep_seconds" } while [ "$#" -gt 0 ]; do case "$1" in -o|--output-dir) shift OUTPUT_DIR=${1:?"missing output dir"} ;; --interval-minutes) shift INTERVAL_MINUTES=${1:?"missing interval minutes"} ;; --once) RUN_ONCE=true ;; -h|--help) print_usage exit 0 ;; *) echo "未知参数: $1" >&2 echo >&2 print_usage >&2 exit 1 ;; esac shift done if [ -z "$OUTPUT_DIR" ]; then echo "必须通过 --output-dir 指定发布目录。" >&2 echo >&2 print_usage >&2 exit 1 fi validate_positive_integer "$INTERVAL_MINUTES" "interval-minutes" # 当前导图链路依赖 macOS 自带的 Swift + WKWebView。 # 如果部署机不是 macOS,这一步会失败,届时需要单独换成跨平台截图方案。 if [ ! -x /usr/bin/swift ]; then echo "未找到 /usr/bin/swift,当前机器无法使用现有 WebKit 导图链路。" >&2 exit 1 fi while true; do if publish_once; then : else status=$? log "本轮发布失败,退出码:$status" if [ "$RUN_ONCE" = true ]; then exit "$status" fi fi if [ "$RUN_ONCE" = true ]; then break fi sleep_until_next_run done