80

I am using Ansible to deploy my project and I trying to check if an specified package is installed, but I have a problem with it task, here is the task:

- name: Check if python-apt is installed
  command: dpkg -l | grep python-apt
  register: python_apt_installed
  ignore_errors: True

And here is the problem:

$ ansible-playbook -i hosts idempotent.yml

PLAY [lxc-host] *************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [10.0.3.240]

TASK: [idempotent | Check if python-apt is installed] ************************* 
failed: [10.0.3.240] => {"changed": true, "cmd": ["dpkg", "-l", "|", "grep", "python-apt"], "delta": "0:00:00.015524", "end": "2014-07-10 14:41:35.207971", "rc": 2, "start": "2014-07-10 14:41:35.192447"}
stderr: dpkg-query: error: package name in specifier '|' is illegal: must start with an alphanumeric character
...ignoring

PLAY RECAP ******************************************************************** 
10.0.3.240                 : ok=2    changed=1    unreachable=0    failed=0 

Why is illegal this character '|' .

Robert
  • 10,403
  • 14
  • 67
  • 117
  • Btw, according to https://github.com/ansible/ansible/pull/4617 `python-apt` should be automatically installed when you use `apt` module, so you shouldn't need to manually bootstrap it. – Mxx Jul 11 '14 at 04:24
  • use `shell` module if you want to use `pipe` – deepdive Feb 23 '18 at 02:05

2 Answers2

163

From the doc:

command - Executes a command on a remote node

The command module takes the command name followed by a list of space-delimited arguments. The given command will be executed on all selected nodes. It will not be processed through the shell, so variables like $HOME and operations like "<", ">", "|", and "&" will not work (use the shell module if you need these features).

shell - Executes a commands in nodes

The shell module takes the command name followed by a list of space-delimited arguments. It is almost exactly like the command module but runs the command through a shell (/bin/sh) on the remote node.

Therefore you have to use shell: dpkg -l | grep python-apt.

Amos Baker
  • 769
  • 6
  • 13
Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125
  • 4
    My mistake was to use command rather than shell. I also have to ignore the error the first time and then when the python-apt package is installed, the check task doesn't fail. Thank you. – Robert Jul 11 '14 at 13:28
41

read about the command module in the Ansible documentation:

It will not be processed through the shell, so .. operations like "<", ">", "|", and "&" will not work

As it recommends, use the shell module:

- name: Check if python-apt is installed
  shell: dpkg -l | grep python-apt
  register: python_apt_installed
  ignore_errors: True

For what it's worth, you can check/confirm the installation in a debian environment using the apt command:

- name: ensure python-apt is installed
  apt: name=python-apt state=present
tedder42
  • 23,519
  • 13
  • 86
  • 102
  • If I want to use the apt module, is necessary installed first. I do the confirmation only the first time and later I use apt module to install packages. Thank you for your answer. – Robert Jul 11 '14 at 13:32
  • I think this is a better aproach, using modules that interact directly with packages. – diablinux Jul 11 '14 at 13:53
  • @rob3 wait, what confirmation? you can certainly use `apt` to install modules and verify they are installed. Both debian and ubuntu have apt already, and `python-apt` doesn't have any manual installation steps. – tedder42 Jul 11 '14 at 16:46
  • 2
    yes, but from documentation the first note says: **Requires python-apt**. Then the first task is install python-apt and then I can use it for install others packages. – Robert Jul 11 '14 at 18:34
  • @Rob3 it seems strange, but you can use apt to install python-apt. – tedder42 Jul 11 '14 at 18:53
  • Should be the accepted answer. More straightforward than @Sylvain's. – Charlie Dalsass Apr 11 '18 at 14:14