通过Terraform local-exec执行Python脚本的问题及配置问询
版本信息
- VS Code: v1.74.3
- Python: v3.9.1
- Terraform: v1.3.6
环境设置
文件夹结构如下:
. ├── main.tf └── scripts └── my_script.py
main.tf配置:
locals { python = (substr(pathexpand("~"), 0, 1) == "/") ? "python3" : "python.exe" } resource "null_resource" "custom_objects" { for_each = local.custom_objects triggers = { name = each.key } provisioner "local-exec" { command = <<-EOT python3 -m my_script '{"key_1": "value_1"}' EOT interpreter = [ local.python ] working_dir = "${path.module}/scripts" } }
./scripts/my_script.py代码:
if __name__ == '__main__': print('my_script executed.')
问题描述
执行terraform plan或terraform apply时出现如下错误:
Error running command 'python3 -m my_script '{"key_1": "value_1"}'
│ ': exit status 2. Output: /home_path/.pyenv/versions/3.9.1/bin/python3: can't open file '/path_to_repo/scripts/python3 -m my_script '{"key_1": "value_1"}'
│ ': [Errno 2] No such file or directory
技术问询与解答
1. 为何错误信息显示了相关路径,但local-exec仍无法找到脚本?
核心问题是local-exec的interpreter和command配置逻辑冲突。当指定interpreter时,Terraform会把整个command的内容当作单个参数传递给解释器。这里你指定了Python作为解释器,它就会把python3 -m my_script '{"key_1": "value_1"}'当成一个完整的文件名去查找,自然找不到——这根本不是一个文件,而是命令参数的组合。
2. 如何配置才能通过local-exec以模块形式执行Python脚本?
有两种可靠的配置方式:
方式一:移除interpreter,直接在command中使用完整命令
既然已经通过local.python区分了不同系统的Python命令,直接把它嵌入到command里即可:
provisioner "local-exec" { command = <<-EOT ${local.python} -m my_script '{"key_1": "value_1"}' EOT working_dir = "${path.module}/scripts" }
这种方式下,系统会直接执行完整命令,Python能正确识别-m my_script为模块运行指令。
方式二:拆分参数给interpreter(需注意引号转义)
如果一定要保留interpreter,需要把命令拆成解释器的参数列表,而非将整个命令作为单个参数传递:
provisioner "local-exec" { command = <<-EOT -m my_script '{"key_1": "value_1"}' EOT interpreter = [local.python] working_dir = "${path.module}/scripts" }
这种方式要注意引号的转义问题,相对来说第一种方式更直观不易出错。
另外,working_dir设置为scripts后,Python会自动将当前目录加入模块搜索路径,所以my_script能被识别为可运行模块,无需额外配置路径。
内容的提问来源于stack exchange,提问作者GreenyMcDuff

