ohmyapi commited on
Commit
3c7791a
·
verified ·
1 Parent(s): 2927da7

revert: restore to 03e51a9 baseline (remove cleanup scripts)

Browse files
Files changed (4) hide show
  1. Dockerfile +3 -6
  2. cleanup_tokens.sh +0 -217
  3. config.yaml +3 -1
  4. entrypoint.sh +0 -54
Dockerfile CHANGED
@@ -2,20 +2,17 @@ FROM eceasy/cli-proxy-api:latest
2
 
3
  USER root
4
 
5
- RUN apk add --no-cache bash libc6-compat gcompat jq
6
 
7
  WORKDIR /app
8
  RUN cp /CLIProxyAPI/CLIProxyAPI ./cli-proxy-api && chmod +x ./cli-proxy-api
9
  RUN mkdir -p /tmp/.cli-proxy-api /tmp/logs /tmp/pg_cache/pgstore && chmod -R 777 /tmp
10
 
11
  COPY config.yaml /app/config.yaml
12
- COPY cleanup_tokens.sh /app/cleanup_tokens.sh
13
- COPY entrypoint.sh /app/entrypoint.sh
14
-
15
  RUN cp /app/config.yaml /app/config.example.yaml
16
- RUN chmod +x /app/cleanup_tokens.sh /app/entrypoint.sh
17
 
18
  ENV TZ=Asia/Shanghai
19
  EXPOSE 7860
20
 
21
- CMD ["/app/entrypoint.sh"]
 
2
 
3
  USER root
4
 
5
+ RUN apk add --no-cache bash libc6-compat gcompat
6
 
7
  WORKDIR /app
8
  RUN cp /CLIProxyAPI/CLIProxyAPI ./cli-proxy-api && chmod +x ./cli-proxy-api
9
  RUN mkdir -p /tmp/.cli-proxy-api /tmp/logs /tmp/pg_cache/pgstore && chmod -R 777 /tmp
10
 
11
  COPY config.yaml /app/config.yaml
12
+ # 修复 config.example.yaml 缺失
 
 
13
  RUN cp /app/config.yaml /app/config.example.yaml
 
14
 
15
  ENV TZ=Asia/Shanghai
16
  EXPOSE 7860
17
 
18
+ CMD ["./cli-proxy-api", "--config", "/app/config.yaml"]
cleanup_tokens.sh DELETED
@@ -1,217 +0,0 @@
1
- #!/bin/sh
2
- #
3
- # cleanup_tokens.sh - Remove invalid/unavailable auth tokens via CLIProxyAPI Management API
4
- #
5
- # Environment variables:
6
- # MANAGEMENT_PASSWORD CLIProxyAPI management API password (required)
7
- # FEISHU_WEBHOOK_URL Feishu bot webhook URL for notifications (optional)
8
- # CLEANUP_CONCURRENCY Max parallel DELETE requests (default: 20)
9
- #
10
-
11
- API_BASE="http://localhost:7860/v0/management"
12
- TIMESTAMP="$(date '+%Y-%m-%d %H:%M:%S')"
13
- LOG_PREFIX="[cleanup_tokens] ${TIMESTAMP}"
14
- TMP_FILE="/tmp/auth_files_$$.json"
15
- TMP_NAMES="/tmp/auth_names_$$.txt"
16
- TMP_DIR="/tmp/cleanup_$$"
17
-
18
- CONCURRENCY="${CLEANUP_CONCURRENCY:-20}"
19
-
20
- cleanup_tmp() {
21
- rm -f "$TMP_FILE" "$TMP_NAMES"
22
- rm -rf "$TMP_DIR"
23
- }
24
- trap cleanup_tmp EXIT
25
-
26
- # ---------------------------------------------------------------------------
27
- # notify_feishu TITLE BODY
28
- # ---------------------------------------------------------------------------
29
- notify_feishu() {
30
- [ -z "$FEISHU_WEBHOOK_URL" ] && return 0
31
- PAYLOAD=$(jq -n --arg title "$1" --arg body "$2" '{
32
- msg_type: "post",
33
- content: { post: { zh_cn: {
34
- title: $title,
35
- content: [[{"tag": "text", "text": $body}]]
36
- }}}
37
- }')
38
- curl -sf -X POST -H "Content-Type: application/json" \
39
- -d "$PAYLOAD" "$FEISHU_WEBHOOK_URL" > /dev/null 2>&1 \
40
- && echo "${LOG_PREFIX} Feishu notification sent." \
41
- || echo "${LOG_PREFIX} WARNING: Failed to send Feishu notification."
42
- }
43
-
44
- # ---------------------------------------------------------------------------
45
- # delete_one NAME — writes result to $TMP_DIR/<name>.result
46
- # Format: "OK <name>" or "ERR <name> <http_status>"
47
- # ---------------------------------------------------------------------------
48
- delete_one() {
49
- NAME="$1"
50
- ENCODED=$(printf '%s' "$NAME" | sed 's/@/%40/g; s/ /%20/g')
51
- RESULT_FILE="${TMP_DIR}/$(printf '%s' "$NAME" | md5sum | cut -d' ' -f1).result"
52
-
53
- HTTP_ST=$(curl -s -o /dev/null -w "%{http_code}" \
54
- -X DELETE \
55
- -H "Authorization: Bearer ${MANAGEMENT_PASSWORD}" \
56
- "${API_BASE}/auth-files?name=${ENCODED}" 2>/dev/null)
57
-
58
- if [ "$HTTP_ST" = "200" ]; then
59
- printf 'OK %s\n' "$NAME" > "$RESULT_FILE"
60
- else
61
- printf 'ERR %s %s\n' "$NAME" "$HTTP_ST" > "$RESULT_FILE"
62
- fi
63
- }
64
-
65
- # ---------------------------------------------------------------------------
66
- # Main
67
- # ---------------------------------------------------------------------------
68
-
69
- if [ -z "$MANAGEMENT_PASSWORD" ]; then
70
- echo "${LOG_PREFIX} ERROR: MANAGEMENT_PASSWORD not set, skipping cleanup"
71
- exit 1
72
- fi
73
-
74
- echo "${LOG_PREFIX} Starting invalid token cleanup... (concurrency=${CONCURRENCY})"
75
-
76
- # --- Fetch auth file list ---------------------------------------------------
77
- HTTP_STATUS=$(curl -s -o "$TMP_FILE" -w "%{http_code}" \
78
- -H "Authorization: Bearer ${MANAGEMENT_PASSWORD}" \
79
- "${API_BASE}/auth-files" 2>/dev/null)
80
-
81
- if [ "$HTTP_STATUS" != "200" ]; then
82
- MSG="API 返回 HTTP ${HTTP_STATUS},服务可能尚未就绪。"
83
- echo "${LOG_PREFIX} ERROR: ${MSG}"
84
- notify_feishu "❌ Token 清理失败" "[TIME] ${TIMESTAMP}
85
-
86
- [ERROR] ${MSG}"
87
- exit 1
88
- fi
89
-
90
- if ! jq empty "$TMP_FILE" 2>/dev/null; then
91
- echo "${LOG_PREFIX} ERROR: Invalid JSON response"
92
- notify_feishu "❌ Token 清理失败" "[TIME] ${TIMESTAMP}
93
-
94
- [ERROR] API 返回了无效的 JSON 响应"
95
- exit 1
96
- fi
97
-
98
- TOTAL=$(jq '.files | length' "$TMP_FILE")
99
- echo "${LOG_PREFIX} Total auth files: ${TOTAL}"
100
-
101
- [ "$TOTAL" -eq 0 ] && { echo "${LOG_PREFIX} No auth files found."; exit 0; }
102
-
103
- # --- Identify tokens to delete ---------------------------------------------
104
- jq -r '
105
- .files[] |
106
- select(.runtime_only != true) |
107
- select(
108
- .unavailable == true or
109
- (.status != null and (
110
- .status == "error" or .status == "expired" or
111
- .status == "invalid" or .status == "failed" or
112
- .status == "unauthorized" or .status == "quota_exceeded"
113
- ))
114
- ) |
115
- .name
116
- ' "$TMP_FILE" > "$TMP_NAMES"
117
-
118
- TO_DELETE=$(grep -c '' "$TMP_NAMES" 2>/dev/null || echo 0)
119
- echo "${LOG_PREFIX} Tokens to delete: ${TO_DELETE}"
120
-
121
- if [ "$TO_DELETE" -eq 0 ]; then
122
- echo "${LOG_PREFIX} All tokens healthy, nothing to clean up."
123
- notify_feishu "✅ Token 状态检查" "[TIME] ${TIMESTAMP}
124
-
125
- [STATS] 共 ${TOTAL} 个 token,全部健康
126
-
127
- [RESULT] 无需清理"
128
- exit 0
129
- fi
130
-
131
- # Log the plan
132
- while IFS= read -r NAME; do
133
- STATUS=$(jq -r --arg n "$NAME" '.files[] | select(.name==$n) | .status // "unknown"' "$TMP_FILE")
134
- echo "${LOG_PREFIX} - ${NAME} (${STATUS})"
135
- done < "$TMP_NAMES"
136
-
137
- # --- Parallel DELETE with concurrency control ------------------------------
138
- mkdir -p "$TMP_DIR"
139
-
140
- ACTIVE=0
141
- while IFS= read -r NAME; do
142
- [ -z "$NAME" ] && continue
143
-
144
- # Launch delete in background
145
- delete_one "$NAME" &
146
- ACTIVE=$((ACTIVE + 1))
147
-
148
- # When we hit the concurrency limit, wait for all current batch to finish
149
- if [ "$ACTIVE" -ge "$CONCURRENCY" ]; then
150
- wait
151
- ACTIVE=0
152
- fi
153
- done < "$TMP_NAMES"
154
-
155
- # Wait for any remaining background jobs
156
- wait
157
-
158
- # --- Collect results -------------------------------------------------------
159
- DELETED=0
160
- ERRORS=0
161
- DETAIL_LINES=""
162
- ERROR_LINES=""
163
-
164
- # Re-read the names file to preserve status info for the notification
165
- while IFS= read -r NAME; do
166
- [ -z "$NAME" ] && continue
167
- RESULT_FILE="${TMP_DIR}/$(printf '%s' "$NAME" | md5sum | cut -d' ' -f1).result"
168
- RESULT=$(cat "$RESULT_FILE" 2>/dev/null)
169
-
170
- case "$RESULT" in
171
- OK*)
172
- STATUS=$(jq -r --arg n "$NAME" '.files[] | select(.name==$n) | .status // "unknown"' "$TMP_FILE")
173
- echo "${LOG_PREFIX} DELETED: ${NAME}"
174
- DELETED=$((DELETED + 1))
175
- DETAIL_LINES="${DETAIL_LINES} • ${NAME} [${STATUS}]\n"
176
- ;;
177
- ERR*)
178
- HTTP_ST=$(echo "$RESULT" | awk '{print $3}')
179
- echo "${LOG_PREFIX} ERROR deleting ${NAME} (HTTP ${HTTP_ST})"
180
- ERRORS=$((ERRORS + 1))
181
- ERROR_LINES="${ERROR_LINES} • ${NAME} (HTTP ${HTTP_ST})\n"
182
- ;;
183
- *)
184
- echo "${LOG_PREFIX} WARNING: No result for ${NAME}"
185
- ERRORS=$((ERRORS + 1))
186
- ERROR_LINES="${ERROR_LINES} • ${NAME} (no result)\n"
187
- ;;
188
- esac
189
- done < "$TMP_NAMES"
190
-
191
- echo "${LOG_PREFIX} Done. Deleted: ${DELETED}, Errors: ${ERRORS}"
192
-
193
- # --- Feishu notification ---------------------------------------------------
194
- # printf to interpret \n in the accumulated lines
195
- DETAIL_LINES=$(printf '%b' "$DETAIL_LINES")
196
- ERROR_LINES=$(printf '%b' "$ERROR_LINES")
197
-
198
- if [ "$ERRORS" -gt 0 ]; then
199
- notify_feishu "⚠️ Token 清理完成(有错误)" "[TIME] ${TIMESTAMP}
200
-
201
- [STATS] 共 ${TOTAL} 个 token,发现 ${TO_DELETE} 个失效
202
-
203
- ────────────────────
204
- [SUCCESS] 已删除 ${DELETED} 个:
205
- ${DETAIL_LINES}
206
- [FAIL] 删除失败 ${ERRORS} 个:
207
- ${ERROR_LINES}────────────────────"
208
- else
209
- notify_feishu "🧹 Token 清理完成" "[TIME] ${TIMESTAMP}
210
-
211
- [STATS] 共 ${TOTAL} 个 token,清理 ${DELETED} 个失效
212
-
213
- ────────────────────
214
- [REMOVED] 已删除:
215
- ${DETAIL_LINES}────────────────────
216
- [RESULT] Success: ${DELETED}/${TO_DELETE} | Failed: 0/${TO_DELETE}"
217
- fi
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
config.yaml CHANGED
@@ -1,6 +1,8 @@
1
  host: "0.0.0.0"
2
  port: 7860
3
 
 
 
4
  auth-dir: "/tmp/.cli-proxy-api"
5
  logging-to-file: true
6
  logs-dir: "/tmp/logs"
@@ -10,4 +12,4 @@ remote-management:
10
  secret-key: "${MANAGEMENT_PASSWORD}"
11
 
12
  commercial-mode: true
13
- debug: false
 
1
  host: "0.0.0.0"
2
  port: 7860
3
 
4
+ pgstore-dsn: "${PGSTORE_DSN}"
5
+
6
  auth-dir: "/tmp/.cli-proxy-api"
7
  logging-to-file: true
8
  logs-dir: "/tmp/logs"
 
12
  secret-key: "${MANAGEMENT_PASSWORD}"
13
 
14
  commercial-mode: true
15
+ debug: false
entrypoint.sh DELETED
@@ -1,54 +0,0 @@
1
- #!/bin/sh
2
- #
3
- # entrypoint.sh - Start crond for scheduled cleanup, then launch CLIProxyAPI
4
- #
5
- # Environment variables:
6
- # CLEANUP_CRON_SCHEDULE - Cron schedule for token cleanup (default: "0 */6 * * *", every 6h)
7
- # CLEANUP_STARTUP_DELAY - Seconds to wait after service is ready before first cleanup (default: 10)
8
- #
9
-
10
- echo "[entrypoint] Starting up at $(date)"
11
-
12
- CLEANUP_CRON_SCHEDULE="${CLEANUP_CRON_SCHEDULE:-0 */6 * * *}"
13
- CLEANUP_STARTUP_DELAY="${CLEANUP_STARTUP_DELAY:-10}"
14
- CRON_OK=0
15
-
16
- mkdir -p /tmp/logs /tmp/crontabs
17
-
18
- # Write crontab to /tmp (HuggingFace root filesystem is read-only)
19
- cat > /tmp/crontabs/root << EOF
20
- ${CLEANUP_CRON_SCHEDULE} /app/cleanup_tokens.sh >> /tmp/logs/cleanup.log 2>&1
21
- EOF
22
-
23
- echo "[entrypoint] Cleanup schedule: ${CLEANUP_CRON_SCHEDULE}"
24
-
25
- # Try crond; if it fails, fall back to a sleep loop
26
- if crond -c /tmp/crontabs -l 8 -L /tmp/logs/crond.log 2>/dev/null; then
27
- echo "[entrypoint] crond started"
28
- CRON_OK=1
29
- else
30
- echo "[entrypoint] WARNING: crond failed, will use sleep-loop fallback"
31
- fi
32
-
33
- # Background: wait for API ready, run initial cleanup, then optionally loop
34
- (
35
- MAX_WAIT=120
36
- WAITED=0
37
- while ! wget -q -O /dev/null http://localhost:7860/ 2>/dev/null; do
38
- sleep 2
39
- WAITED=$((WAITED + 2))
40
- [ "$WAITED" -ge "$MAX_WAIT" ] && break
41
- done
42
- sleep "${CLEANUP_STARTUP_DELAY}"
43
- /app/cleanup_tokens.sh >> /tmp/logs/cleanup.log 2>&1
44
-
45
- if [ "$CRON_OK" = "0" ]; then
46
- while true; do
47
- sleep 21600
48
- /app/cleanup_tokens.sh >> /tmp/logs/cleanup.log 2>&1
49
- done
50
- fi
51
- ) &
52
-
53
- echo "[entrypoint] Launching cli-proxy-api..."
54
- exec /app/cli-proxy-api --config /app/config.yaml "$@"