ansible命令详解_ansible playbook执行shell脚本

(85) 2024-07-08 22:01:01

Ansible介绍

  • 不需要安装客户端,通过sshd去通信
  • 基于模块工作,模块可以由任何语言开发
  • 不仅支持命令行使用模块,也支持编写yaml格式的playbook,易于编写和阅读 安装十分简单,centos上可直接yum安装
  • 有提供UI(浏览器图形化)www.ansible.com/tower,收费的
  • 官方文档 http://docs.ansible.com/ansible/latest/index.html
  • ansible已经被redhat公司收购,它在github上是一个非常受欢迎的开源软件,github地址https://github.com/ansible/ansible
  • 一本不错的入门电子书 https://ansible-book.gitbooks.io/ansible-first-book/

Ansible安装

  • 准备两台机器,前面我们做实验的两台机器aming-01,aming-02
  • 只需要在aming-01上安装ansible
  • yum list |grep ansible 可以看到自带源里就有2.4版本的ansible
  • yum install -y ansible
  • aming-01上生成密钥对 ssh-keygen -t rsa
  • 把公钥放到aming-02上,设置密钥认证
  • vi /etc/ansible/hosts //增加
    [testhost]
    127.0.0.1
    192.168.133.132 说明: testhost为主机组名字,自定义的。 下面两个ip为组内的机器ip。
<root@linux0 /srv/salt>$ yum list |grep ansible ansible.noarch 2.4.2.0-2.el7 @extras ansible-doc.noarch 2.4.2.0-2.el7 @extras centos-release-ansible26.noarch 1-3.el7.centos extras <root@linux0 /srv/salt>$ yum install ansible ansible-doc <root@linux0 /srv/salt>$ ssh 192.168.87.150 root@192.168.87.150's password: #需要密码; <root@linux0 /srv/salt>$ ssh-copy-id 192.168.87.150 #把公钥复制过去,实现无密码登陆机器,ssh只认IP和帐号,不判断hostname(旧的hostname生成的密钥也可以用);149机器即本机需要做同样的工序,linux可本机ssh登陆本机; <root@linux0 /srv/salt>$ vim /etc/ansible/hosts #添加如下内容; [thosts] #设置一个主机组;可使用组名操作组内机器; 192.168.87.149 #组内机器IP; 192.168.87.150 #组内机器IP; 

Ansible远程执行命令

  • ansible testhost -m command -a ‘w’ 这样就可以批量执行命令了。
  • 这里的testhost 为主机组名,-m后边是模块名字,-a后面是命令。当然我们也可以直接写一个ip,针对某一台机器来执行命令。
  • ansible 127.0.0.1 -m command -a ‘hostname’
  • 错误: “msg”: “Aborting, target uses selinux but python bindings (libselinux-python) aren’t installed!”
  • 解决: yum install -y libselinux-python
  • 还有一个模块就是shell同样也可以实现 ansible testhost -m shell -a ‘w’
<root@linux0 /srv/salt>$ ansible thosts -m command -a 'hostname' 192.168.87.150 | SUCCESS | rc=0 >> linux1 192.168.87.149 | SUCCESS | rc=0 >> linux0 <root@linux0 /srv/salt>$ ansible thosts -m shell -a "ps aux |grep http" #shell才可以用管道符; 192.168.87.150 | SUCCESS | rc=0 >> #不展示具体内容; 192.168.87.149 | SUCCESS | rc=0 >> <root@linux0 /srv/salt>$ ansible thosts -m command -a "ps aux |grep http" #command使用出错; 192.168.87.150 | FAILED | rc=1 >> error: garbage option 192.168.87.149 | FAILED | rc=1 >> error: garbage option 

Ansible拷贝文件或者目录

  • ansible aming-02 -m copy -a “src=/etc/ansible dest=/tmp/ansibletest owner=root group=root mode=0755”
  • 注意:源目录会放到目标目录下面去,如果目标指定的目录不存在,它会自动创建。如果拷贝的是文件,dest指定的名字和源如果不同,并且它不是已经存在的目录,相当于拷贝过去后又重命名。但相反,如果desc是目标机器上已经存在的目录,则会直接把文件拷贝到该目录下面。
  • ansible testhost -m copy -a “src=/etc/passwd dest=/tmp/123”
    这里的/tmp/123和源机器上的/etc/passwd是一致的,但如果目标机器上已经有/tmp/123目录,则会再/tmp/123目录下面建立passwd文件
<root@linux0 ~>$ vi /etc/ansible/hosts #修改hosts name; [thosts] 192.168.87.149 #ansible命令控制一台机器时,一定要用这个名字; #192.168.87.150 linux1 #改成字符形式; <root@linux0 ~>$ ansible 192.168.87.150 -m command -a "w" #修改之后不能用IP登陆; [WARNING]: Could not match supplied host pattern, ignoring: 192.168.87.150 [WARNING]: No hosts matched, nothing to do <root@linux0 ~>$ cat !$ cat /etc/hosts #127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 #::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 #192.168.87.149 linux0 192.168.87.150 linux1 #设置hosts; 对应ansible hosts设置; <root@linux0 ~>$ ansible linux1 -m command -a "w" linux1 | SUCCESS | rc=0 >> 12:32:38 up 21 days, 22:45, 2 users, load average: 0.10, 0.18, 0.13 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/1 192.168.87.1 五17 3:18 0.13s 0.13s -bash root pts/2 linux0 12:32 0.00s 0.10s 0.00s w 
<root@linux0 ~>$ ansible linux1 -m copy -a "src=/etc/ansible dest=/tmp/bucunzai owner=root group=root mode=0755" #目标路径是源目录的上级目录,不存在会创建,并把整个目录放在新建目录下; linux1 | SUCCESS => { 
    "changed": true, "dest": "/tmp/bucunzai/", "src": "/etc/ansible" } <root@linux0 ~>$ ansible linux1 -m command -a "ls -ld /tmp/bucunzai" linux1 | SUCCESS | rc=0 >> drwxr-xr-x 3 root root 21 12月 30 12:37 /tmp/bucunzai <root@linux0 ~>$ date 2019年 12月 30日 星期一 12:37:55 CST <root@linux0 ~>$ ansible linux1 -m command -a "ls -l /tmp/bucunzai" linux1 | SUCCESS | rc=0 >> 总用量 0 drwxr-xr-x 3 root root 51 12月 30 12:37 ansible <root@linux0 ~>$ ls /etc/ansible ansible.cfg hosts roles <root@linux0 ~>$ ll !$ ll /etc/ansible 总用量 24 -rw-r--r-- 1 root root 19179 1月 30 2018 ansible.cfg -rw-r--r-- 1 root root 1062 12月 30 12:28 hosts drwxr-xr-x 2 root root 6 1月 30 2018 roles <root@linux0 ~>$ ansible linux1 -m copy -a "src=/etc/ansible/hosts dest=/tmp/bucunzaifile" #copy文件,修改了文件名字; linux1 | SUCCESS => { 
    "changed": true, "checksum": "d2498e8c027056bced372d02a144ad2a5", "dest": "/tmp/bucunzaifile", "gid": 0, "group": "root", "md5sum": "9e8b0416c70cd4cbc058dee4", "mode": "0644", "owner": "root", "size": 1062, "src": "/root/.ansible/tmp/ansible-tmp-.99-404/source", "state": "file", "uid": 0 } <root@linux0 ~>$ ansible linux1 -m command -a "ll /tmp/bucunzaifile" #不能用别名,cp这些别名与名字一样的命令可用; linux1 | FAILED | rc=2 >> [Errno 2] 没有那个文件或目录 <root@linux0 ~>$ ansible linux1 -m command -a "ls -l /tmp/bucunzaifile" linux1 | SUCCESS | rc=0 >> -rw-r--r-- 1 root root 1062 12月 30 12:47 /tmp/bucunzaifile <root@linux0 ~>$ ansible linux1 -m copy -a "src=/etc/ansible/hosts dest=/tmp/bucunzai2/bucunzaifile" #复制文件时,文件名之前的目录必须要存在的,不存在的目录不会自动创建; linux1 | FAILED! => { 
    "changed": false, "checksum": "d2498e8c027056bced372d02a144ad2a5", "msg": "Destination directory /tmp/bucunzai2 does not exist" } <root@linux0 ~>$ ansible linux1 -m copy -a "src=/etc/ansible/hosts dest=/tmp/bucunzai/bucunzaifile" #存在目录时,会修改名字,dest最后一段就是文件名; linux1 | SUCCESS => { 
    "changed": true, "checksum": "d2498e8c027056bced372d02a144ad2a5", "dest": "/tmp/bucunzai/bucunzaifile", "gid": 0, "group": "root", "md5sum": "9e8b0416c70cd4cbc058dee4", "mode": "0644", "owner": "root", "size": 1062, "src": "/root/.ansible/tmp/ansible-tmp-.34-145/source", "state": "file", "uid": 0 } 

Ansible远程执行脚本

  • 首先创建一个shell脚本
    vim /tmp/test.sh //加入内容
    #!/bin/bash echo
    date > /tmp/ansible_test.txt
  • 然后把该脚本分发到各个机器上
    ansible testhost -m copy -a “src=/tmp/test.sh dest=/tmp/test.sh mode=0755”
  • 最后是批量执行该shell脚本
    ansible testhost -m shell -a “/tmp/test.sh”
  • shell模块,还支持远程执行命令并且带管道
    ansible testhost -m shell -a "cat /etc/passwd|wc -l "
root@linux0 ~>$ vim /tmp/test.sh [root@linux0 ~]# cat /tmp/test.sh  #! /bin/bash echo `date` > /tmp/ansible_test.txt [root@linux0 ~]# ansible thosts -m copy -a "src=/tmp/test.sh dest=/tmp/test.sh mode=0755" linux1 | SUCCESS => { 
    "changed": true, #复制成功;黄色显示;莹光粉警告,如找不到文件;红色运行失败,如脚本语法错误; "checksum": "432f5691b624e4f391ca4f564e99845d58c0eeab", "dest": "/tmp/test.sh", "gid": 0, "group": "root", "md5sum": "bb8fe20b104f03555ca8374f0bf68caa", "mode": "0755", "owner": "root", "size": 49, "src": "/root/.ansible/tmp/ansible-tmp-.11-4552/source", "state": "file", "uid": 0 } 192.168.87.149 | SUCCESS => { 
    "changed": false, #本机复制不成功,不用操作,绿色显示; "checksum": "432f5691b624e4f391ca4f564e99845d58c0eeab", "gid": 0, "group": "root", "mode": "0755", "owner": "root", "path": "/tmp/test.sh", "size": 49, "state": "file", "uid": 0 } [root@linux0 ~]# ansible thosts -m shell -a "/tmp/test.sh" linux1 | SUCCESS | rc=0 >> 192.168.87.149 | SUCCESS | rc=0 >> [root@linux0 ~]# ansible thosts -m shell -a "cat /tmp/ansible_test.txt" #生成的文件内容; linux1 | SUCCESS | rc=0 >> 2019年 12月 30日 星期一 13:56:07 CST 192.168.87.149 | SUCCESS | rc=0 >> 2019年 12月 30日 星期一 13:56:08 CST 

Ansible管理任务计划

  • ansible testhost -m cron -a “name=‘test cron’ job=’/bin/touch /tmp/1212.txt’ weekday=6”
  • 若要删除该cron 只需要加一个字段 state=absent
  • ansible testhost -m cron -a “name=‘test cron’ state=absent”
  • 其他的时间表示:分钟 minute 小时 hour 日期 day 月份 month
[root@linux0 ~]# ansible thosts -m cron -a "name='test cron' job='/bin/touch /tmp/1212.txt' minute=1 hour=3 day=10" linux1 | SUCCESS => { 
    "changed": true, "envs": [], "jobs": [ "test cron" ] } 192.168.87.149 | SUCCESS => { 
    "changed": true, "envs": [], "jobs": [ "test cron" ] } [root@linux0 ~]# crontab -l #Ansible: test cron 1 3 10 * * /bin/touch /tmp/1212.txt [root@linux0 ~]# ansible thosts -m cron -a "name='test cron' state=absent" linux1 | SUCCESS => { 
    "changed": true, "envs": [], "jobs": [] } 192.168.87.149 | SUCCESS => { 
    "changed": true, "envs": [], "jobs": [] } [root@linux0 ~]# crontab -l 

Ansible安装rpm包/管理服务

  • ansible testhost -m yum -a “name=httpd”
  • 在name后面还可以加上state=installed/removed
  • ansible testhost -m service -a “name=httpd state=started enabled=yes”
  • 这里的name是centos系统里的服务名,可以通过chkconfig --list查到。
  • Ansible文档的使用
    ansible-doc -l 列出所有的模块
    ansible-doc cron 查看指定模块的文档
[root@linux0 ~]# ansible linux1 -m yum -a "name=httpd state=removed" #删除; linux1 | SUCCESS => { 
    "changed": true, "msg": "", "rc": 0, "results": [ "已加载插件:fastestmirror\n正在解决依赖关系\n--> 正在检查事务\n---> 软件包 httpd.x86_64.0.2.4.6-90.el7.centos 将被 删除\n--> 解决依赖关系完成\n\n依赖关系解决\n\n================================================================================\n Package 架构 版本 源 大小\n================================================================================\n正在删除:\n httpd x86_64 2.4.6-90.el7.centos @base 9.4 M\n\n事务概要\n================================================================================\n移除 1 软件包\n\n安装大小:9.4 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n 正在删除 : httpd-2.4.6-90.el7.centos.x86_64 1/1 \n 验证中 : httpd-2.4.6-90.el7.centos.x86_64 1/1 \n\n删除:\n httpd.x86_64 0:2.4.6-90.el7.centos \n\n完毕!\n" ] } [root@linux0 ~]# ansible linux1 -m yum -a "name=httpd" #安装; linux1 | SUCCESS => { 
    "changed": true, "msg": "", "rc": 0, "results": [ "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-90.el7.centos will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n httpd x86_64 2.4.6-90.el7.centos base 2.7 M\n\nTransaction Summary\n================================================================================\nInstall 1 Package\n\nTotal download size: 2.7 M\nInstalled size: 9.4 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : httpd-2.4.6-90.el7.centos.x86_64 1/1 \n Verifying : httpd-2.4.6-90.el7.centos.x86_64 1/1 \n\nInstalled:\n httpd.x86_64 0:2.4.6-90.el7.centos \n\nComplete!\n" ] } [root@linux0 ~]# ansible linux1 -m service -a "name=httpd state=started enabled=yes" #启动; linux1 | SUCCESS => { 
    "changed": true, "enabled": true, "name": "httpd", "state": "started", [root@linux0 ~]# ansible linux1 -m command -a "systemctl status httpd" #可使用service/systemctl查询状态,只有开启状态会绿色显示,关闭状态会显示成红色,其实并没有错误,只是因为返回码是3; linux1 | SUCCESS | rc=0 >> ● httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled) Active: active (running) since 一 2019-12-30 16:04:04 CST; 1min 30s ago Docs: man:httpd(8) man:apachectl(8) Main PID: 68555 (httpd) Status: "Total requests: 0; Current requests/sec: 0; Current traffic: 0 B/sec" CGroup: /system.slice/httpd.service ├─68555 /usr/sbin/httpd -DFOREGROUND ├─68598 /usr/sbin/httpd -DFOREGROUND ├─68599 /usr/sbin/httpd -DFOREGROUND ├─68600 /usr/sbin/httpd -DFOREGROUND ├─68601 /usr/sbin/httpd -DFOREGROUND └─68602 /usr/sbin/httpd -DFOREGROUND 12月 30 16:03:44 linux1 systemd[1]: Starting The Apache HTTP Server... 12月 30 16:03:54 linux1 httpd[68555]: AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using fe80::50a5:f454:5189:9942. Set the 'ServerName' directive globally to suppress this message 12月 30 16:04:04 linux1 systemd[1]: Started The Apache HTTP Server. [root@linux0 ~]# ansible linux1 -m service -a "name=httpd state=stauts" #service模块并没有status; linux1 | FAILED! => { 
    "changed": false, "msg": "value of state must be one of: started,stopped,restarted,reloaded, got: stauts" } 
THE END

发表回复