如果是 CLI 与通过状态文件执行 salt cmd.run 会有不同的行为。有什么不同?

execution of salt cmd.run has different behaviors if it's CLI vs through state files. what's the difference?

我正在尝试使用 IMDSv2(AWS 实例元数据)令牌的值设置变量 TOKEN 以获取实例 IP 地址。

通过 salt CLI 执行一组命令会产生预期的结果:下面是命令:

salt-ssh 'name.of.host' cmd.run cmd='TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -s -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") && curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/public-ipv4'

但是,我正在尝试通过这样的计算表达式执行相同的命令:

{{ salt["cmd.run"](cmd='TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -s -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") && curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/public-ipv4')}}

并出现以下错误:

 FileNotFoundError: [Errno 2] No such file or directory: 'TOKEN=$(curl': 'TOKEN=$(curl'

我的想法是 salt 通过 CLI 评估命令表达式的方式不同于 jinja esque 评估。我也明白空格是 shell 盐表达式中的一个因素。我尝试了将转义字符放在等号、美元和括号后面的不同组合,但没有这样的运气。我仍然认为它与特殊字符有关,但无法确定是什么。

有什么想法吗?非常感谢。

根据 documentationcmd.run 默认不处理通过 Shell 的命令。引用上面的“警告” link:

This function does not process commands through a shell unless the python_shell flag is set to True. This means that any shell-specific functionality such as 'echo' or the use of pipes, redirection or &&, should either be migrated to cmd.shell or have the python_shell=True flag set here.

所以有两种选择:

  • 不要使用 cmd.run,而是使用 cmd.shell。例如:

    {{ salt.cmd.shell('TOKEN=$(curl -X PUT ...)') }}
    
  • 或将python_shell=True添加到cmd.run。例如:

     {{ salt.cmd.run('TOKEN=$(curl -X PUT ...)', python_shell=True) }}