tfc-run-logs
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTerraform Cloud Run Logs
Terraform Cloud 运行日志
Retrieve and display plan and/or apply logs from Terraform Cloud runs directly in the terminal.
直接在终端中获取并展示Terraform Cloud运行任务的计划(plan)和/或执行(apply)日志。
Prerequisites
前提条件
bash
undefinedbash
undefinedRequired environment variables
Required environment variables
export TFE_TOKEN="your-api-token" # User or team token (not organization token)
export TFE_ADDRESS="app.terraform.io" # Optional, defaults to app.terraform.io
undefinedexport TFE_TOKEN="your-api-token" # User or team token (not organization token)
export TFE_ADDRESS="app.terraform.io" # Optional, defaults to app.terraform.io
undefinedCore Workflow
核心工作流程
Get Both Plan and Apply Logs
同时获取计划和执行日志
bash
#!/bin/bash
set -euo pipefail
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
RUN_ID="${1:?Usage: $0 <run-id>}"bash
#!/bin/bash
set -euo pipefail
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
RUN_ID="${1:?Usage: $0 <run-id>}"Get run with plan and apply relationships
Get run with plan and apply relationships
RUN_DATA=$(curl -sf --header "Authorization: Bearer $TOKEN"
"$BASE_URL/runs/$RUN_ID?include=plan,apply")
"$BASE_URL/runs/$RUN_ID?include=plan,apply")
RUN_DATA=$(curl -sf --header "Authorization: Bearer $TOKEN"
"$BASE_URL/runs/$RUN_ID?include=plan,apply")
"$BASE_URL/runs/$RUN_ID?include=plan,apply")
Extract IDs
Extract IDs
PLAN_ID=$(echo "$RUN_DATA" | jq -r '.data.relationships.plan.data.id')
APPLY_ID=$(echo "$RUN_DATA" | jq -r '.data.relationships.apply.data.id // empty')
PLAN_ID=$(echo "$RUN_DATA" | jq -r '.data.relationships.plan.data.id')
APPLY_ID=$(echo "$RUN_DATA" | jq -r '.data.relationships.apply.data.id // empty')
Get and display plan logs
Get and display plan logs
PLAN_LOG_URL=$(curl -sf --header "Authorization: Bearer $TOKEN"
"$BASE_URL/plans/$PLAN_ID" | jq -r '.data.attributes."log-read-url"')
"$BASE_URL/plans/$PLAN_ID" | jq -r '.data.attributes."log-read-url"')
echo "=== PLAN OUTPUT ==="
curl -sf "$PLAN_LOG_URL" | sed 's/\x1b[[0-9;]*m//g' # Strip ANSI codes
PLAN_LOG_URL=$(curl -sf --header "Authorization: Bearer $TOKEN"
"$BASE_URL/plans/$PLAN_ID" | jq -r '.data.attributes."log-read-url"')
"$BASE_URL/plans/$PLAN_ID" | jq -r '.data.attributes."log-read-url"')
echo "=== PLAN OUTPUT ==="
curl -sf "$PLAN_LOG_URL" | sed 's/\x1b[[0-9;]*m//g' # Strip ANSI codes
Get apply logs if exists
Get apply logs if exists
if [ -n "$APPLY_ID" ]; then
APPLY_LOG_URL=$(curl -sf --header "Authorization: Bearer $TOKEN"
"$BASE_URL/applies/$APPLY_ID" | jq -r '.data.attributes."log-read-url"')
"$BASE_URL/applies/$APPLY_ID" | jq -r '.data.attributes."log-read-url"')
echo ""
echo "=== APPLY OUTPUT ==="
curl -sf "$APPLY_LOG_URL" | sed 's/\x1b[[0-9;]*m//g'
fi
undefinedif [ -n "$APPLY_ID" ]; then
APPLY_LOG_URL=$(curl -sf --header "Authorization: Bearer $TOKEN"
"$BASE_URL/applies/$APPLY_ID" | jq -r '.data.attributes."log-read-url"')
"$BASE_URL/applies/$APPLY_ID" | jq -r '.data.attributes."log-read-url"')
echo ""
echo "=== APPLY OUTPUT ==="
curl -sf "$APPLY_LOG_URL" | sed 's/\x1b[[0-9;]*m//g'
fi
undefinedGet Plan Logs Only
仅获取计划日志
bash
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
RUN_ID="run-abc123"bash
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
RUN_ID="run-abc123"Get plan ID from run
Get plan ID from run
PLAN_ID=$(curl -sf --header "Authorization: Bearer $TOKEN"
"$BASE_URL/runs/$RUN_ID" | jq -r '.data.relationships.plan.data.id')
"$BASE_URL/runs/$RUN_ID" | jq -r '.data.relationships.plan.data.id')
PLAN_ID=$(curl -sf --header "Authorization: Bearer $TOKEN"
"$BASE_URL/runs/$RUN_ID" | jq -r '.data.relationships.plan.data.id')
"$BASE_URL/runs/$RUN_ID" | jq -r '.data.relationships.plan.data.id')
Get log URL and fetch logs
Get log URL and fetch logs
PLAN_LOG_URL=$(curl -sf --header "Authorization: Bearer $TOKEN"
"$BASE_URL/plans/$PLAN_ID" | jq -r '.data.attributes."log-read-url"')
"$BASE_URL/plans/$PLAN_ID" | jq -r '.data.attributes."log-read-url"')
curl -sf "$PLAN_LOG_URL"
undefinedPLAN_LOG_URL=$(curl -sf --header "Authorization: Bearer $TOKEN"
"$BASE_URL/plans/$PLAN_ID" | jq -r '.data.attributes."log-read-url"')
"$BASE_URL/plans/$PLAN_ID" | jq -r '.data.attributes."log-read-url"')
curl -sf "$PLAN_LOG_URL"
undefinedGet Apply Logs Only
仅获取执行日志
bash
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
RUN_ID="run-abc123"bash
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
RUN_ID="run-abc123"Get apply ID from run
Get apply ID from run
APPLY_ID=$(curl -sf --header "Authorization: Bearer $TOKEN"
"$BASE_URL/runs/$RUN_ID" | jq -r '.data.relationships.apply.data.id')
"$BASE_URL/runs/$RUN_ID" | jq -r '.data.relationships.apply.data.id')
if [ -n "$APPLY_ID" ] && [ "$APPLY_ID" != "null" ]; then
Get log URL and fetch logs
APPLY_LOG_URL=$(curl -sf --header "Authorization: Bearer $TOKEN"
"$BASE_URL/applies/$APPLY_ID" | jq -r '.data.attributes."log-read-url"')
"$BASE_URL/applies/$APPLY_ID" | jq -r '.data.attributes."log-read-url"')
curl -sf "$APPLY_LOG_URL"
else
echo "No apply for this run"
fi
undefinedAPPLY_ID=$(curl -sf --header "Authorization: Bearer $TOKEN"
"$BASE_URL/runs/$RUN_ID" | jq -r '.data.relationships.apply.data.id')
"$BASE_URL/runs/$RUN_ID" | jq -r '.data.relationships.apply.data.id')
if [ -n "$APPLY_ID" ] && [ "$APPLY_ID" != "null" ]; then
Get log URL and fetch logs
APPLY_LOG_URL=$(curl -sf --header "Authorization: Bearer $TOKEN"
"$BASE_URL/applies/$APPLY_ID" | jq -r '.data.attributes."log-read-url"')
"$BASE_URL/applies/$APPLY_ID" | jq -r '.data.attributes."log-read-url"')
curl -sf "$APPLY_LOG_URL"
else
echo "No apply for this run"
fi
undefinedQuick One-Liners
快速单行命令
Plan Logs (with ANSI colors)
计划日志(保留ANSI颜色)
bash
curl -sf -H "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/run-abc123?include=plan" | \
jq -r '.included[0].attributes."log-read-url"' | xargs curl -sfbash
curl -sf -H "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/run-abc123?include=plan" | \
jq -r '.included[0].attributes."log-read-url"' | xargs curl -sfPlan Logs (clean text)
计划日志(纯文本)
bash
curl -sf -H "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/run-abc123?include=plan" | \
jq -r '.included[0].attributes."log-read-url"' | \
xargs curl -sf | sed 's/\x1b\[[0-9;]*m//g'bash
curl -sf -H "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/run-abc123?include=plan" | \
jq -r '.included[0].attributes."log-read-url"' | \
xargs curl -sf | sed 's/\x1b\[[0-9;]*m//g'Important Notes
重要说明
- Log URLs are secrets: Archivist URLs contain embedded authentication - don't log them
- URLs expire: Log URLs are valid for 25 hours
- No auth needed for logs: Once you have the archivist URL, no bearer token is required
- ANSI codes: Logs contain color codes; use to strip them for clean output
sed - Rate limits: endpoint is limited to 30 requests/minute
/runs
- 日志URL为敏感信息:归档URL包含内置认证信息 - 请勿记录这些URL
- URL会过期:日志URL的有效期为25小时
- 日志无需额外认证:获取归档URL后,无需再使用Bearer令牌即可访问日志
- ANSI代码:日志中包含颜色代码;可使用命令去除以得到纯文本输出
sed - 速率限制:接口的请求限制为每分钟30次
/runs
Common Errors
常见错误
404 Not Found
404 Not Found(未找到)
- Run ID doesn't exist OR you don't have permission
- TFC returns 404 for both cases (security measure)
- 运行ID不存在,或者您无访问权限
- TFC对这两种情况均返回404(安全机制)
401 Unauthorized
401 Unauthorized(未授权)
- Token is invalid or expired
- Organization tokens cannot access run data - use user/team token
- 令牌无效或已过期
- 组织令牌无法访问运行数据 - 请使用用户/团队令牌
No Apply Logs
无执行日志
- Run may be plan-only, not yet applied, or discarded
- Check run status first
- 运行任务可能仅执行了计划,尚未执行,或已被丢弃
- 请先检查运行任务状态
See Also
相关工具
- : Quick status check for a run
tfc-run-status - : List recent runs in a workspace
tfc-list-runs - : Get structured plan JSON output
tfc-plan-json
- :快速检查运行任务状态
tfc-run-status - :列出工作区中的近期运行任务
tfc-list-runs - :获取结构化的计划JSON输出
tfc-plan-json