Spaces:
Runtime error
Runtime error
| # 设置 DNS(在容器启动后执行) | |
| echo "nameserver 8.8.8.8" > /tmp/resolv.conf | |
| echo "nameserver 8.8.4.4" >> /tmp/resolv.conf | |
| cp /tmp/resolv.conf /etc/resolv.conf 2>/dev/null || true | |
| # 日志级别配置(默认 warning,可选 debug/info/warning) | |
| LOG_LEVEL="${LOG_LEVEL:-warning}" | |
| # 创建日志目录(/root/.opencode/logs 由 bucket 挂载) | |
| mkdir -p /root/.opencode/logs | |
| LOG_DIR='/root/.opencode/logs' | |
| LOG_MAX_SIZE=104857600 # 100MB | |
| log() { | |
| local level="$1" | |
| shift | |
| local message="$@" | |
| # 检查日志文件大小,超过 100MB 则重命名 | |
| if [ -f "$LOG_DIR/entrypoint.log" ]; then | |
| LOG_SIZE=$(wc -c < "$LOG_DIR/entrypoint.log" 2>/dev/null | awk '{print $1}') | |
| if [ -n "$LOG_SIZE" ] && [ "$LOG_SIZE" -gt "$LOG_MAX_SIZE" ]; then | |
| mv "$LOG_DIR/entrypoint.log" "$LOG_DIR/entrypoint-$(date +%Y-%m-%d).log" | |
| fi | |
| fi | |
| # 根据 LOG_LEVEL 过滤日志 | |
| case "$LOG_LEVEL" in | |
| debug) | |
| # debug: 显示所有日志 | |
| ;; | |
| info) | |
| # info: 只显示 info/warning/error | |
| [ "$level" = "debug" ] && return | |
| ;; | |
| warning) | |
| # warning: 只显示 warning/error | |
| [ "$level" = "debug" ] && return | |
| [ "$level" = "info" ] && return | |
| ;; | |
| esac | |
| # 额外过滤:控制台输出级别 | |
| local show_on_console=false | |
| [ "$level" = "error" ] && show_on_console=true | |
| [ "$level" = "warning" ] && show_on_console=true | |
| # debug 级别也显示到控制台(方便调试) | |
| [ "$LOG_LEVEL" = "debug" ] && [ "$level" = "debug" ] && show_on_console=true | |
| TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') | |
| if [ "$show_on_console" = true ]; then | |
| echo "[$TIMESTAMP] [$level] $message" | tee -a "$LOG_DIR/entrypoint.log" | |
| else | |
| echo "[$TIMESTAMP] $message" >> "$LOG_DIR/entrypoint.log" | |
| fi | |
| } | |
| OPENCODE_LOG_FILE="${LOG_DIR}/opencode.log" | |
| # 设置 OpenCode 路径(npm 安装后已在 PATH 中) | |
| export PATH="/root/.local/bin:/usr/local/bin:/usr/bin:/bin:$PATH" | |
| # ============================================ | |
| # 启动 OpenCode(带 RAM 监控) | |
| # ============================================ | |
| RAM_LIMIT_KB=$((14 * 1024 * 1024)) | |
| RAM_CHECK_INTERVAL=30 | |
| start_opencode() { | |
| log info "=== 启动 OpenCode ===" | |
| log debug "执行命令: opencode serve --port 7860 --hostname 0.0.0.0" | |
| export OPENCODE_SERVER_USERNAME=${OPENCODE_SERVER_USERNAME} | |
| export OPENCODE_SERVER_PASSWORD=${OPENCODE_SERVER_PASSWORD} | |
| opencode serve --port 7860 --hostname 0.0.0.0 > "$OPENCODE_LOG_FILE" 2>&1 & | |
| OPENCODE_PID=$! | |
| log info "=== OpenCode 已启动(PID: $OPENCODE_PID)===" | |
| } | |
| ram_watchdog() { | |
| while true; do | |
| if [ -n "$OPENCODE_PID" ] && kill -0 "$OPENCODE_PID" 2>/dev/null; then | |
| USED_KB=$(ps --no-headers -o rss --ppid "$OPENCODE_PID" 2>/dev/null | awk '{sum+=$1} END {print sum+0}') | |
| SELF_KB=$(ps --no-headers -o rss -p "$OPENCODE_PID" 2>/dev/null | awk '{print $1+0}') | |
| TOTAL_KB=$((USED_KB + SELF_KB)) | |
| # debug 模式显示详细 RAM 信息 | |
| if [ "$LOG_LEVEL" = "debug" ]; then | |
| USED_MB=$((USED_KB / 1024)) | |
| SELF_MB=$((SELF_KB / 1024)) | |
| TOTAL_MB=$((TOTAL_KB / 1024)) | |
| RAM_PERCENT=$((TOTAL_KB * 100 / RAM_LIMIT_KB)) | |
| log debug "RAM: ${TOTAL_MB}MB / 14336MB (${RAM_PERCENT}%)" | |
| fi | |
| if [ "$TOTAL_KB" -ge "$RAM_LIMIT_KB" ]; then | |
| log warning "=== [RAM] 内存超限!杀死 OpenCode(${TOTAL_KB}KB >= ${RAM_LIMIT_KB}KB)===" | |
| kill -9 "$OPENCODE_PID" 2>/dev/null | |
| sleep 3 | |
| log warning '=== [RAM] 重启 OpenCode... ===' | |
| start_opencode | |
| fi | |
| else | |
| log warning '=== [RAM] OpenCode 未运行!重启... ===' | |
| start_opencode | |
| fi | |
| sleep "$RAM_CHECK_INTERVAL" | |
| done | |
| } | |
| start_opencode | |
| ram_watchdog & | |
| log info "=== OpenCode 运行中 ===" | |
| # 无限循环:检查 OpenCode 是否运行 | |
| while true; do | |
| pgrep -f 'opencode' > /dev/null || { log error '严重错误:OpenCode 进程已退出!容器退出...'; exit 1; } | |
| sleep "$RAM_CHECK_INTERVAL" | |
| done |