feat: add automatic token cleanup with crond + fixed /tmp/crontabs for HF read-only fs
Browse files- Dockerfile +6 -3
- cleanup_tokens.sh +217 -0
- config.yaml +1 -1
- entrypoint.sh +54 -0
Dockerfile
CHANGED
|
@@ -2,17 +2,20 @@ FROM eceasy/cli-proxy-api:latest
|
|
| 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 |
-
|
|
|
|
|
|
|
| 13 |
RUN cp /app/config.yaml /app/config.example.yaml
|
|
|
|
| 14 |
|
| 15 |
ENV TZ=Asia/Shanghai
|
| 16 |
EXPOSE 7860
|
| 17 |
|
| 18 |
-
CMD ["
|
|
|
|
| 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"]
|
cleanup_tokens.sh
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
@@ -12,4 +12,4 @@ remote-management:
|
|
| 12 |
secret-key: "${MANAGEMENT_PASSWORD}"
|
| 13 |
|
| 14 |
commercial-mode: true
|
| 15 |
-
debug: false
|
|
|
|
| 12 |
secret-key: "${MANAGEMENT_PASSWORD}"
|
| 13 |
|
| 14 |
commercial-mode: true
|
| 15 |
+
debug: false
|
entrypoint.sh
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 "$@"
|