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

Docker Compose运行Shell脚本时$SECONDS变量失效报错排查

问题根因

$SECONDS是Bash Shell专属的内置变量,(( ))双括号算术判断语法也是Bash独有的特性。
你在容器中执行脚本时默认调用的是/bin/sh,绝大多数Docker基础镜像(Alpine、Debian Slim等)中的/bin/sh是dash、ash这类轻量POSIX标准Shell,既不内置$SECONDS变量,也不支持双括号算术语法。这种环境下$SECONDS取值为空,判断语句里的<会被解析为文件重定向符,整段逻辑就变成尝试打开名为120的文件读取输入,最终抛出你看到的can't open 120: no such file报错。

可用解决方案

方案1:显式使用Bash执行脚本(保留原有$SECONDS写法)

  • 修改脚本第一行的shebang声明,替换为Bash路径:
#!/bin/bash
  • 如果使用的是Alpine这类默认不带Bash的极小基础镜像,先在Dockerfile中安装Bash:
RUN apk add --no-cache bash
  • 在docker-compose.yml的启动命令中,显式调用Bash执行脚本,不要用sh调用:
command: bash /opt/app/zuulStartContainer.sh

改完后原有依赖$SECONDS的逻辑可以直接正常运行,和宿主机行为完全一致。

方案2:改写为POSIX兼容逻辑(无额外依赖,适配所有Shell环境)

如果不想额外安装Bash,可以放弃$SECONDS和Bash专属语法,用Unix时间戳自行计算等待时长,所有标准POSIX Shell都能直接运行,改完的脚本示例如下:

echo "right before second"
start_time=$(date +%s)
echo "start at timestamp: ${start_time}"
echo "right after second"

interval=10
max_wait=120

while true; do
    current_time=$(date +%s)
    waited_time=$((current_time - start_time))
    
    if [ ${waited_time} -ge ${max_wait} ]; then
        break
    fi

    SuccessMessage=$(grep "successful" "$LOG_FILE" | wc -l)
    if [ "$SuccessMessage" -gt 0 ]; then
        echo "Successful"
        exit 0
    fi

    echo "Waiting... (already waited ${waited_time}s)"
    sleep ${interval}
done

echo "Failed to Start"
exit 1

注意:该写法不需要依赖Bash,脚本shebang写#!/bin/sh即可,在宿主机和任意Docker容器环境下都能稳定运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 14:06:27