ansible
第二天
以上学习了ping、command、shell、script模块,但一般不建议使用以上三个,因为这三个模块没有幂等性。举例如下:
[root@control ansible]# ansible test -a "mkdir /tmp/1234"
 [WARNING]: Consider using the file module with state=directory rather than running 'mkdir'.
If you need to use command because file is insufficient you can add 'warn: false' to this
command task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
node1 | CHANGED | rc=0 >>
[root@control ansible]# ansible test -a "mkdir /tmp/1234"
 [WARNING]: Consider using the file module with state=directory rather than running 'mkdir'.
If you need to use command because file is insufficient you can add 'warn: false' to this
command task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
node1 | FAILED | rc=1 >>
mkdir: 无法创建目录 “/tmp/1234”: 文件已存在non-zero return code
因为被控主机已经存在了要创建的目录,所以报错显示已存在
如果不想看到报错,可以使用专用的file模块
[root@control ansible]# ansible test -m file -a "path=/tmp/1234 state=directory"
node1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "gid": 0,
    "group": "root",
    "mode": "0755",
    "owner": "root",
    "path": "/tmp/1234",
    "size": 6,
    "state": "directory",
    "uid": 0
}file模块
查看使用帮助
EXAMPLES:
- name: Change file ownership, group and permissions
  file:   模块名。以下是它的各种参数
    path: /etc/foo.conf  要修改的文件的路径
    owner: foo   文件所有者
    group: foo   文件的所有组
    mode: '0644'  权限
根据上面的example,-m file -a的内容就是doc中把各参数的冒号换成=号
在test主机上创建/tmp/file.txt
[root@control ansible]# ansible test -m file -a "path=/tmp/file.txt state=touch"  touch是指如果文件不存在,则创建
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "dest": "/tmp/file.txt",
    "gid": 0,
    "group": "root",
    "mode": "0644",
    "owner": "root",
    "size": 0,
    "state": "file",
    "uid": 0
}
[root@node1 ~]# ls /tmp | grep file.txt
file.txt
在test主机上创建/tmp/demo目录
[root@control ansible]# ansible test -m file -a "path=/tmp/demo state=directory"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "gid": 0,
    "group": "root",
    "mode": "0755",
    "owner": "root",
    "path": "/tmp/demo",
    "size": 6,
    "state": "directory",
    "uid": 0
}
[root@node1 ~]# ls /tmp | grep demo
demo
在test主机上创建一个/tmp/file.txt文件,属主为sshd,属组为adn 权限为777
[root@control ansible]# ansible test -m file -a "path=/tmp/file.txt owner=sshd group=adm mode="0777""
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "gid": 4,
    "group": "adm",
    "mode": "0777",
    "owner": "sshd",
    "path": "/tmp/file.txt",
    "size": 0,
    "state": "file",
    "uid": 74
}
[root@node1 ~]# ll /tmp | grep file
-rwxrwxrwx  1 sshd adm     0 11月  8 18:00 file.txt
在test主机上删除/tmp/file.txt文件
[root@control ansible]# ansible test -m file -a "path=/tmp/file.txt state=absent"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "path": "/tmp/file.txt",
    "state": "absent"
}
在test主机上删除/tmp/demo目录
[root@control ansible]# ansible test -m file -a "path=/tmp/demo state=absent"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "path": "/tmp/demo",
    "state": "absent"
}
在test主机上创建/etc/hosts的软连接,目标是/tmp/host.txt
[root@control ansible]# ansible test -m file -a "src=/etc/hosts dest=/tmp/host.txt state=link"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "dest": "/tmp/host.txt",
    "gid": 0,
    "group": "root",
    "mode": "0777",
    "owner": "root",
    "size": 10,
    "src": "/etc/hosts",
    "state": "link",
    "uid": 0
}
copy模块
用于将文件从控制端拷贝到被控端
常用选项:
src:源。控制端的文件路径
dest:目标。被控制端的文件路径
content: 内容。需要写到文件中的内容
[root@control ansible]# ansible test -m copy -a "src=a.txt dest=/root"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "checksum": "54e87908396f730ae24754dc967d141bee7a293f",
    "dest": "/root/a.txt",
    "gid": 0,
    "group": "root",
    "md5sum": "5ce11a5724b80ca946683b6c626bdb6c",
    "mode": "0644",
    "owner": "root",
    "size": 4,
    "src": "/root/.ansible/tmp/ansible-tmp-1699486007.0826297-54906651569985/source",
    "state": "file",
    "uid": 0
}
[root@node1 ~]# cat a.txt 
Aaa
绝对路径
[root@control ansible]# ansible test -m copy -a "src=/root/root.txt dest=/root"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "checksum": "552c0ba71b1046a083583ebf943cc9aa09f39a32",
    "dest": "/root/root.txt",
    "gid": 0,
    "group": "root",
    "md5sum": "74cc1c60799e0a786ac7094b532f01b1",
    "mode": "0644",
    "owner": "root",
    "size": 5,
    "src": "/root/.ansible/tmp/ansible-tmp-1699486076.8466651-150992524492280/source",
    "state": "file",
    "uid": 0
}
[root@node1 ~]# cat root.txt 
root
发送目录成功
[root@control ansible]# ansible test -m copy -a "src=/etc/security dest=/root/"
node1 | CHANGED => {
    "changed": true,
    "dest": "/root/",
    "src": "/etc/security"
}
[root@node1 ~]# ls | grep test
[root@node1 ~]# ll | grep security
drwxr-xr-x  7 root root 4096 11月  8 18:31 security
前提是目录不能为空
如果 getenforce状态不为Disabled,需要再各个主机安装python3-libselinux软件包
在远程主机直接创建文件,添加内容
[root@control ansible]# ansible test -m copy -a "dest=/tmp/mytest.txt content='hello world'"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "checksum": "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed",
    "dest": "/tmp/mytest.txt",
    "gid": 0,
    "group": "root",
    "md5sum": "5eb63bbbe01eeed093cb22bb8f5acdc3",
    "mode": "0644",
    "owner": "root",
    "size": 11,
    "src": "/root/.ansible/tmp/ansible-tmp-1699486796.9039702-79725117871198/source",
    "state": "file",
    "uid": 0
}
[root@node1 ~]# cat /tmp/mytest.txt 
hello worldfetch模块
与copy模块相反,copy是上传,fetch是下载
常用选项:
src:源。被控制端的文件路径
dest:目标。控制端的文件路径
将test主机上的/etc/hostname下载到本地用户的家目录下
[root@control ansible]# ansible webservers -m fetch -a "src=/etc/hostname dest=~/"
node3 | CHANGED => {
    "changed": true,
    "checksum": "70e478f6fb7a1971d09496d109002c5809006a86",
    "dest": "/root/node3/etc/hostname",
    "md5sum": "3ce6701b5ee42becf085baf7368fe8ce",
    "remote_checksum": "70e478f6fb7a1971d09496d109002c5809006a86",
    "remote_md5sum": null
}
node4 | CHANGED => {
    "changed": true,
    "checksum": "5367c434083cf09560c19a3338c1d6caa791f36b",
    "dest": "/root/node4/etc/hostname",
    "md5sum": "a97ac14927fea0efc7a9733fe320cd99",
    "remote_checksum": "5367c434083cf09560c19a3338c1d6caa791f36b",
    "remote_md5sum": null
}
[root@control ansible]# ls ~/node3/etc/
hostname  
[root@control ansible]# ls ~/node4/etc/
hostname
不能下载目录
[root@control ansible]# ansible webservers -m fetch -a "src=/root/aaa dest=~/"
node4 | FAILED! => {
    "changed": false,
    "file": "/root/aaa",
    "msg": "remote file is a directory, fetch cannot work on directories"
}
node3 | FAILED! => {
    "changed": false,
    "file": "/root/aaa",
    "msg": "remote file is a directory, fetch cannot work on directories"
}lineinfile模块
用于确保存目标文件中有某一行内容
常用选项:
path:待修改的文件路径
line: 写入文件的一行内容
regexp:正则表达式,用于查找文件中的内容
test组的主机,/etc/issue中一定要有一行hello world。如果该行不存在,则默认添加到文件结尾
[root@control ansible]# ansible test -m lineinfile -a "path=/etc/issue line='hello world'"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "backup": "",
    "changed": true,
    "msg": "line added"
}
[root@node1 ~]# cat /etc/issue
\S
Kernel \r on an \m
hello world
test组中的主机,把/etc/issue中有hello的行,替换成chi le ma
[root@control ansible]# ansible test -m lineinfile -a "path=/etc/issue line='chi le ma' regexp=hello"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "backup": "",
    "changed": true,
    "msg": "line replaced"
}
[root@node1 ~]# cat /etc/issue
\S
Kernel \r on an \m
chi le ma
[root@control ansible]# ansible test -m lineinfile -a "path=/etc/issue line='chi le ma' regexp=hello"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "backup": "",
    "changed": true,
    "msg": "line added"
}
[root@node1 ~]# cat /etc/issue
\S
Kernel \r on an \m
chi le ma
chi le mareplace模块
lineinfile会替换一行,replace可以替换关键词
常用选项:
path:待修改的文件路径
replace:将正则表达式查到的内容,替换成replace的内容
regexp: 正则表达式,用于查找文件中的内容
将test组中的主机上/etc/issue文件中的chi,替换成he
[root@node1 ~]# cat /etc/issue
\S
Kernel \r on an \m
chi le ma
chi le ma
[root@control ansible]# ansible test -m replace  -a "path=/etc/issue regexp=chi replace="he""
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "2 replacements made"
}
[root@node1 ~]# cat /etc/issue
\S
Kernel \r on an \m
he le ma
he le ma
文件操作综合练习

[root@control ansible]# cat exec.sh 
#!/bin/bash
ansible test -m file -a "path=/tmp/mydemo state=directory owner=adm group=adm mode=0777"
ansible test -m copy -a "src=/etc/hosts dest=/tmp/mydemo owner=adm group=adm mode=0600"
ansible test -m replace -a "path=/tmp/mydemo/hosts regexp='node5' replace='server5'"
ansible test -m fetch -a "src=/tmp/mydemo/hosts dest=/root/ansible/"user模块
实现linux用户管理
常用选项:
name: 待创建的用户名
uid:用户ID
group:设置主组
groups:设置附加组
home:设置家目录
password:设置用户密码
state:状态。present表示创建,它是默认选项。absent表示删除
remove:删除家目录、邮箱等。值为yes或者true都可以
在test主机上创建个tom用户
[root@control ansible]# ansible test -m user -a "user=tom"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "comment": "",
    "create_home": true,
    "group": 1000,
    "home": "/home/tom",
    "name": "tom",
    "shell": "/bin/bash",
    "state": "present",
    "system": false,
    "uid": 1000
}
[root@node1 ~]# cat /etc/passwd | grep ^tom
tom:x:1000:1000::/home/tom:/bin/bash
[root@control ansible]# ansible test -m user -a "name=jerry uid=1010 group=adm groups=daemon,root home=/home/jerry"
设置tom密码为123456,用sha512加密
[root@control ansible]# ansible test -m user -a "name=tom password={{'123456'|password_hash('sha512')}}"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "append": false,
    "changed": true,
    "comment": "",
    "group": 1000,
    "home": "/home/tom",
    "move_home": false,
    "name": "tom",
    "password": "NOT_LOGGING_PASSWORD",
    "shell": "/bin/bash",
    "state": "present",
    "uid": 1000
}
[root@node1 ~]# cat /etc/shadow | grep tom
tom:$6$Dfyqw6ty.pPwnyZm$SRpTqqORuCbPFGcdPuT8sNHHmIpHJAslaoDgk1RCA6gIAEEeg9tvz8MBxj7mGR1j4LV7GVN.1teZQ7OUaP51J1:19670:0:99999:7:::
删除tom用户,不删除家目录
[root@control ansible]# ansible test -m user -a "name=tom state=absent"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "force": false,
    "name": "tom",
    "remove": false,
    "state": "absent"
}
删除jerry用户,同时删除家目录
[root@control ansible]# ansible test -m user -a "name=jerry state=absent remove=yes"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "force": false,
    "name": "jerry",
    "remove": true,
    "state": "absent"
}
[root@node1 ~]# ls /home
tom
group模块
创建、删除组
常用选项:
name:待创建的组名
gid:组的ID号
state:prensent表示创建、它是默认选项。absent是删除
在test组的主机上创建名为devops的组
[root@control ansible]# ansible test -m group -a "name=devops state=present"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "gid": 1000,
    "name": "devops",
    "state": "present",
    "system": false
 }
 在test组的主机上删除名为devops的组
[root@control ansible]# ansible test -m group -a "name=devops state=absent"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "name": "devops",
    "state": "absent"
}


















