You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CircleCI中until循环执行docker compose logs grep异常返回255退出码

问题分析与解决方案

问题核心

你的Kafka就绪检测脚本在镜像构建耗时超过1分钟时失效,grep持续返回255错误码,但单独执行相同命令却能找到目标日志行。这是因为Kafka启动日志已被Docker日志滚动机制归档,默认的docker compose logs无法读取到历史滚动日志,同时命令中混用Docker Compose v1和v2版本也可能加剧这个问题。

具体原因

  1. 日志滚动导致启动日志丢失:Docker默认使用json-file日志驱动,当日志文件达到默认大小(通常10MB)或运行时间较久时,会自动滚动归档旧日志。当镜像构建耗时≥1分钟,Kafka的启动日志已经被归档到旧日志文件中,docker compose logs默认只读取当前活跃的日志文件,因此找不到目标行。
  2. Docker Compose版本混用:你在启动服务时用了v1的docker-compose up,而读取日志时用了v2的docker compose logs,两者在日志存储的兼容性上存在细微差异,可能导致部分历史日志无法被检索。
  3. 管道中断引发的异常:grep -q找到匹配后会立即退出,导致上游的docker compose logs进程收到SIGPIPE信号中断输出,后续循环中可能出现日志读取异常(虽然单独执行能成功,但循环中的连续执行可能触发这个问题)。

解决方案

方案1:强制读取所有历史日志

修改就绪检测脚本,添加--tail all参数让docker compose logs输出所有日志(包括已滚动的归档日志):

until docker compose logs --tail all kafka | grep -q "started (kafka.server.KafkaServer)"; do
  sleep 1
done
echo "Kafka is ready"

方案2:统一Docker Compose版本

将所有命令切换为v2的docker compose,避免版本混用带来的兼容性问题:

- run:
    name: 'Start background services'
    working_directory: services
    background: true
    command: docker compose up

方案3:改用更可靠的就绪检测方式

依赖日志的检测方式容易受日志滚动影响,建议使用Kafka自带的工具或端口检测来验证就绪状态:

方式A:使用Kafka主题列表命令检测(推荐)

until docker compose exec -T kafka kafka-topics.sh --list --bootstrap-server localhost:9092 > /dev/null 2>&1; do
  sleep 1
done
echo "Kafka is ready"

(添加-T参数避免终端交互问题,适配CI环境)

方式B:使用端口检测(简易版)

until nc -z localhost 9092; do
  sleep 1
done
echo "Kafka is ready"

注意:端口通了仅代表Kafka进程在运行,不代表服务完全就绪,生产或严格测试环境建议用方式A。

方案4:调整Docker日志滚动策略

在services/docker-compose.yml中修改Kafka的日志配置,增大日志文件大小或禁用滚动,确保启动日志不会被快速归档:

services:
  kafka:
    # 其他配置...
    logging:
      driver: "json-file"
      options:
        max-size: "100m"  # 增大单日志文件大小
        max-file: "5"     # 保留更多归档文件

内容的提问来源于stack exchange,提问作者MasterOdin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 19:25:29