如果未安装包,如何使Ansible执行shell脚本

Kim*_*ble 58 ansible

如果没有安装(rpm)软件包,如何让Ansible执行shell脚本?是否有可能利用yum模块?

Bru*_*e P 69

在这种情况下,我不认为yum模块会有所帮助.它目前有3个州:缺席,现在和最新.由于听起来您不想实际安装或删除软件包(至少在此时),因此您需要在两个手动步骤中执行此操作.第一个任务将检查包是否存在,然后第二个任务将根据第一个命令的输出调用命令.

如果使用"rpm -q"来检查包是否存在,那么对于存在的包,输出将如下所示:

# rpm -q httpd
httpd-2.2.15-15.el6.centos.1.x86_64
Run Code Online (Sandbox Code Playgroud)

如果包不存在,请像这样:

# rpm -q httpdfoo
package httpdfoo is not installed
Run Code Online (Sandbox Code Playgroud)

所以你的ansible任务看起来像这样:

- name: Check if foo.rpm is installed
  command: rpm -q foo.rpm
  register: rpm_check

- name: Execute script if foo.rpm is not installed
  command: somescript
  when: rpm_check.stdout.find('is not installed') != -1
Run Code Online (Sandbox Code Playgroud)

如果包存在,rpm命令也将退出0,如果找不到包,则退出1,所以另一种可能性是使用:

when: rpm_check.rc == 1
Run Code Online (Sandbox Code Playgroud)

  • 该命令的问题是,如果`rpm -q`以0退出(未找到包),则剧本将失败.为了防止附加:`ignore_errors:True`到任务,以便在后续任务中使用输出来安装rpm. (13认同)
  • 另外,你可能想添加`changed_when:no`来强制`command`模块不要说某些东西已经改变了. (6认同)
  • 另外,为了避免在找不到软件包时出现故障消息,可以设置`failed_when:rpm_check.rc> 1`. (3认同)
  • 使用`ignore_errors:yes`它仍然算作错误,所以`failed_when:no`似乎是一个更好的选择. (3认同)

Kev*_*ody 29

基于上面的Bruce P答案,apt/deb文件的类似方法是

- name: Check if foo is installed
  command: dpkg-query -l foo
  register: deb_check

- name: Execute script if foo is not installed
  command: somescript
  when: deb_check.stdout.find('no packages found') != -1
Run Code Online (Sandbox Code Playgroud)

  • 我需要添加`failed_when:False` (2认同)
  • @Erathiel我认为如果找到给定的包,这个剧本解决的是运行"某些"任务.所以不一定要安装一个丢失的软件包,它可能是其他东西.'only_upgrade`选项用于确保安装或更新包,就像`state`一样. (2认同)

arm*_*rma 24

与此相关.

将所有内容放在一起,完成Debian(Ubuntu)的playbook,只有在已经安装的情况下才更新包:

---
- name: Update package only if already installed (Debian)
  hosts: all
  sudo: yes
  tasks:
    - name: Check if Package is installed
      shell: dpkg-query -W -f='${Status}' {{ package }} | grep 'install ok installed'
      register: is_installed
      failed_when: no
      changed_when: no

    - name: Update Package only if installed
      apt:
        name: {{ package }}
        state: latest
        update_cache: yes
      when: is_installed.rc == 0
Run Code Online (Sandbox Code Playgroud)

可悲的是,Ansible仍然没有内置支持进行简单的软件包更新,请参阅例如:https://github.com/ansible/ansible/issues/10856


ree*_*gnz 20

如果软件包可以通过系统软件包管理器(yum,apt等)本身安装,那么您可以使用ansible的检查模式标志来注册安装状态,而无需实际安装软件包.

- name: check if package is installed
  package:
    name: mypackage
    state: present
  check_mode: true
  register: mypackage_check

- name: run script if package installed
  shell: myscript.sh
  when: not mypackage_check.changed 
Run Code Online (Sandbox Code Playgroud)

  • 通过使用`package`模块而不是特定的`yum`模块,这将使它成为最好的答案,因为它将比RHEL或Debian系列的Linux发行版更多.做得好! (5认同)

sdu*_*hil 16

从Ansible 2.5开始,您可以使用package_facts模块:

- name: Gather package facts
  package_facts:
    manager: auto

- name: Debug if package is present
  debug:
    msg: 'yes, mypackage is present'
  when: '"mypackage" in ansible_facts.packages'

- name: Debug if package is absent
  debug:
    msg: 'no, mypackage is absent'
  when: '"mypackage" not in ansible_facts.packages'
Run Code Online (Sandbox Code Playgroud)

注意:您需要在目标上安装apt/rpm的python绑定,例如python-aptDebian.


cor*_*ngi 9

您不应该使用,dpkg -l package因为它不知道您的包已被删除或仍然安装.
相反,它可能更好用dpkg -s package.

要检查软件包是否已安装:
- shell: dpkg -s package | grep 'install ok installed'
或者如果您不介意保留包或其他状态:
- shell: dpkg -s package | grep 'installed'
安装时返回0,否则返回1.

(因为我们使用管道,所以使用shell很重要|)