使用 ansible 在远程服务器上运行长 shell 命令

使用 ansible 在远程服务器上运行长 shell 命令

我有一个任务,我想在远程服务器的 shell 上运行以下命令,但是每当我运行我的剧本时,它总是给我异常:

  - name: copy files
    shell: "machines=(machineA machineB machineC); for machine in $(shuf -e ${machines[@]}); do ssh -o StrictHostKeyChecking=no david@$machine 'ls -1 /process/snap/{{ folder }}/*' | parallel -j{{ threads }} 'scp -o StrictHostKeyChecking=no david@${machine}:{} /data/files/'; [ $? -eq 0 ] && break; done"

以下是错误:我不明白我在这里做错了什么?

"stderr": "/bin/sh: 1: Syntax error: \"(\" unexpected", "stderr_lines": ["/bin/sh: 1: Syntax error: \"(\" unexpected"], "stdout": "", "stdout_lines": []}

我可以在任何远程服务器的 shell 上直接运行此命令,但在通过 ansible 运行时遇到问题。

这是我将其转换为一行并在 shell 模块中使用的脚本:

machines=(machineA machineB machineC)
for machine in $(shuf -e ${machines[@]}); do 
    ssh -o StrictHostKeyChecking=no david@$machine 'ls -1 /process/snap/{{ folder }}/*' | parallel -j{{ threads }} 'scp -o StrictHostKeyChecking=no david@${machine}:{} /data/files/'
   [ $? -eq 0 ] && break
done

更新:

我现在尝试这样做,但它给出了不同的异常。

  - name: copy files
    shell: |
      set -x
      machines=(machineA machineB machineC)
      for machine in $(shuf -e ${machines[@]}); do
          ssh -o StrictHostKeyChecking=no david@$machine 'ls -1 /process/snap/{{ folder }}/*' | parallel -j{{ parallelism }} 'scp -o StrictHostKeyChecking=no david@${machine}:{} /data/files/'
          [ $? -eq 0 ] && break
      done
    args:
      executable: /bin/bash

完整错误:(我已将其缩短)

致命:[some_machine]:失败! => {“changed”: true, “cmd”: “machines=(machineA machineB machineC)\n for machine in $(shuf -e ${machines[@]}); do\n ssh -o StrictHostKeyChecking=no david@$machine 'ls -1 /process/snap/20180422/*' | parallel -j10 'scp -o StrictHostKeyChecking=no david@${machine}:{} /data/files/'\n [ $? -eq 0 ] && break\n done", “delta”: “0:00:37.546329", “end”: “2018-04-29 23:27:44.003538", “msg”: “非零返回码", “rc”: 1, “start”: “2018-04-29 23:27:06.457209", “stderr”: “ssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知已知\r\nssh:无法解析主机名:未知的名称或服务\r\nssh:无法解析主机名:未知的名称或服务\r\nssh:无法解析主机名:未知的名称或服务\r\nssh:无法解析主机名:未知的名称或服务\r\nssh:无法解析主机名:未知的名称或服务\r\nssh:无法解析主机名:未知的名称或服务\r\nssh:无法解析主机名:未知的名称或服务\r\nssh:无法解析主机名:未知的名称或服务\r\nssh:无法解析主机名:未知的名称或服务\r\nssh:无法解析主机名:未知的名称或服务\r\nssh:无法解析主机名:未知的名称或服务\r\nssh:无法解析主机名:未知的名称或服务\r\nssh:无法解析主机名:未知的名称或服务未知\r\nssh: 无法解析主机名:名称或服务未知\r\nssh: 无法解析主机名:名称或服务未知\r\nssh: 无法解析主机名:名称或服务未知\r\nssh: 无法解析主机名:名称或服务未知\r\nssh: 无法解析主机名:名称或服务未知\r\nssh: 无法解析主机名:名称或服务未知\r\nssh: 无法解析主机名:名称或服务未知\r\nssh: 无法解析主机名:名称或服务未知\r\nssh: 无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知\r\nssh:无法解析主机名:名称或服务未知known\r\nssh:无法解析主机名:名称或服务未知”、“ssh:无法解析主机名:名称或服务未知”、“ssh:无法解析主机名:名称或服务未知”],“stdout”:“”,“stdout_lines”:[]}

我也尝试了这个基本方法,并且没有任何错误,所以我认为它有效?

  - name: copy files
    shell: |
      set -x
      machines=(machineA machineB machineC)
      for machine in $(shuf -e ${machines[@]}); do
          echo $machine
          [ $? -eq 0 ] && break
      done
    args:
      executable: /bin/bash

我认为我的 scp 语句可能存在问题?我不确定,只是猜测?

答案1

好吧,我无法说出您的问题到底是什么,但错误表明您的命令中存在语法错误。这几乎肯定与执行时转义或未正确翻译的内容有关。

我必须提出几件事。首先,使用 yaml 语法来包含包含行尾的文本块。

- name: Run Script
  shell: |
    machines=(machineA machineB machineC)
    for machine in $(shuf -e ${machines[@]}); do
        ssh -o StrictHostKeyChecking=no david@$machine 'ls -1 /process/snap/{{ folder }}/*' |
        parallel -j{{ threads }} 'scp -o StrictHostKeyChecking=no david@${machine}:{} /data/files/'
      [ $? -eq 0 ] && break
    done

我认为你的片段可能有一些巴什主义。您可能需要指定脚本通过以下方式执行狂欢代替/bin/sh

- name: Run command that requires bash
  shell: echo 'not a very good example.
  args:
    executable: /bin/bash

您可能还想添加一个set -x作为片段的第一行。shell 的更详细输出应该可以帮助您了解错误到底是什么。

当然,我也建议你尝试使用 Ansible 模块来执行此操作。我怀疑也许将同步模块与异步功能

答案2

这对我有用:

    - name: Generate new certificate
      shell: "keytool -genkey -keystore {{ keystore_key }} 
                -storepass {{ keystore_pass }} \
                -storetype {{ keystore_type }} \
                -alias {{ keystore_alias }} \
                -validity {{ keystore_validity }} \
                -keysize {{ keystore_keysize }} \
                -keyalg {{ keystore_keyalg }}"

答案3

既然您说您可以在任何远程服务器的 shell 上直接运行此命令,请尝试使用 Ansible 的脚本模块。

- name: Run a script with arguments   
  script: /some/local/script.sh --some-argument 1234

文档在这里:https://docs.ansible.com/ansible/latest/modules/script_module.html

干杯

相关内容