链接 https://galaxy.ansible.com 下载相应的roles,此网站是Ansible爱好者将平常使用较好的playbooks打包上传,其余人能够免费下载 到Ansible PlayBooks并当即投入使用。
ansible-galaxy 语法:php
ansible-galaxy [delete|import|info|init|install|list|login|remove|search|setup] [--help] [options] 列出已安装的galaxy #ansible-galaxy list geerlingguy.mysql - geerlingguy.mysql, 2.8.1 安装galaxy ansible-galaxy install geerlingguy.redis 删除galaxy ansible-galaxy remove geerlingguy.redis
进入网站后找到这时标记的地方mysql
把名字复制下来nginx
就能够在你的ansible主机上进行安装剧本了。git
#ansible-galaxy install geerlingguy.mysql - downloading role 'mysql', owned by geerlingguy - downloading role from https://github.com/geerlingguy/ansible-role-mysql/archive/2.8.1.tar.gz - extracting geerlingguy.mysql to /root/.ansible/roles/geerlingguy.mysql - geerlingguy.mysql (2.8.1) was installed successfully
安装的剧本默认是存放在家目录的隐藏文件中。
/root/.ansiblegithub
#tree -L 2 . └── geerlingguy.mysql ├── defaults ├── handlers ├── LICENSE ├── meta ├── README.md ├── tasks ├── templates ├── tests └── vars
固然,本机的galaxy命令也提供在线搜索剧本。web
#ansible-galaxy search --author geerlingguy Found 90 roles matching your search: Name Description ---- ----------- geerlingguy.raspberry-pi Configures a Raspberry Pi. geerlingguy.php-redis PhpRedis support for Linux geerlingguy.drupal-console Drupal Console geerlingguy.adminer Installs Adminer for Database management. geerlingguy.blackfire Blackfire installation for Linux geerlingguy.tomcat6 Tomcat 6 for RHEL/CentOS and Debian/Ubuntu. geerlingguy.php-pear PHP PEAR library installation.
功能:管理加密解密yml文件正则表达式
ansible-vault [create|decrypt|edit|encrypt|rekey|view] ansible-vault encrypt hello.yml 加密 ansible-vault decrypt hello.yml 解密 ansible-vault view hello.yml 查看加密问题 ansible-vault edit hello.yml 编辑加密文件 ansible-vault rekey hello.yml 修改口令 ansible-vault create new.yml 建立新文件
可交互执行命令,支持tab补全。redis
#ansible-console Vault password:默认是当前登陆帐号密码 root@all (5)[f:5]$ 列出全部的内置命令: ?或help 执行用户@当前操做的主机组(all) (当前组的主机数量5)[f:并发数5] 设置并发数: forks n root@all (5)[f:5]$ forks 10 切换组: cd 主机组 root@all (5)[f:10]$ cd db 列出当前组主机列表: list root@all (5)[f:10]$ list 6-web-1.hunk.tech 7-web-0.hunk.tech 7-web-2.hunk.tech 6-dns-1.hunk.tech 7-db-3.hunk.tech 执行一行指令 root@web (3)[f:10]$ setup filter=ansible_distribution_version
语法:sql
ansible-playbook <filename.yml> ... [options] 常见选项 --check 只检测可能会发生的改变,但不真正执行操做 --list-hosts 列出运行任务的主机 --list-tasks 列出此playbook中的全部任务 --list-tags 列出此playbook中的全部的tags --limit 主机列表 只针对主机列表中的主机执行 --step 一步一步执行脚本 --flush-cache 清除fact缓存 -C 文件名 执行前先检查语法。 -D 显示出执行先后的变化内容 -v 显示过程 -vv -vvv 更详细
--- - hosts: all remote_user: root tasks: - name: test yml command: /usr/bin/wall "hello world"
语法检查shell
真正执行
Playbook采用YAML语言编写
这里只涉及到playbook相关的语法,更多请参考官网http://www.yaml.org
语法很是严格,请仔细仔细再仔细。
在单一档案中,可用连续三个连字号(---)区分多个档案。另外,还有选择性的连续三个点号( ... )用来表示档案结尾 次行开始正常写Playbook的内容,通常建议写明该Playbook的功能 使用#号注释代码 缩进必须是统一的,不能空格和tab混用,通常缩进2个空格 缩进的级别也必须是一致的,一样的缩进表明一样的级别,程序判别配置的级别是经过缩进结合换行来实现的 YAML文件内容和Linux系统大小写判断方式保持一致,是区别大小写的,key/value的值均需大小写敏感 key/value的值能够写在同一行,也可换行写。同一行使用 , 逗号分隔 value但是个字符串,也但是另外一个列表 一个完整的代码块功能需最少元素需包括 name和task 一个name只能包括一个task 使用| 和 > 来分隔多行,实际上这只是一行。 include_newlines: | exactly as you see will appear these three lines of poetry ignore_newlines: > this is really a single line of text despite appearances Yaml中不容许在双引号中出现转义符号,因此都是以单引号来避免转义符错误 YAML文件扩展名一般为yml或yaml
其全部元素均使用"-"打头
- web - dns -空格web
一般由多个key与value构成
多行写法: name: hunk blog: "http://https://blog.51cto.com/191226139" name:空格hunk > 这个冒号后面必须是一个空格 同一行写法: 须要使用{ } {name: hunk, blog: "http://https://blog.51cto.com/191226139"} > 逗号后建议使用留一个空格 布尔值的表示法: yes/no true/false create_key: yes needs_agent: no knows_oop: True likes_emacs: TRUE uses_cvs: false
Ansible 使用 "{{ var }}" 来引用变量. 若是一个值以 "{"开头, YAML 将认为它是一个字典, 因此咱们必须引用它, 像这样:
foo: "{{ variable }}"
使用引号来包裹任何包含冒号:的value值, 像这样:
foo: "somebody said I should put a colon here: so I did"
hosts 行的内容是一个或多个组或主机的 patterns,以逗号为分隔符。一般是/etc/ansible/hosts定义的主机列表
remote_user 就是远程执行任务的帐户名:
--- - hosts: web,dns remote_user: root
任务集
tasks: - name: install httpd yum: name=httpd - name: start httpd service: name=httpd state=started - name: check http port shell: ss -ntl|grep 80 > /tmp/httpd.txt - name: fetch fetch: src=/tmp/httpd.txt dest=/app
执行过程
执行结果 #tree /app /app ├── 6-web-1.hunk.tech │ └── tmp │ └── httpd.txt ├── 7-web-0.hunk.tech │ └── tmp │ └── httpd.txt ├── 7-web-2.hunk.tech │ └── tmp │ └── httpd.txt #cat /app/6-web-1.hunk.tech/tmp/httpd.txt LISTEN 0 128 :::80 :::*
一个yml文件里能够设计多个playbook,不过呢,为了更清晰的管理,建议应该独立存放不一样任务需求,方便之后调用。
这里要注意双引号的状况 - name: change httpd.conf shell: "/bin/sed -i.bakr '/^Listen 80/cListen 8080' /etc/httpd/conf/httpd.conf"
由特定条件触发的操做,知足条件方才执行,不然不执行。
Handlers也是task列表,这些task与前述的tasks并无本质上的不一样,用于当关注的资源发生变化时,才会采起必定的操做
仍是拿上个例子的playbook修改下。
--- - hosts: ~^7.*web remote_user: root tasks: - name: install httpd yum: name=httpd - name: change httpd.conf copy: src=/app/httpd.conf dest=/etc/httpd/conf/ backup=yes notify: restart httpd > 在 notify 中定义内容必定要和handlers中定义的 - name 内容同样,这样才能达到触发的效果,不然会不生效。 - name: start httpd service: name=httpd state=started - name: wall http status shell: /usr/bin/wall `ss -nltp|grep httpd` handlers: - name: restart httpd > 只有接收到通知才会执行这里的任务 service: name=httpd state=restarted
这里准备了一个httpd2.4版本的配置文件 #grep ^Listen /app/httpd.conf Listen 8080
这个配置文件不可用于httpd2.2版本,所以须要在执行时指定匹配的主机用正则判断一下。 --- #ansible-playbook installhttpd.yml --limit ~^7.*web > 支持正则表达式 PLAY [web] TASK [Gathering Facts] ok: [7-web-0.hunk.tech] ok: [7-web-2.hunk.tech]
指定某条任务执行,用于选择运行playbook中的部分代码。 ansible具备幂等性,所以会自动跳过没有变化的部分,
即使如此,有些代码为测试其确实没有发生变化的时间依然会很是地长。此时,若是确信其没有变化,就能够经过
tags跳过此些代码片段。能够为每一个tasks设置tags,这样方便调用。
- name: change httpd.conf copy: src=/app/httpd.conf dest=/etc/httpd/conf/ tags: copyconf > tags:后除了一个空格外,不要有其余空格,中间可使用_下划线 notify: restart httpd
可使用多个tags
#ansible-playbook –t copyconf useradd.yml #ansible-playbook –t copyconf,start_httpd useradd.yml
若是命令或脚本的退出码不为零,可使用以下方式替代 tasks: - name: run this command and ignore the result shell: /usr/bin/somecommand || /bin/true 或者使用ignore_errors来忽略错误信息: tasks: - name: run this command and ignore the result shell: /usr/bin/somecommand ignore_errors: True
变量名仅能由字母、数字和下划线组成,且只能以字母开头
1. # ansible setup facts 远程主机的全部变量均可直接调用。setup模块就是用来获取远程主机的相关信息的。通常以ansible_开头的就是变量能够调用 2. 在/etc/ansible/hosts中定义 普通变量:主机组中主机单独定义,优先级高于公共变量 公共(组)变量:针对主机组中全部主机定义统一变量 [web] 6-web-1.hunk.tech hname=nginx http_prot=8080 > 主机普通变量 7-web-0.hunk.tech hname=httpd http_prot=8081 > 主机普通变量 7-web-2.hunk.tech hname=httpd24 http_prot=8082 > 主机普通变量 [web:vars] 注意:vars是关键字,针对web组内全部主机设置的变量 hname=web > 主机公共(组)变量, 3. 经过命令行指定变量,优先级最高 #ansible-playbook –e 变量名=变量值 http_port=80 4. 在playbook中定义 vars: > 关键字 - var1: value1 - var2: value2 5. vars_files指定变量文件 vars_files: - /app/vars.yml 6. 在role中定义 7. 经过{{ variable_name }} 调用变量,且变量名先后必须有空格,有时用"{{ variable_name }}"才生效 8. register 注册变量 把某一条任务执行的结果保存下来,能够在接下的任务中调用或者作些判断。这里是定义告终果存到什么名字的变量里。常与ignore_errors配合设置成True 整个变量可使用在template中,动做行中,或者是when语句中 使用-v参数来查看存储的内容或者使用debug: var=注册名 register变量的命名不能用 - 中横线 各类变量优先级: 命令行 -e > vars_files指定变量文件 > 主机清单普通变量 > 主机清单公共(组)变量
--- - hosts: web remote_user: root vars: > 关键字 - username: hunk88 > 键值对 - groupname: groupabc > 键值对 tasks: - name: add group group: name={{ groupname }} > 变量调用 - name: add user user: name={{ username }} > 变量调用 ...
--- - hosts: web remote_user: root tasks: - name: create file copy: dest=/app/ip.txt content="{{ ansible_all_ipv4_addresses }}" > 调用了setup 模块收集的ansible_all_ipv4_addresses变量值 ... #cat /app/ip.txt ["192.168.5.102", "172.18.103.79", "192.168.7.201"]
[web] 6-web-1.hunk.tech hname=nginx http_prot=8080 7-web-0.hunk.tech hname=httpd http_prot=8081 7-web-2.hunk.tech hname=httpd24 http_prot=8082 --- - hosts: web remote_user: root tasks: - name: set hostname hostname: name={{ hname }}-{{ http_prot }} 结果: #ansible web -m shell -a 'echo $HOSTNAME' 6-web-1.hunk.tech | SUCCESS | rc=0 >> nginx-8080 7-web-0.hunk.tech | SUCCESS | rc=0 >> httpd-8081 7-web-2.hunk.tech | SUCCESS | rc=0 >> httpd24-8082
[web] 6-web-1.hunk.tech http_prot=8080 7-web-0.hunk.tech http_prot=8081 7-web-2.hunk.tech http_prot=8082 [web:vars] hname=web make="-" tasks: - name: change hostname hostname: name={{ hname }}{{ make }}{{ http_prot }} 结果: #ansible web -m shell -a 'echo $HOSTNAME' 6-web-1.hunk.tech | SUCCESS | rc=0 >> web-8080 7-web-0.hunk.tech | SUCCESS | rc=0 >> web-8081 7-web-2.hunk.tech | SUCCESS | rc=0 >> web-8082
#vim /app/vars.yml hname: nginx > 注意键值对的格式 prot: 9527 playbook: - hosts: web remote_user: root vars_files: - /app/vars.yml tasks: - name: set hostname hostname: name={{ hname }}-{{ prot }} 结果: #ansible web -m shell -a 'echo $HOSTNAME' 6-web-1.hunk.tech | SUCCESS | rc=0 >> nginx-9527 7-web-2.hunk.tech | SUCCESS | rc=0 >> nginx-9527 7-web-0.hunk.tech | SUCCESS | rc=0 >> nginx-9527
- hosts: web tasks: - shell: /bin/cat /etc/centos-release register: release > 将上一条结果保存到release变量 - name: show release debug: var=release 如下是用debug模块查看输出结果 ok: [7-web-0.hunk.tech] => { "release": { "changed": true, > 显示是否已更改 "cmd": "/bin/cat /etc/centos-release", > 执行的命令 "delta": "0:00:00.006148", "end": "2018-02-03 22:47:49.010194", > 执行结束的时间 "failed": false, "rc": 0, > 命令的返回码 "start": "2018-02-03 22:47:49.004046", > 执行开始的时间 "stderr": "", > 若是有错误,则输出错误的信息 "stderr_lines": [], > 逐行输出 "stdout": "CentOS Linux release 7.4.1708 (Core) ", > 命令的输出 "stdout_lines": [ "CentOS Linux release 7.4.1708 (Core) " ] } } 调用: - hosts: web tasks: - shell: /bin/cat /etc/centos-release ignore_errors: true register: release - name: show Centos 6 command: /usr/bin/wall "Centos 6" when: release.stdout | match("CentOS release 6.9 (Final)") - name: show Centos 7 command: /usr/bin/wall "Centos 7" when: release.stdout | search("release 7") > 模糊匹配
- hosts: all tasks: - name: check file shell: ls /app/ip.txt ignore_errors: true register: release - name: show file not found command: /usr/bin/wall "file not found" when: release.rc != 0 - name: show file found command: /usr/bin/wall "file found" when: release.rc == 0
与shell编程中的条件判断相似
在task后添加when子句便可使用条件测试;when语句支持Jinja2表达式语法
前面的案例使用了正则来判断主机的系统版本号,这里直接使用when调用系统变量来判断
match:精确匹配 search:模糊匹配 支持正则表达式 when: release.stdout | match('.*release 6.9.*$') when: release.stdout | match('CentOS release 6.9 \(Final\)') > 精确匹配 when: release.stdout | search("release 7") > 模糊匹配 when: ansible_distribution_major_version == "7"
判断变量是否认义
is defined: 变量已经定义 is undefined: 变量未定义 tasks: - shell: echo "I've got '{{ foo }}' and am not afraid to use it!" when: foo is defined - fail: msg="Bailing out. this play requires 'bar'" when: bar is undefined
当有须要重复性执行的任务时,可使用迭代机制。相似于循环
对迭代项的引用,固定变量名为 item" 要在task中使用with_items给定要迭代的元素列表 列表格式: 字符串 字典
例子:
- hosts: web remote_user: root vars: > 定义了2个变量 - user1: hunk4 > 键值对 - user2: hunk5 tasks: - name: create user user: name={{ item }} > 调用with_items的值,这是固定的关键字,不能换成其余的。 with_items: > with_items:列表开始 - "{{ user1 }}" > 调用vars中定义的2个变量,注意须要用双引号引发来。 - "{{ user2 }}" 结果: #ansible web -a 'tail -n3 /etc/passwd' 6-web-1.hunk.tech | SUCCESS | rc=0 >> user2:x:503:503::/home/user2:/bin/bash hunk4:x:504:504::/home/hunk4:/bin/bash hunk5:x:505:505::/home/hunk5:/bin/bash 7-web-0.hunk.tech | SUCCESS | rc=0 >> user2:x:1003:1003::/home/user2:/bin/bash hunk4:x:1004:1004::/home/hunk4:/bin/bash hunk5:x:1005:1005::/home/hunk5:/bin/bash 7-web-2.hunk.tech | SUCCESS | rc=0 >> user2:x:1003:1003::/home/user2:/bin/bash hunk4:x:1004:1004::/home/hunk4:/bin/bash hunk5:x:1005:1005::/home/hunk5:/bin/bash 固然,也能够不像上面那样,直接在with_items下直接给到列表内容。 另外,每一个- name 下面的with_items能够同时存在,不相互冲突。以下面的: - name: X1 with_items - a - b - name: X2 with_items - c - d
等价的写法:
方法1,多行: tasks: - name: with_items command: wall "{{ item }}" with_items: - 0 - 2 - 4 - 6 - 8 - 10 when: item > 5 方法2,单行: tasks: - name: with_items command: wall "{{ item }}" with_items: [ 0, 2, 4, 6, 8, 10 ] > 使用[ ] 来存放列表 when: item > 5
批量循环建立文件夹
本着为了之后更好的维护变量的设计,此次把变量独立到到个文件中 #vim /app/vars.yml all_data: - A - B - C - D playbook: - hosts: dns remote_user: root vars_files: - /app/vars.yml tasks: - name: create dir file: "path=/tmp/{{ item }} state=directory" with_items: - "{{ all_data }}" #tree /tmp /tmp ├── A ├── B ├── C └── D
此次来了个综合一点的例子,本着为了之后更好的维护变量的设计,此次把变量独立到到个文件中
#cat /app/vars.yml user1: hunk3 > 键值对 user2: hunk4 group1: A group2: B
playbook
- hosts: web remote_user: root vars_files: > 导入变量文件 - /app/vars.yml tasks: - name: create groups group: name={{ item }} > 使用with_items建立组 with_items: - "{{ group1 }}" > with_items列表的值来自变量文件中的变量名 - "{{ group2 }}" - name: create users user: name={{ item.username }} group={{ item.groupname }} > 嵌套子变量,格式为:item.with_items的列表中的键名 with_items: - { username: "{{ user1 }}", groupname: "{{ group1 }}" } > 别晕,最外层的{} 就是键值对的语法,里面有2个键值对,用逗号,分隔。{{ }}是引入的变量键名,注意要用双引号。 - { username: "{{ user2 }}", groupname: "{{ group2 }}" }
结果:
#ansible web -m shell -a 'id hunk3;id hunk4' 6-web-1.hunk.tech | SUCCESS | rc=0 >> uid=502(hunk3) gid=502(A) groups=502(A) uid=503(hunk4) gid=503(B) groups=503(B) 7-web-0.hunk.tech | SUCCESS | rc=0 >> uid=1002(hunk3) gid=1002(A) groups=1002(A) uid=1003(hunk4) gid=1003(B) groups=1003(B) 7-web-2.hunk.tech | SUCCESS | rc=0 >> uid=1002(hunk3) gid=1002(A) groups=1002(A) uid=1003(hunk4) gid=1003(B) groups=1003(B)