如果未安装包,如何使Ansible执行shell脚本
如果没有安装(rpm)包,如何使Ansible执行shell脚本?是否有可能利用yum模块?我认为在这种情况下,yum模块不会有帮助。它目前有3种状态:缺席、当前和最新。由于听起来您不想实际安装或删除软件包(至少在这一点上),因此您需要通过两个手动步骤来完成此操作。第一个任务将检查包是否存在,然后第二个任务将根据第一个命令的输出调用一个命令 如果使用“rpm-q”检查包是否存在,那么对于存在的包,输出将如下所示:如果未安装包,如何使Ansible执行shell脚本,ansible,Ansible,如果没有安装(rpm)包,如何使Ansible执行shell脚本?是否有可能利用yum模块?我认为在这种情况下,yum模块不会有帮助。它目前有3种状态:缺席、当前和最新。由于听起来您不想实际安装或删除软件包(至少在这一点上),因此您需要通过两个手动步骤来完成此操作。第一个任务将检查包是否存在,然后第二个任务将根据第一个命令的输出调用一个命令 如果使用“rpm-q”检查包是否存在,那么对于存在的包,输出将如下所示: # rpm -q httpd httpd-2.2.15-15.el6.centos
# rpm -q httpd
httpd-2.2.15-15.el6.centos.1.x86_64
如果包不存在,则如下所示:
# rpm -q httpdfoo
package httpdfoo is not installed
因此,您的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
如果包存在,rpm命令也将以0退出,如果找不到包,rpm命令将以1退出,因此另一种可能性是使用:
when: rpm_check.rc == 1
基于上面的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
与此相关
将所有内容放在一起,完成Debian(Ubuntu)的playbook,该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
遗憾的是,Ansible仍然没有内置支持进行简单的软件包更新,请参见示例:您不应该使用
dpkg-l软件包,因为它不知道您的软件包是否已被删除或仍在安装。
相反,最好使用dpkg-s包
要检查软件包是否已安装:
-shell:dpkg-s软件包| grep“安装正常已安装”
或者,如果您不介意包裹处于搁置状态或其他状态:
-shell:dpkg-s包| grep“已安装”
安装时返回0,否则返回1
(使用shell非常重要,因为我们使用的是管道|
)如果包可以通过系统包管理器(yum、apt等)本身安装,则可以使用ansible的check mode标志注册安装状态,而无需实际安装包
- 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
我发现使用shell或命令模块不是“ansiblic”
我更喜欢使用yum模块和filter来检查包是否已经安装。例如,httpd包:
- yum:
list: httpd
register: apache_service
- assert:
that:
- "'installed' in apache_service|json_query('results[*].yumstate')"
msg: 'httpd is not installed'
由于Ansible 2.5,您可以使用以下模块:
注意:您需要在目标系统上安装apt/rpm的python绑定,例如Debian的python apt
。该命令的问题是,如果rpm-q
以0退出(未找到包),playbook将失败。为防止出现这种情况,请将:ignore\u errors:True
附加到任务中,以便在后续任务中使用输出来安装rpm。此外,当:no
时,您可能需要添加changed\u,以强制命令
模块不要说某些内容已更改。此外,为了避免在找不到包时出现失败消息,您可以将failed\u设置为:rpm\u check.rc>1
。当:rpm\u check.rc=1
时,它不是failed\u吗。我没有看到大于1的数字。对于ignore\u错误:yes
它仍然算作一个错误,因此failed\u when:no
似乎是一个更好的选择。我需要添加failed\u when:False
我想指出,从Ansible 2.1开始,apt模块有一个名为only\u upgrade
的选项,这正是为此目的而设计的。文档中描述了这个开关:“只有在已经安装了软件包的情况下才安装/升级软件包”。@Erathiel我认为这个剧本解决的问题是,如果找到给定的软件包,就运行“特定”任务。因此,不一定是安装丢失的软件包,它可能是其他东西。only\u upgrade
选项用于确保安装或更新软件包,就像state
@Erathiel一样,OP需要进行if/then测试。他/她没有声明他们想实际安装任何东西。干杯。如果您希望它是幂等的,那么在:False时添加changed\u。例如,使用shell:dpkg--status{{package}}| grep'install ok installed'
比使用命令:dpkg query-l{package}
更健壮。通过使用package
模块而不是特定的yum
one,这将使它成为最好的解决方案,因为它将在不止RHEL或Debian系列的Linux发行版上工作。做得好!这对我不起作用。如果未安装软件包,则会显示Ansible错误。我不得不在“检查软件包是否安装”部分添加“忽略错误:是”。什么版本?从RPM文件安装时,2.3.2.0会出错。它在2.4.0.0中得到了修复。当软件包未安装时,任务检查软件包是否已安装
报告故障,事实上,当它成功运行并注册了变量mypackage\u check
时,我不得不将其更改为shell:dpkg-s package | grep-c“install ok installed”
在Debian上,grep没有返回0或1。使用-c
选项,它返回找到的行数。
- 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'