Terraform 常用 CLI 命令与工具详解

详解 Terraform 1.16.5 常用 CLI 命令与工具:init/validate/plan/apply/destroy/show/state/output/import/providers/workspace/console/fmt 等,每个命令给出完整用法、真实输出与参数说明,全部在 Ubuntu 22.04 实测

TerraformTerraformDevOps基础设施即代码2026/10/10

Terraform 常用 CLI 命令与工具详解

目标:详解 Terraform 1.16.5 常用的 CLI 命令与工具:init、validate、plan、apply、destroy、show、state、output、import、providers、workspace、console、fmt 等,每个命令给出完整用法、真实输出与参数说明。所有命令均在 Ubuntu 22.04 真实环境实测,以实际输出为准。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS
  • 系统架构:x86_64
  • Terraform 版本:1.16.5(/usr/local/bin/terraform)
  • 演示项目目录:/opt/data/terraform/demo(local backend,含 local_file/null_resource/random 资源)
  • Provider:hashicorp/local v2.9.1、hashicorp/null v3.3.2、hashicorp/random v3.9.1

二、工具概览

Terraform 是单一二进制 CLI,terraform -help 输出全部可用命令:

命令分类主要用途
init主工作流初始化工作目录(后端 + provider + 模块)
validate主工作流校验配置合法性
plan主工作流预览变更(只读)
apply主工作流创建或更新基础设施
destroy主工作流销毁已创建的基础设施
show状态/查询展示状态或保存的计划
state状态/查询状态文件高级管理(list/show/rm/mv)
output状态/查询展示输出值
import资源管理把已存在资源纳入状态管理
providers资源管理展示配置所需的 provider
graph资源管理输出依赖关系图(Graphviz)
get资源管理安装远程模块(init 已自动执行)
workspace工作区工作区管理(list/new/select/delete)
console表达式交互式表达式求值
fmt表达式格式化配置文件
version其他显示版本信息

💡 说明:terraform -help 的输出顺序即上表顺序——主工作流命令(init→validate→plan→apply→destroy)排最前,其余按字母序。-help 后跟子命令名可看子命令专属帮助(如 terraform state -help)。

三、前置条件

  • 已安装 Terraform 1.16.5(见《Ubuntu 22.04 安装 Terraform 指南》)
  • 已按《Terraform 工作区与项目初始化指南》完成项目初始化
  • 本文命令在 /opt/data/terraform/demo 目录执行;文中所有路径/回显均为该环境实测

四、核心工作流命令

4.1 terraform init(初始化)

初始化工作目录:配置 backend、下载 provider 插件、安装模块、生成 .terraform.lock.hcl 锁文件。

cd /opt/data/terraform/demo
terraform init

执行结果:

Initializing the backend...

Successfully configured the backend "local"! Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...
- Finding latest version of hashicorp/local...
- Finding latest version of hashicorp/null...
- Installing hashicorp/local v2.9.1...
- Installed hashicorp/local v2.9.1 (signed by HashiCorp)
- Installing hashicorp/null v3.3.2...
- Installed hashicorp/null v3.3.2 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
常用参数说明
-upgrade忽略锁文件,升级到允许的最新 provider 版本
-reconfigure丢弃已有 backend 配置缓存,重新初始化后端
-migrate-state后端迁移时把旧状态复制到新后端
-backend-config=KEY=VALUE覆盖 backend 部分参数(如 -backend-config="path=/opt/data/terraform/demo/terraform.tfstate")

💡 说明:init 是幂等操作,配置未变化时重复执行不会重复下载;改动 backend/provider/module source 后必须重跑,否则其他命令会提示重新初始化。

4.2 terraform validate(校验配置)

只做语法与内部一致性校验,不访问远端,不产生变更。

terraform validate

执行结果:

Success! The configuration is valid.

💡 说明:校验失败时会列出错误位置(文件与行号),如 Error: Invalid resource type。适合在 CI 中作为门禁步骤。

4.3 terraform plan(预览变更)

对比「配置期望状态」与「当前状态」,输出将要执行的动作清单,不产生任何真实变更。

terraform plan

执行结果(节选):

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # local_file.app_conf will be created
  + resource "local_file" "app_conf" {
      + content              = <<-EOT
            mode = production
            port = 8080
        EOT
      + filename             = "/opt/data/terraform/app.conf"
      + id                   = (known after apply)
    }

  # null_resource.setup_script will be created
  + resource "null_resource" "setup_script" {
      + id = (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.
常用参数说明
-out=文件把计划保存为二进制文件,供 apply 精确执行
-var 'k=v'覆盖变量值(可多次使用)
-var-file=文件从 tfvars 文件加载变量
-target=资源地址只计划指定资源(如 -target=local_file.app_conf)
-destroy生成销毁计划(等价于 destroy 的预览)

💡 说明:动作符号含义:+ create(新增)、-(删除)、~(更新)、-/+(替换:先删后建)、+/-(先建后删)。Plan: N to add, N to change, N to destroy 是变更汇总。

4.4 terraform apply(执行变更)

执行计划,创建/更新/删除资源。生产建议配合 plan -out 保存的计划执行,保证执行内容与审批内容一致。

terraform apply -auto-approve

执行结果(节选):

local_file.app_conf: Creating...
local_file.app_conf: Creation complete after 0s [id=a7391f05d0a6b7aba73c4696e2db3f5fd97eae55]
null_resource.setup_script: Provisioning with 'local-exec'...
null_resource.setup_script: Creation complete after 0s [id=38845130277906940]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Outputs:

conf_path = "/opt/data/terraform/app.conf"
常用参数说明
-auto-approve跳过交互式确认(脚本/CI 使用)
-var / -var-file覆盖变量(与 plan 一致)
-target=资源地址只执行指定资源(谨慎使用,易产生部分状态)
-replace=资源地址强制替换重建指定资源
-parallelism=N并发执行资源数(默认 10)

⚠️ 注意:不带 -auto-approve 时,apply 会先展示计划并等待输入 yes 确认。生产环境务必先 plan -out 审批,再 apply 计划文件。

4.5 terraform destroy(销毁资源)

按状态文件反向删除全部资源并清空状态。

terraform destroy -auto-approve

执行结果(节选):

local_file.app_conf: Refreshing state... [id=a7391f05d0a6b7aba73c4696e2db3f5fd97eae55]
null_resource.setup_script: Refreshing state... [id=38845130277906940]

Plan: 0 to add, 0 to change, 2 to destroy.

null_resource.setup_script: Destruction complete after 0s
local_file.app_conf: Destruction complete after 0s

Destroy complete! Resources: 2 destroyed.

⚠️ 注意:destroy 会删除远端真实资源,不可逆。支持 -target 定向删除;配置了 lifecycle.prevent_destroy 的资源会被阻断并报错(见《Terraform 配置参数详解》第十节)。

五、状态与查询命令

5.1 terraform show(展示状态/计划)

展示当前状态(所有资源)或保存的计划文件内容。

terraform show

执行结果(节选):

# local_file.app_conf:
resource "local_file" "app_conf" {
    content              = <<-EOT
        mode = production
        port = 8080
    EOT
    content_base64sha256 = "7fwCvONGUZVjLFrG6usuujh1RBnv/E1OtLlAqY1YW2I="
    content_md5          = "d2de931a445336485ee225f5fb4e2246"
    content_sha1         = "a7391f05d0a6b7aba73c4696e2db3f5fd97eae55"
    directory_permission = "0777"
    file_permission      = "0777"
    filename             = "/opt/data/terraform/app.conf"
    id                   = "a7391f05d0a6b7aba73c4696e2db3f5fd97eae55"
}

# null_resource.setup_script:
resource "null_resource" "setup_script" {
    id = "38845130277906940"
}
常用参数说明
-json输出 JSON 格式(脚本解析用)
-no-color关闭彩色输出
计划文件传参时展示该计划文件(如 terraform show plan.tfplan)

5.2 terraform state(状态管理)

状态文件管理子命令集,terraform state -help 可见 list/show/mv/rm/pull/push 等子命令。

state list(列出全部资源地址):

terraform state list

执行结果:

local_file.app_conf
local_file.cluster_config[0]
local_file.cluster_config[1]
local_file.cluster_config[2]
local_file.component_config["api"]
local_file.component_config["web"]
local_file.component_config["worker"]
local_file.fmt_demo
local_file.gateway_config
local_file.protected_conf
null_resource.setup_script
random_id.cluster_token
random_pet.svc_name

state show(查看单个资源):

terraform state show local_file.app_conf

执行结果(节选):

# local_file.app_conf:
resource "local_file" "app_conf" {
    content              = <<-EOT
        mode = production
        port = 8080
    EOT
    filename             = "/opt/data/terraform/app.conf"
    id                   = "a7391f05d0a6b7aba73c4696e2db3f5fd97eae55"
}

state mv(状态内移动/重命名):

terraform state mv local_file.cluster_config[0] local_file.cluster_node0

执行结果:

Move "local_file.cluster_config[0]" to "local_file.cluster_node0"
Successfully moved 1 object(s).

state rm(从状态移除,不删除真实资源):

terraform state rm random_pet.svc_name

执行结果:

Removed random_pet.svc_name
Successfully removed 1 resource instance(s).

💡 说明:state rm 只摘除状态记录,不会删除真实资源;配合 import 可实现"状态搬迁"。mv 用于资源重命名/跨模块迁移时保持状态不丢。

5.3 terraform output(查看输出值)

展示根配置声明的 output 值。

terraform output
terraform output -json

执行结果:

conf_content = <<EOT
mode = production
port = 8080

EOT
conf_path = "/opt/data/terraform/app.conf"
{
  "conf_content": {
    "sensitive": false,
    "type": "string",
    "value": "mode = production\nport = 7070\n"
  },
  "conf_path": {
    "sensitive": false,
    "type": "string",
    "value": "/opt/data/terraform/app.conf"
  }
}
常用参数说明
-jsonJSON 输出(含 type/value,供脚本消费)
-raw只输出值本身(单值 output 时)
输出名只查看指定输出(如 terraform output conf_path)

💡 说明:-json 输出的 value 字段可直接被 Ansible/脚本读取;sensitive: true 的输出值为 (sensitive value)。

六、资源与依赖命令

6.1 terraform import(导入已存在资源)

把已存在但不在状态中的真实资源纳入 Terraform 管理。语法:terraform import <资源地址> <资源ID>,ID 格式取决于 provider。

实测一:导入 random_id(hex 作为 ID,成功):

terraform import random_id.cluster_token f19a3536

执行结果:

random_id.cluster_token: Importing from ID "f19a3536"...
random_id.cluster_token: Import prepared!
  Prepared random_id for import
random_id.cluster_token: Refreshing state... [id=f19a3536]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state. Use "terraform plan" to see what has changed.

实测二:不支持导入的资源(报错示例):

terraform import local_file.app_conf /opt/data/terraform/app.conf

执行结果:

╷
│ Error: Resource Import Not Implemented
│
│ This resource does not support import. Please contact the provider
│ developer for additional information.
╵

💡 说明:并非所有资源都支持 import(local_file 就不支持)。导入前先查 provider 文档确认;导入后执行 terraform plan 检查是否与配置一致,再做 apply。

6.2 terraform providers(查看 provider 依赖)

terraform providers

执行结果:

Providers required by configuration:
.
├── provider[registry.terraform.io/hashicorp/local]
├── provider[registry.terraform.io/hashicorp/null]
└── provider[registry.terraform.io/hashicorp/random]

Providers required by state:

    provider[registry.terraform.io/hashicorp/null]

    provider[registry.terraform.io/hashicorp/local]

💡 说明:上半部分展示配置声明的 provider 树(含模块递归);下半部分展示状态中记录的 provider,两者不一致时提示重新 init。

6.3 terraform graph(输出依赖图)

输出 Graphviz DOT 格式的依赖图:

terraform graph

执行结果(节选):

digraph G {
  rankdir = "RL";
  node [shape = rect, fontname = "sans-serif"];
  "local_file.app_conf" [label="local_file.app_conf"];
  "local_file.fmt_demo" [label="local_file.fmt_demo"];
  "null_resource.setup_script" [label="null_resource.setup_script"];
  "random_pet.svc_name" [label="random_pet.svc_name"];
}

💡 说明:输出可管道给 Graphviz 渲染依赖图:terraform graph | dot -Tpng > graph.png(需安装 graphviz)。用于理解资源执行顺序与依赖关系。

6.4 terraform get(安装模块)

terraform get -help

执行结果:

Usage: terraform [global options] get [options]

  Downloads and installs modules needed for the configuration in the
  current working directory.

  This recursively downloads all modules needed, such as modules
  imported by modules imported by the root and so on. If a module is
  already downloaded, it will not be redownloaded or checked for updates
  unless the -update flag is specified.

  Module installation also happens automatically by default as part of
  the "terraform init" command, so you should rarely need to run this
  command separately.

💡 说明:get 只负责模块下载,通常无需单独执行——terraform init 已包含此步骤;-update 可强制刷新已缓存的模块。

七、工作区命令

7.1 terraform workspace(工作区管理)

terraform workspace list        # 查看工作区列表(* 标记当前)
terraform workspace new dev     # 新建并切换
terraform workspace show        # 显示当前工作区
terraform workspace select default  # 切换工作区
terraform workspace delete dev  # 删除工作区(不能删除当前/非空?仅可删非当前)

执行结果(依次):

* default

Created and switched to workspace "dev"!

You're now on a new, empty workspace. Workspaces isolate their state,
so if you run "terraform plan" Terraform will not see any existing state
for this configuration.

dev

Switched to workspace "default".

Deleted workspace "dev"!

💡 说明:工作区隔离的是状态而非配置;典型用法是 default(生产)+ 按需 dev/staging。删除工作区会连同其状态一起删除,管理着真实资源的工作区请先 destroy(详见《Terraform 工作区与项目初始化指南》第四节)。

八、表达式与格式命令

8.1 terraform console(表达式求值)

在配置上下文内交互式求值 HCL 表达式:

echo 'var.app_port + 1' | terraform console
echo 'upper("terraform demo")' | terraform console
echo 'local.conf_content' | terraform console

执行结果:

8081
"TERRAFORM DEMO"
<<EOT
mode = production
port = 8080

EOT

💡 说明:不接 stdin 时进入交互提示符(可连续输入表达式,exit 退出)。适合验证变量、函数与表达式语法。

8.2 terraform fmt(格式化配置)

按标准风格重排 .tf 文件(缩进、对齐、换行):

terraform fmt -diff

执行结果:

fmt_demo.tf
--- old/fmt_demo.tf
+++ new/fmt_demo.tf
@@ -1,4 +1,4 @@
 resource "local_file" "fmt_demo" {
-filename="/opt/data/terraform/fmt.txt"
-content="fmt test"
+  filename = "/opt/data/terraform/fmt.txt"
+  content  = "fmt test"
 }
terraform fmt -check   # 只检查是否已格式化(CI 门禁用)
echo "exit=$?"

执行结果:

exit=0
常用参数说明
-check只检查不修改,未格式化时返回非 0(CI 用)
-diff展示修改差异
-recursive递归处理子目录(含 modules/)
-write=false只显示结果不写文件

💡 说明:fmt 输出「被修改的文件列表」;全部已格式化时无输出(-check 返回 0)。

九、版本与全局选项

9.1 terraform version

terraform version

执行结果:

Terraform v1.16.5
on linux_amd64

💡 说明:-version 是 version 子命令的别名(terraform -version 等价)。required_version 约束(如 >= 1.5)不匹配时会在此提示。

9.2 全局选项

terraform -help 中的全局选项(须放在子命令之前):

选项说明
-chdir=DIR先切换工作目录再执行子命令(如 terraform -chdir=/opt/data/terraform/demo plan)
-help查看帮助或某子命令帮助
-version版本号别名

十、注意事项

  • 命令必须在初始化后的目录执行:未 init 就 plan/apply 会提示 Error: Missing required provider plugin;backend 变更后必须重新 init。
  • apply 前必须看 plan:生产环境用 plan -out 保存计划并审批,避免 -auto-approve 直改生产。
  • state rm 与 destroy 的区别:rm 只摘状态(资源仍在),destroy 真删资源;误用 rm 可用 import 找回(见 6.1)。
  • -target 慎用:定向执行容易造成部分应用的状态与配置不一致,长期留缺口。
  • 并发安全:团队共享后端时靠 s3 状态锁保证并发;本地 local 后端无锁,多机操作同一目录会互相覆盖。
  • 输出与脚本:脚本化解析统一用 -json(show/output),不要解析彩色人类可读输出。

十一、常见问题(FAQ)

11.1 提示 Terraform has not been initialized

原因: 当前目录从未执行 terraform init,或 backend 配置已变更。

解决: 执行 terraform init 后重试。

11.2 apply 卡在交互确认无法执行

原因: 未加 -auto-approve,等待输入 yes。

解决: 交互环境输入 yes 回车;脚本环境加 -auto-approve(配合 plan -out 审批模式)。

11.3 计划中资源大量显示「替换重建」而非更新

原因: 属性变更触发 ForceNew(不可变属性),或资源处于 tainted 状态。

解决: 查看变更属性是否确实需要重建;tainted 资源可用 terraform apply -replace=<地址> 强制重建一次。

11.4 terraform state rm 误删记录后如何恢复

原因: 状态记录被移除,但真实资源还在。

解决: 用 terraform import <资源地址> <资源ID> 重新导入(前提:该资源类型支持 import,见 6.1;不支持时需手工重写配置并对齐)。

11.5 多工作区之间资源串扰

原因: 记错了当前工作区,在错误 workspace 上 apply。

解决: 执行前 terraform workspace show 确认;在 CI 流水线中用 workspace select 显式指定。

11.6 terraform plan 报 Provider ... is not available

原因: 锁文件/插件缓存与配置要求的 provider 版本不一致。

解决: terraform init -upgrade 重新解析并锁定 provider 版本。

十二、参考链接


本文档由 www.quzuo.net 平台开发

Terraform 常用 CLI 命令与工具详解 - Quzuo