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

BitBucket Pipelines执行Shell脚本时跳过后续命令的问题

BitBucket Pipelines SSH执行脚本时后续命令被跳过的问题排查与解决

我来帮你分析这个问题,这种情况大概率是SSH通过管道接收脚本内容时,脚本中的某些命令(比如./gradlew build)会读取标准输入(stdin),导致后续的脚本内容被这些命令“吃掉”,从而中断了脚本的执行。

问题根源

当你用cat ./deploy.sh | ssh -T user@[myIp]这种方式执行时,SSH会把管道里的脚本内容作为远程shell的stdin。而./gradlew build这类命令在运行过程中可能会尝试读取stdin(比如Gradle的某些内部机制、潜在的交互场景),这就会把后续还没执行的脚本内容当作输入读走,导致脚本到这一步之后就没下文了。

解决方案

这里有几种可靠的解决方式,按推荐程度排序:

1. 先把脚本上传到服务器再执行(最稳妥)

彻底避免管道传递的问题,先通过SCP把脚本传到服务器,再远程执行:

step:
    name: Deploy dev
    trigger: manual
    script:
      - scp ./deploy.sh user@[myIp]:/tmp/deploy.sh
      - ssh user@[myIp] "chmod +x /tmp/deploy.sh && /tmp/deploy.sh dev && rm /tmp/deploy.sh"

这样脚本是在服务器本地完整执行的,完全不会有stdin被抢占的问题。

2. 使用SSH的-n参数禁止读取stdin

ssh -n会把SSH的stdin重定向到/dev/null,这样远程命令就不会读取管道里的脚本内容了:

step:
    name: Deploy dev
    trigger: manual
    script:
      - cat ./deploy.sh | ssh -n user@[myIp]

注意:如果你的脚本里有需要交互输入的步骤(比如输入密码),这个参数会导致问题,但你的脚本里没有交互逻辑,所以这个方法完全适用。

3. 将脚本作为字符串传递给SSH

把脚本内容直接作为SSH命令的一部分执行,避免依赖管道stdin:

step:
    name: Deploy dev
    trigger: manual
    script:
      - ssh user@[myIp] "$(cat ./deploy.sh)" dev

这种方式把脚本内容打包成远程shell的命令字符串,只要脚本里没有复杂的特殊字符(比如嵌套引号、反斜杠),用起来会很方便。

4. 修改deploy.sh,让读取stdin的命令关闭输入

在./gradlew build这一行后追加< /dev/null,强制它不从stdin读取内容:

echo "---------------------------------------- | BUILD API"
cd ${basePath}/API
./gradlew build < /dev/null

这样Gradle就不会抢占脚本的stdin,后续命令就能正常执行了。这个方法适合不想修改Pipeline步骤的场景。

验证建议

你可以先在本地模拟BitBucket的执行方式测试:

cat ./deploy.sh | ssh -T user@[myIp]

如果本地这样执行也出现同样的问题,就能100%确认是stdin被抢占的问题,再用上面的方法解决即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:54:21