| #!/usr/bin/env bash |
| set -uo pipefail |
|
|
| ENV_FILE="/etc/profile.d/openclaw-env.sh" |
| LOG_FILE="/var/log/openclaw/env-update.log" |
| CACHE_FILE="/tmp/hf-env-cache.json" |
| EXPORT_FILE="/tmp/env-from-api.sh" |
|
|
| DRY_RUN=false |
|
|
| usage() { |
| cat <<EOF |
| Usage: $0 [OPTIONS] |
| |
| 从 Hugging Face API 获取最新的环境变量并更新到本地文件。 |
| |
| 必需的环境变量: |
| HF_TOKEN 或 HF_API_TOKEN HuggingFace API Token |
| OPENCLAW_HF_SPACE_ID HuggingFace Space ID |
| |
| 选项: |
| --dry-run 预览将从 API 获取的环境变量,不写入任何文件 |
| -h, --help 显示本帮助信息 |
| |
| 使用示例: |
| # 预览模式(不写入文件) |
| HF_TOKEN=hf_xxxxx OPENCLAW_HF_SPACE_ID=username/space-name $0 --dry-run |
| |
| # 正常执行 |
| HF_TOKEN=hf_xxxxx OPENCLAW_HF_SPACE_ID=username/space-name $0 |
| |
| # 使用 HF_API_TOKEN |
| HF_API_TOKEN=hf_xxxxx OPENCLAW_HF_SPACE_ID=username/space-name $0 |
| |
| EOF |
| } |
|
|
| while [[ $# -gt 0 ]]; do |
| case "$1" in |
| --dry-run) |
| DRY_RUN=true |
| shift |
| ;; |
| -h|--help) |
| usage |
| exit 0 |
| ;; |
| *) |
| echo "Unknown option: $1" |
| usage |
| exit 1 |
| ;; |
| esac |
| done |
|
|
| mkdir -p /var/log/openclaw |
|
|
| log() { |
| echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $1" | tee -a "$LOG_FILE" |
| } |
|
|
| log_dry() { |
| echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] [DRY-RUN] $1" |
| } |
|
|
| fetch_and_show_env() { |
| local OPENCLAW_HF_SPACE_ID="$1" |
| local api_token="$2" |
|
|
| if [[ -z "$OPENCLAW_HF_SPACE_ID" ]] || [[ -z "$api_token" ]]; then |
| log "Error: OPENCLAW_HF_SPACE_ID or API_TOKEN is empty" |
| return 1 |
| fi |
|
|
| log "Fetching environment variables from HF API for space: $OPENCLAW_HF_SPACE_ID" |
|
|
| local response |
| response=$(curl -s -w "\n%{http_code}" \ |
| -H "Authorization: Bearer $api_token" \ |
| "https://huggingface.co/api/spaces/$OPENCLAW_HF_SPACE_ID/runtime" 2>/dev/null) |
|
|
| local http_code=$(echo "$response" | tail -n1) |
| local body=$(echo "$response" | sed '$d') |
|
|
| if [[ "$http_code" != "200" ]]; then |
| log "Error: API request failed with HTTP $http_code" |
| log "Response: $body" |
| return 1 |
| fi |
|
|
| echo "$body" > "$CACHE_FILE" |
|
|
| if ! command -v jq >/dev/null 2>&1; then |
| log "Error: jq not available, cannot parse API response" |
| return 1 |
| fi |
|
|
| local env_count |
| env_count=$(echo "$body" | jq '.env // {} | length') |
| if [[ "$env_count" -eq 0 ]]; then |
| log "Warning: API response contains no environment variables" |
| return 1 |
| fi |
|
|
| log "Found $env_count environment variables from API" |
| echo "" |
|
|
| if [[ "$DRY_RUN" == "true" ]]; then |
| log_dry "========== DRY-RUN: Environment Variables to be fetched ==========" |
| else |
| : > "$EXPORT_FILE" |
| fi |
|
|
| local sensitive_pattern="(TOKEN|KEY|SECRET|PASSWORD|ENCRYPTION_PASSWORD)" |
| while IFS='=' read -r key value; do |
| if [[ -n "$key" && "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then |
| if [[ "$DRY_RUN" == "true" ]]; then |
| if [[ "$key" =~ $sensitive_pattern ]]; then |
| log_dry " $key=<sensitive>" |
| else |
| log_dry " $key=$value" |
| fi |
| else |
| printf 'export %s=%q\n' "$key" "$value" >> "$EXPORT_FILE" |
| if [[ "$key" =~ $sensitive_pattern ]]; then |
| log "Exported: $key=<sensitive>" |
| else |
| log "Exported: $key=$value" |
| fi |
| fi |
| fi |
| done < <(echo "$body" | jq -r '.env // {} | to_entries[] | "\(.key)=\(.value)"') |
|
|
| if [[ "$DRY_RUN" == "true" ]]; then |
| log_dry "========== DRY-RUN: Would write to files ==========" |
| log_dry " ENV_FILE=$ENV_FILE (skipped in dry-run)" |
| log_dry " EXPORT_FILE=$EXPORT_FILE (skipped in dry-run)" |
| log_dry "========================================================" |
| rm -f "$CACHE_FILE" |
| fi |
|
|
| return 0 |
| } |
|
|
| main() { |
| log "Starting environment update from HF API..." |
| if [[ "$DRY_RUN" == "true" ]]; then |
| log "*** DRY-RUN MODE: No files will be written ***" |
| fi |
|
|
| local OPENCLAW_HF_SPACE_ID="${OPENCLAW_HF_SPACE_ID:-}" |
| if [[ -z "$OPENCLAW_HF_SPACE_ID" ]]; then |
| log "Error: OPENCLAW_HF_SPACE_ID is required but not set" |
| log "Please set OPENCLAW_HF_SPACE_ID environment variable" |
| exit 1 |
| fi |
|
|
| local hf_token="${HF_TOKEN:-${HF_API_TOKEN:-}}" |
| if [[ -z "$hf_token" ]]; then |
| log "Error: HF_TOKEN is required but not set" |
| log "Please set HF_TOKEN or HF_API_TOKEN environment variable" |
| exit 1 |
| fi |
|
|
| if ! fetch_and_show_env "$OPENCLAW_HF_SPACE_ID" "$hf_token"; then |
| log "Warning: Failed to fetch env from API" |
| exit 1 |
| fi |
|
|
| if [[ "$DRY_RUN" == "true" ]]; then |
| log "Dry-run completed. No files were modified." |
| exit 0 |
| fi |
|
|
| if [[ -x /usr/local/bin/save-env.sh ]]; then |
| if [[ -f "$EXPORT_FILE" && -s "$EXPORT_FILE" ]]; then |
| log "Sourcing API exports before calling save-env.sh" |
| source "$EXPORT_FILE" |
| fi |
| /usr/local/bin/save-env.sh |
| log "Environment file updated successfully" |
| else |
| log "Error: save-env.sh not found or not executable" |
| exit 1 |
| fi |
|
|
| rm -f "$EXPORT_FILE" |
|
|
| log "Current non-sensitive variables:" |
| log " OPENCLAW_BACKUP_DATASET_REPO: ${OPENCLAW_BACKUP_DATASET_REPO:-<not set>}" |
| log " OPENCLAW_BACKUP_CRON: ${OPENCLAW_BACKUP_CRON:-*/12 * * * *}" |
| log " OPENCLAW_BACKUP_ENCRYPTION_ENABLED: ${OPENCLAW_BACKUP_ENCRYPTION_ENABLED:-<not set>}" |
| } |
|
|
| main "$@" 2>&1 | tee -a "$LOG_FILE" |