Ubuntu下docker compose run捕获输出致终端冻结的脚本问题
解决
docker compose run捕获输出时脚本卡住的问题 问题分析
当用$()捕获docker compose run命令的输出时,脚本会卡在命令执行阶段无法继续。直接运行命令却正常,原因是docker compose run默认会分配TTY(终端),即使是非交互式场景,捕获输出时进程会因等待终端输入而挂起。
解决方案
方法1:禁用TTY分配(推荐)
给docker compose run添加-T参数,明确禁用TTY分配,让进程在无终端环境下正常执行:
#!/bin/bash set -x DOCKER_COMPOSE_FILE="/services/nginx/docker-compose.yml" echo "starting renewal" # 添加-T参数禁用TTY,避免进程挂起 output=$(/usr/bin/docker compose -f "$DOCKER_COMPOSE_FILE" run -T --rm certbot renew --force-renewal 2>&1) echo "docker script has run" # 此处添加发送output到日志服务商的逻辑,例如: # curl -H "Content-Type: text/plain" -X POST -d "$output" https://your-log-provider.com/endpoint
方法2:通过临时文件中转输出
如果不想修改docker compose命令参数,可以先将输出重定向到临时文件,再读取文件内容:
#!/bin/bash set -x DOCKER_COMPOSE_FILE="/services/nginx/docker-compose.yml" # 创建临时文件存储输出 TEMP_LOG=$(mktemp) echo "starting renewal" # 将命令输出写入临时文件 /usr/bin/docker compose -f "$DOCKER_COMPOSE_FILE" run --rm certbot renew --force-renewal 2>&1 > "$TEMP_LOG" # 读取临时文件内容到变量 output=$(cat "$TEMP_LOG") # 删除临时文件 rm "$TEMP_LOG" echo "docker script has run" # 发送output到日志服务商
额外注意事项
- 变量引用时添加双引号(如
"$DOCKER_COMPOSE_FILE"),避免路径包含空格时出现错误。 - 如果不需要调试,可移除
set -x以减少日志输出。
内容的提问来源于stack exchange,提问作者Andriy
相关产品推荐
相关产品推荐

