ansible playbook命令出现问题?

时间:2019-07-11 12:20:51

标签: shell docker ansible hyperledger-fabric

我正在尝试从本机在其他计算机上的docker上执行命令。当我执行此命令时:

- name: Add header
      command: docker exec cli bash -l -c "echo '{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":'$(cat jaguar_update.json)'}}}' | jq . > jaguar_update_in_envelope.json"

通过一本有趣的剧本,出现以下错误。

fatal:[  
   command-task
]:FAILED! =>{  
   "changed":true,
   "cmd":[  ],
   "delta":"0:00:00.131115",
   "end":"2019-07-11 17:32:44.651504",
   "msg":"non-zero return code",
   "rc":4,
   "start":"2019-07-11 17:32:44.520389",
   "stderr":"mesg: ttyname   
failed: Inappropriate ioctl for device\nparse error: Invalid numeric   
literal at line 1, column 9",
   "stderr_lines":[  
      "mesg: ttyname failed: 
Inappropriate ioctl for device",
      "parse error: Invalid numeric literal 
at line 1, column 9"
   ],
   "stdout":"",
   "stdout_lines":[  

   ]
}

但是,如果我在docker容器中手动执行命令,它可以正常工作,而且我没有任何问题。

编辑: 如建议的那样,我尝试使用shell模块

shell: docker exec cli -it bash -l -c "echo '{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":'$(cat jaguar_update.json)'}}}' | jq . > jaguar_update_in_envelope.json"

但是我得到以下错误

  致命:[命令任务]:失败! => {“ changed”:true,“ cmd”:“ docker   exec cli -it bash -l -c echo   '{\“ payload \”:{\“ header \”:{\“ channel_header \”:{\“ channel_id \”:\“ gll \”,   \“ type \”:2}},\“ data \”:{\“ config_update \”:'$(cat   jaguar_update.json)'}}}'| jq。 > jaguar_update_in_envelope.json”,   “ delta”:“ 0:00:00.110341”,“ end”:“ 2019-07-12 10:21:45.204049”,“ msg”:   “非零返回码”,“ rc”:4,“开始”:“ 2019-07-12   10:21:45.093708“,” stderr“:” cat:jaguar_update.json:没有此类文件或   目录\ nparse错误:第1行第4列的数字常量无效,   “ stderr_lines”:[“ cat:jaguar_update.json:没有这样的文件或目录”,   “解析错误:第1行第4列的无效数字文字”],“ stdout”:   “”,“ stdout_lines”:[]}

工作目录中存在的所有文件'jaguar_update.json'。我已经确认了工作目录。

如果我将其放在Shell脚本文件中,然后从ansible执行Shell脚本,上述命令将起作用。

3 个答案:

答案 0 :(得分:3)

正如每个人都提到的那样,这确实需要您使用shell而不是command。现在,您想简化此命令,以便它可以首先在bash中运行。使用printf

可以轻松完成
$ printf "%s%s%s" '{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":' $(<jaguar_update.json'}}}' | jq . > jaguar_update_in_envelope.json

$ cat jaguar_update_in_envelope.json
{
  "payload": {
    "header": {
      "channel_header": {
        "channel_id": "gll",
        "type": 2
      }
    },
    "data": {
      "config_update": {
        "name": "tarun"
      }
    }
  }
}

因此,现在我们的命令可以正常运行了。接下来是以bash -l -c格式移动它。因此,我们使用多行命令,而不是使用-c,它需要我们将整个命令作为一个参数传递,

$ bash -l <<EOF
printf "%s%s%s" '{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":' $(<jaguar_update.json) '}}}' | jq . > jaguar_update_in_envelope.json
EOF

但这失败并显示错误

{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":{bash: line 2: name:: command not found
bash: line 3: syntax error near unexpected token `}'
bash: line 3: `} '}}}' | jq . > jaguar_update_in_envelope.json'

这是因为EOF格式会将每行换行视为不同的命令。所以我们需要替换所有换行符

bash -l <<EOF
printf "%s%s%s" '{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":' $(sed -E 's|"|\\"|g' jaguar_update.json | tr -d '\n') '}}}' | jq . > jaguar_update_in_envelope.json
EOF

现在陷入困境

- name: a play that runs entirely on the ansible host
  hosts: 127.0.0.1
  connection: local
  tasks:
     - name: Solve the problem
       shell: |
           bash -l <<EOF
                printf "%s%s%s" '{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":' $(sed -E 's|"|\\"|g' jaguar_update.json | tr -d '\n') '}}}' | jq . > jaguar_update_in_envelope.json
           EOF

结果

$ ansible-playbook test.yml
PLAY [a play that runs entirely on the ansible host] *********************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************
ok: [127.0.0.1]

TASK [Solve the problem] *************************************************************************************************************************************************************
changed: [127.0.0.1]

PLAY RECAP ***************************************************************************************************************************************************************************
127.0.0.1                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

$ cat jaguar_update_in_envelope.json
{
  "payload": {
    "header": {
      "channel_header": {
        "channel_id": "gll",
        "type": 2
      }
    },
    "data": {
      "config_update": {
        "name": "tarun"
      }
    }
  }
}

答案 1 :(得分:1)

c.f。 docs-

  • 将不会通过外壳处理命令,因此$ HOME之类的变量和“ <”,“>”,“ |”,“;”之类的操作和“&”将不起作用。如果需要这些功能,请使用shell模块。

shell实际上是将脚本提交给sh命令解析器。

另一注-在<a href="/SM/AddSMHome/" title="Add New Student" class="rotateImage"> <img src="/icon/SM_add_student3.png" class="img- responsive img-circle img-thumbnail" style="max-width: 100px;max-height: 100px;" alt="Add New Student"></a>之前结束单引号,然后在$(cat jaguar_update.json)之后重新启动,但不要在其周围使用任何双引号。您的输出可能会解决该问题,但是如果有必要,我想引起注意。

答案 2 :(得分:0)

为避免任何复杂性,请尝试as in this question将命令包装在脚本中,然后调用该脚本(使用commandshell

- name: Add header
      raw: /path/to/script/docker-add-header.sh

/path/to/script/docker-add-header.sh中:

docker exec cli -it bash -l -c "echo '{"payload":{"header":{"channel_header":{"channel_id":"gll", "type":2}},"data":{"config_update":'$(cat jaguar_update.json)'}}}' | jq . > jaguar_update_in_envelope.json

尝试使脚本首先单独运行(无Ansible)。
请参阅(如果它不起作用,即使在任何Ansible调用之外也是如此)以转义嵌套的双引号:

docker exec cli -it bash -l -c "echo '{\"payload\":{\"header\":...