退出码
CloudBase CLI 使用结构化退出码(Exit Codes)来表示命令执行结果,便于 CI/CD 流水线、脚本和自动化工具进行错误处理和重试决策。
为什么需要退出码?
退出码是 Unix/Linux 进程的标准机制,用于告诉调用者命令是否成功以及失败原因的分类:
1. CI/CD 流程控制
# GitHub Actions 示例
- name: Deploy function
run: tcb fn deploy app --env-id ${{ secrets.ENV_ID }}
continue-on-error: false # 非 0 退出码会中断流水线
2. Shell 脚本错误处理
#!/bin/bash
set -e # 遇到非 0 退出码立即退出
tcb fn deploy app --env-id my-env
if [ $? -eq 2 ]; then
echo "认证失败,请重新登录"
tcb login
fi
3. 条件执行和重试
# 仅当函数部署成功时,才部署静态资源
tcb fn deploy && tcb hosting deploy
# 认证失败时自动重试登录
tcb fn list || (tcb login && tcb fn list)
4. 自动化测试
# 测试脚本验证 CLI 行为
tcb fn delete non-existent-func
EXIT_CODE=$?
if [ $EXIT_CODE -eq 4 ]; then
echo "✅ 资源不存在错误码正确"
else
echo "❌ 期望退出码 4,实际 $EXIT_CODE"
exit 1
fi
退出码定义
| 退出码 | 语义 | 触发场景 | 建议处理方式 |
|---|---|---|---|
| 0 | 成功 | 命令正常执行完成 | 继续下一步 |
| 1 | 通用错误 | 未分类的错误(兜底) | 查看错误信息,手动排查 |
| 2 | 认证失败 | 未登录、Token 过期、无权限 | 执行 tcb login 重新登录 |
| 3 | 参数错误 | 缺少必填参数、格式错误、枚举值非法 | 检查命令参数,参考 --help |
| 4 | 资源不存在 | 函数名/环境 ID 无效、集合不存在等 | 确认资源名称是否正确 |
| 5 | 云 API 错误 | CloudBase API 返回错误、网络超时 | 检查网络连接,查看 --verbose 日志 |
| 6 | 本地文件错误 | cloudbaserc.json 缺失/损坏、路径不存在 | 检查配置文件和路径 |
使用场景
场景 1: 条件执行
# 仅当函数部署成功时,才部署静态资源
tcb fn deploy app && tcb hosting deploy
场景 2: 错误捕获与处理
#!/bin/bash
tcb fn deploy app --env-id my-env
EXIT_CODE=$?
case $EXIT_CODE in
0)
echo "✅ 部署成功"
;;
2)
echo "❌ 认证失败,请重新登录"
tcb login
;;
3)
echo "❌ 参数错误,请检查命令"
exit 1
;;
4)
echo "❌ 资源不存在"
exit 1
;;
5)
echo "⚠️ 云 API 错误,5 秒后重试..."
sleep 5
tcb fn deploy app --env-id my-env
;;
*)
echo "❌ 未知错误(退出码 $EXIT_CODE)"
exit 1
;;
esac
场景 3: 重试机制
#!/bin/bash
MAX_RETRIES=3
RETRY_DELAY=5
for i in $(seq 1 $MAX_RETRIES); do
tcb fn deploy app --env-id my-env
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "✅ 部署成功"
exit 0
elif [ $EXIT_CODE -eq 5 ]; then
echo "⚠️ 云 API 错误,$RETRY_DELAY 秒后重试(第 $i/$MAX_RETRIES 次)"
sleep $RETRY_DELAY
else
echo "❌ 不可重试的错误(退出码 $EXIT_CODE)"
exit $EXIT_CODE
fi
done
echo "❌ 重试 $MAX_RETRIES 次后仍失败"
exit 1
场景 4: 批量操作
#!/bin/bash
FUNCTIONS=("func1" "func2" "func3")
FAILED=()
for func in "${FUNCTIONS[@]}"; do
tcb fn deploy "$func" --yes
if [ $? -ne 0 ]; then
FAILED+=("$func")
fi
done
if [ ${#FAILED[@]} -gt 0 ]; then
echo "❌ 以下函数部署失败:"
printf '%s\n' "${FAILED[@]}"
exit 1
else
echo "✅ 所有函数部署成功"
fi
场景 5: Makefile
.PHONY: deploy test clean
deploy:
@echo "部署函数..."
@tcb fn deploy app --env-id $(ENV_ID)
@echo "部署静态资源..."
@tcb hosting deploy --env-id $(ENV_ID)
test:
@echo "运行测试..."
@tcb fn invoke app --env-id $(ENV_ID) --data '{"test": true}'
@if [ $$? -eq 0 ]; then \
echo "✅ 测试通过"; \
else \
echo "❌ 测试失败"; \
exit 1; \
fi
clean:
@echo "清理资源..."
@tcb fn delete app --yes --env-id $(ENV_ID) || true
CI/CD 最佳实践
GitHub Actions
name: Deploy to CloudBase
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install CloudBase CLI
run: npm install -g @cloudbase/cli
- name: Login to CloudBase
run: |
echo "${{ secrets.CLOUDBASE_SECRET_ID }}" > /tmp/secret_id
echo "${{ secrets.CLOUDBASE_SECRET_KEY }}" > /tmp/secret_key
tcb login --key --secretId $(cat /tmp/secret_id) --secretKey $(cat /tmp/secret_key)
- name: Deploy Function
id: deploy
run: |
tcb fn deploy app --env-id ${{ secrets.ENV_ID }} --json --yes
continue-on-error: true
- name: Handle Deployment Result
if: failure()
run: |
EXIT_CODE=${{ steps.deploy.outcome }}
if [ "$EXIT_CODE" = "2" ]; then
echo "认证失败,检查密钥配置"
exit 1
elif [ "$EXIT_CODE" = "5" ]; then
echo "云 API 错误,5 秒后重试"
sleep 5
tcb fn deploy app --env-id ${{ secrets.ENV_ID }} --json --yes
else
echo "部署失败(退出码 $EXIT_CODE)"
exit 1
fi
GitLab CI
deploy:
stage: deploy
image: node:18
script:
- npm install -g @cloudbase/cli
- tcb login --key --secretId $SECRET_ID --secretKey $SECRET_KEY
- tcb fn deploy app --env-id $ENV_ID --json --yes
retry:
max: 2
when:
- script_failure # 仅在脚本失败时重试
only:
- main
Jenkins
pipeline {
agent any
stages {
stage('Deploy') {
steps {
script {
def result = sh(
script: 'tcb fn deploy app --env-id ${ENV_ID} --json --yes',
returnStatus: true
)
if (result == 0) {
echo '✅ 部署成功'
} else if (result == 2) {
error '❌ 认证失败,检查密钥配置'
} else if (result == 5) {
echo '⚠️ 云 API 错误,重试中...'
sleep 5
sh 'tcb fn deploy app --env-id ${ENV_ID} --json --yes'
} else {
error "❌ 部署失败(退出码 ${result})"
}
}
}
}
}
}
调试方法
1. 查看退出码
tcb fn deploy app
echo "退出码: $?"
2. 使用 --verbose 查看详细日志
tcb fn deploy app --verbose
3. 使用 --json 获取结构化错误信息
tcb fn deploy app --json
输出示例:
{
"error": {
"code": "FUNCTION_NOT_FOUND",
"message": "函数 app 不存在",
"exit_code": 4
}
}
注意事项
退出码不是 HTTP 状态码
退出码4表示"资源不存在",不是 HTTP 404。退出码5表示"云 API 错误",不是 HTTP 500。--yes不影响退出码
--yes只跳过确认提示,不改变命令的执行结果和退出码。管道操作需要
set -e
在 Shell 脚本中,使用set -e确保管道中的任何命令失败都会中断执行:#!/bin/bash
set -e # 遇到非 0 退出码立即退出
tcb fn deploy app
tcb hosting deployCI/CD 中建议使用
--json
--json输出结构化数据,便于解析错误信息和提取字段。