命令行参数

参数 说明描述
-v –verbose,详细模式,如果命令执行成功,输出详细的结果(-vv –vvv -vvvv)
-i PATH,–inventory=PATH 指定host文件的路径,默认是在/etc/ansible/hosts(生产环境经常用到)
-f NUM,–forks=NU NUM是指定一个整数,默认是5,指定fork开启同步进程的个数。
-m NAME,–module-name=NAME 指定使用的module名称,默认是command
-a MODULE_ARGS 指定module模块的参数
-k -ask-pass 提示输入ssh的密码,而不是使用基于ssh的密钥认证
-sudo 指定使用sudo获得root权限(生产环境经常用到)
-K -ask-sudo-pass 提示输入sudo密码,与–sudo一起使用 (生产环境经常用到)
-u USERNAME,-user=USERNAME 指定移动端的执行用户
-C -check 测试此命令执行会改变什么内容,不会真正的去执行

指定hosts文件中其中的ip地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# ansible all -i '10.10.214.115,' -m shell -a 'echo $HOSTNAME'    
10.10.214.115 | CHANGED | rc=0 >>
szsjhl-dev-tidb-kv-10-10-214-115-belle

# ansible-playbook -i '10.10.214.115,10.10.214.117,' useradd_app.yml

PLAY [all] **********************************************************************************

.......

TASK [add root key] *************************************************************************
changed: [10.10.214.117]
changed: [10.10.214.115]

PLAY RECAP **********************************************************************************
10.10.214.115 : ok=9 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.10.214.117 : ok=9 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

command模块测试环境

1
2
3
4
5
6
7
8
9
[root@temp01 ~]# ansible all -a "pwd"
192.168.3.70 | SUCCESS | rc=0 >>
/root

192.168.3.60 | SUCCESS | rc=0 >>
/root
 [root@temp01 ~]# ansible all -m command -a "pwd"    #-m command 原来是可以省略的,ansible 默认模块就是command 
 192.168.3.70 | SUCCESS | rc=0 >> /root
 192.168.3.60 | SUCCESS | rc=0 >> /root

ping模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#-f 参数用法[root@temp01 ~]# ansible all -m ping -f 1    #all 表示hosts里面所有主机 -m 调用模块 -f 指定同步进程数
192.168.3.60 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.3.70 | SUCCESS => {
"changed": false,
"ping": "pong"
}#-C参数用法
[root@temp01 ~]# ansible all -m ping -f 1 -C  
192.168.3.60 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.3.70 | SUCCESS => {
"changed": false,
"ping": "pong"
}

copy模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# ansible aaa -m copy -a 'src=/root/script/hostname dest=/root/hostname mode=766'
10.234.7.11 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "61bf4f1ae6c144c8ea1d5a70fd9863f6cd10599f",
"dest": "/root/hostname",
"gid": 0,
"group": "root",
"md5sum": "82f4621b4a415f0ed392ec726021a279",
"mode": "0755",
"owner": "root",
"size": 2160,
"src": "/root/.ansible/tmp/ansible-tmp-1615607732.39-6123-208287757851230/source",
"state": "file",
"uid": 0
}
10.234.7.37 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "61bf4f1ae6c144c8ea1d5a70fd9863f6cd10599f",
"dest": "/root/hostname",
"gid": 0,
"group": "root",
"md5sum": "82f4621b4a415f0ed392ec726021a279",
"mode": "0755",
"owner": "root",
"size": 2160,
"src": "/root/.ansible/tmp/ansible-tmp-1615607732.37-6121-37792777908649/source",
"state": "file",
"uid": 0
}

user模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@temp01 ~]# ansible db -m user -a 'name=DBA uid=505 home=/home/dba shell=/sbin/nologin'
192.168.3.70 | SUCCESS => {
"changed": true,
"comment": "",
"createhome": true,
"group": 505,
"home": "/home/dba",
"name": "DBA",
"shell": "/sbin/nologin",
"state": "present",
"system": false,
"uid": 505
}
[root@temp01 ~]# ansible db -m user -a 'name=DBA state=absent'    #state属性有:present表示添加,absend表示删除,state属性默认是present
192.168.3.70 | SUCCESS => {
"changed": true,
"force": false,
"name": "DBA",
"remove": false,
"state": "absent"
}

修改用户密码

1
2
3
4
5
6
7
8
[root@temp01 ansible_playbook]# ansible all -m shell -a 'echo "123456" | passwd --stdin root'
192.168.3.60 | SUCCESS | rc=0 >>
Changing password for user foo.
passwd: all authentication tokens updated successfully.

192.168.3.70 | SUCCESS | rc=0 >>
Changing password for user foo.
passwd: all authentication tokens updated successfully.

看看下面这个坑

1
2
3
4
5
6
7
8
9
10
11
[root@temp01 ~]# ansible all -m cron -a "name=cat minute='*/1' job='ls /root'"
192.168.3.70 | FAILED! => {
"changed": false,
"failed": true,
"msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"
}
192.168.3.60 | FAILED! => {
"changed": false,
"failed": true,
"msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
[root@temp01 ~]# ansible all -m copy -a "src=/etc/ansible/hosts dest=/root mode=600"
192.168.3.60 | FAILED! => {
"changed": false,
"checksum": "8add7a4e56ae6f7a1c6d0218ce757510d195bb3c",
"failed": true,
"msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"
}
192.168.3.70 | FAILED! => {
"changed": false,
"checksum": "8add7a4e56ae6f7a1c6d0218ce757510d195bb3c",
"failed": true,
"msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"
}

需要在客户端安装libselinux-python库

  • 方法如下
1
2
3
4
5
6
7
[root@temp01 ~]# ansible all -m yum -a 'name=libselinux-python state=present'
192.168.3.70 | SUCCESS => {
"changed": true,
"msg": "warning: rpmts_HdrFromFdno: Header V3 RSA/SHA1 Signature, key ID c105b9de: NOKEY\nImporting GPG key 0xC105B9DE:\n Userid : CentOS-6 Key (CentOS 6 Official Signing Key) <centos-6-key@centos.org>\n Package: centos-release-6-5.el6.centos.11.1.x86_64 (@anaconda-CentOS-201311272149.x86_64/6.5)\n From : /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6\n",
"rc": 0,
"results": [
.........

service 模块

1
2
3
4
5
6
7
8
9
10
11
[root@temp01 ~]# ansible all -m service -a 'name=sshd state=restarted'  #state属性有running,started,stopped,restarted,reloaded
192.168.3.60 | SUCCESS => {
"changed": true,
"name": "sshd",
"state": "started"
}
192.168.3.70 | SUCCESS => {
"changed": true,
"name": "sshd",
"state": "started"
}

yum模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@temp01 ~]# ansible all -m yum -a 'name=ntp state=present'    #state属性有absent,present,installed,removed,latest
192.168.3.70 | SUCCESS => {
"changed": false,
"msg": "",
"rc": 0,
"results": [
"ntp-4.2.6p5-1.el6.centos.x86_64 providing ntp is already installed"
]
}
192.168.3.60 | SUCCESS => {
"changed": false,
"msg": "",
"rc": 0,
"results": [
"ntp-4.2.6p5-1.el6.centos.x86_64 providing ntp is already installed"
]
}

script模块 远程执行脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@temp01 ~]# cat ansible.sh              #脚本内容
#!/bin/bash
echo "Hello world" >>/root/ansible.log
[root@temp01 ~]# ansible all -m script -a 'ansible.sh'
192.168.3.70 | SUCCESS => {
"changed": true,
"rc": 0,
"stderr": "",
"stdout": "",
"stdout_lines": []
}
192.168.3.60 | SUCCESS => {
"changed": true,
"rc": 0,
"stderr": "",
"stdout": "",
"stdout_lines": []
}

[root@example_02 ~]# pwd          #跳转到客户端验证
/root
[root@example_02 ~]# cat ansible.log
Hello world

shell模块

1
2
3
4
5
6
7
8
9
10
[root@temp01 ~]# ansible all -m mommand -a 'cat /etc/passwd | grep root'
ERROR! this task 'mommand' has extra params, which is only allowed in the following modules: command, win_command, shell, win_shell, script, include, include_vars, add_host, group_by, set_fact, raw, meta
[root@temp01 ~]# ansible all -m shell -a 'cat /etc/passwd | grep root'
192.168.3.70 | SUCCESS | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

192.168.3.60 | SUCCESS | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
  • 用shell模块给文件添加内容
1
2
3
4
5
6
7
---
- name: add redis config to application-dev.yml
shell: sed -i '$a\redis:\n database:\ 8\n host:\ 127.0.0.1\n port:\ 6379\n password:' /opt/config/application-dev.yml
ignore_errors: True
- name: add redis config to cfg.properties
shell: sed -i '$a\Redis.DB.State.Check.Index=8' /opt/conf/cfg.properties
ignore_errors: True
  • 对文件中的文本内容进行替换
1
ansible all -m shell -a 'sed -i "s/aaa/export JAVA_HOME=\/usr\/java\/jdk1.8.0_181/g" /etc/profile'
1
2
3
4
5
6
7
8
9
10
---
- name: add new line at 3 line in fileName
shell: sed -i '3i newStr' /path/path/fileName
ignore_errors: True
- name: change oldStr to newStr in fileName
shell: sed -i 's/oldStr/newStr/g' /path/path/fileName
ignore_errors: True
- name: change 5 line to new line in fileName
shell: sed -i '5c newStr' /path/path/fileName
ignore_errors: True

file模块

  • 修改文件属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[root@temp01 ~]# ansible all -m file -a 'path=/root/ansible.log owner=root mode=777 group=root'      #修改文件属性
192.168.3.60 | SUCCESS => {
"changed": true,
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"path": "/root/ansible.log",
"secontext": "unconfined_u:object_r:admin_home_t:s0",
"size": 12,
"state": "file",
"uid": 0
}
192.168.3.70 | SUCCESS => {
"changed": true,
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"path": "/root/ansible.log",
"secontext": "unconfined_u:object_r:admin_home_t:s0",
"size": 12,
"state": "file",
"uid": 0
}
  • 新建目录:类 mkdir -p
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[root@temp01 ~]# ansible all -m file -a 'dest=/root/1/2/3/4/ mode=755 owner=root group=root state=directory'
192.168.3.60 | SUCCESS => {
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/root/1/2/3/4/",
"secontext": "unconfined_u:object_r:admin_home_t:s0",
"size": 4096,
"state": "directory",
"uid": 0
}
192.168.3.70 | SUCCESS => {
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/root/1/2/3/4/",
"secontext": "unconfined_u:object_r:admin_home_t:s0",
"size": 4096,
"state": "directory",
"uid": 0
}


[root@example_02 ~]# ll
total 48
-rw-------. 1 root root 1106 Jul 11 05:26 anaconda-ks.cfg
-rwxrwxrwx. 1 root root 12 Dec 30 02:53 ansible.log
-rw-------. 1 root root 1052 Dec 30 01:09 hosts
-rw-r--r--. 1 root root 23089 Jul 11 05:26 install.log
-rw-r--r--. 1 root root 6240 Jul 11 05:24 install.log.syslog
[root@example_02 ~]# cd 1/2/3/4/                        #转到客户端验证
You have new mail in /var/spool/mail/root
[root@example_02 4]# pwd
/root/1/2/3/4
  • 删除目录文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@temp01 ~]# ansible all -m file -a 'dest=/root/1/2/3/4/  state=absent'
192.168.3.60 | SUCCESS => {
"changed": true,
"path": "/root/1/2/3/4/",
"state": "absent"
}
192.168.3.70 | SUCCESS => {
"changed": true,
"path": "/root/1/2/3/4/",
"state": "absent"
}

[root@example_02 ~]# cd 1/2/3/4            #跳转验证
-bash: cd: 1/2/3/4: No such file or directory
[root@example_02 ~]#

hosts文件编辑

1
2
3
4
5
6
7
8
9
10
# cat /etc/ansible/hosts 
[aaa]
10.10.10.10
10.10.10.11

[aaa:vars]
ansible_ssh_user="root"
ansible_ssh_pass="yougou"
ansible_ssh_port="22"

lineinfile模块

常用需求

1、替换某行内容
2、在某行前插入内容
3、在某行后面插入内容
4、删除某行

测试文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[client]
port=3306
socket=/tmp/mysql.sock

[mysqld]
user = mysql
basedir = /app/mysql
datadir = /app/mysql/data
port=3306
server-id = 1
socket=/tmp/mysql.sock

[mysqldump]
quick
max_allowed_packet = 16M

playbook 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
---
- hosts: test
remote_user: cedar
become: yes
tasks:
- name: "在socket=/tmp/mysql.sock前插入内容"
lineinfile:
path: /etc/my_bak.cnf
insertbefore: 'socket=/tmp/mysql.sock'
line: 我是socket前面的内容
- name: "在server-id后插入内容"
lineinfile:
path: /etc/my_bak.cnf
insertafter: 'server-id = 1'
line: 我是server-id后面的内容
- name: "user=mysql 替换"
lineinfile:
path: /etc/my_bak.cnf
regexp: '^user = mysql'
line: user = mingkang
- name: "删除quick这行"
lineinfile:
path: /etc/my_bak.cnf
regexp: 'quick'
state: absent

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# ansible-playbook lineinfile.yaml 

PLAY [test] *****************************************************************************************************************************************************

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

TASK [在socket=/tmp/mysql.sock前插入内容] *****************************************************************************************************************************
changed: [10.3.153.8]

TASK [在server-id后插入内容] ******************************************************************************************************************************************
changed: [10.3.153.8]

TASK [user=mysql 替换] ********************************************************************************************************************************************
changed: [10.3.153.8]

TASK [删除quick这行] ************************************************************************************************************************************************
changed: [10.3.153.8]

PLAY RECAP ******************************************************************************************************************************************************
10.3.153.8 : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

验证结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# cat my_bak.cnf 
[client]
port=3306
socket=/tmp/mysql.sock

[mysqld]
user = mingkang
basedir = /app/mysql
datadir = /app/mysql/data
port=3306
server-id = 1
我是server-id后面的内容
我是socket前面的内容
socket=/tmp/mysql.sock

[mysqldump]
max_allowed_packet = 16M

实例 安装jdk其中一部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# ansible all -m lineinfile -a 'dest=/etc/profile line="export JAVA_HOME=/usr/java/jdk1.8.0_181\nexport PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin\nexport CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$CLASSPATH"'
10.0.80.51 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"backup": "",
"changed": true,
"msg": "line added"
}
10.0.80.50 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"backup": "",
"changed": true,
"msg": "line added"
}
1
2
3
4
5
6
7
8
9
---
- name: add redis config to application-dev.yml
shell: sed -i '$a\redis:\n database:\ 8\n host:\ 127.0.0.1\n port:\ 6379\n password:' /opt/config/application.yml
ignore_errors: True
- name: add redis config to cfg.properties
lineinfile:
dest: /opt/conf/cfg.properties
line: 'Redis.DB.State.Check.Index=8'
ignore_errors: True