> 所谓 ad-hoc 命令是什么呢?
这其实是一个概念性的名字,是相对于写 Ansible playbook 来说的.类似于在命令行敲入shell命令和 写shell scripts两者之间的关系... 如果我们敲入一些命令去比较快的完成一些事情,而不需要将这些执行的命令特别保存下来, 这样的命令就叫做 ad-hoc 命令。 Ansible提供两种方式去完成任务,一是 ad-hoc 命令,一是写 Ansible playbook.前者可以解决一些简单的任务, 后者解决较复杂的任务。一般而言,在学习了 playbooks 之后,你才能体会到 Ansible 真正的强大之处在哪里!
ansible常用模块及其用法示例如下:
一、 command
: 命令模块
ansible有许多模块,默认就是 command,即命令模块,我们可以通过 -m 选项来指定不同的模块。在下面例子中,我们要在 WebServer 组下的服务器中执行 reboot 命令,因为默认就是命令模块,所以就不需要在用-m这个选项指定 ‘command’ 模块。一会在其他例子中,我们会使用 -m 运行其他的模块!
1.1、重启WebServer组下所有服务器,每次重启10个(ssh-agent会fork出10个子进程(bash),以并行的方式执行reboot命令)
1 |
[root@imzcy ~]# ansible WebServer -a "/sbin/reboot" -f 10 |
1.2、查看WebServer组下所有服务器家目录下有哪些文件(ansible hosts配置文件中定义的以哪个用户去认证连接被管理的服务器,就显示哪个用户家目录)
1 2 3 4 5 |
[root@imzcy ~]# ansible WebServer -a "ls -l" 192.168.109.133 | SUCCESS | rc=0 >> 总用量 0 -rw-r--r-- 1 root root 0 10月 19 11:24 root.txt [root@imzcy ~]# |
1.3、另外需要注意的是:command 模块不支持 shell 变量,也不支持管道等 shell 相关的东西。如果你想使用 shell相关的这些东西, 请使用 'shell' 模块!
1 2 3 4 5 6 7 8 9 10 |
[root@imzcy ~]# ansible WebServer -a "df -h |grep /$" 192.168.109.133 | FAILED | rc=1 >> df: "|grep": 没有那个文件或目录 df: "/$": 没有那个文件或目录non-zero return code [root@imzcy ~]# [root@imzcy ~]# ansible WebServer -m shell -a "df -h |grep /$" 192.168.109.133 | SUCCESS | rc=0 >> /dev/mapper/centos-root 18G 1.2G 17G 7% / [root@imzcy ~]# |
二、 shell
: shell模块
使用 Ansible ad-hoc 命令行接口时(与使用 Playbooks 的情况相反),尤其注意 shell 引号的规则。 比如在下面的例子中,如果使用双引号 "echo $HOSTNAME" 会求出HOSTNAME变量在当前系统的值,而我们实际希望的是把这个命令传递,到其它机器执行!
1 2 3 4 5 6 7 8 9 10 |
[root@imzcy ~]# ansible WebServer -m shell -a "echo $HOSTNAME" 192.168.109.133 | SUCCESS | rc=0 >> imzcy [root@imzcy ~]# [root@imzcy ~]# ansible WebServer -m shell -a 'echo $HOSTNAME' 192.168.109.133 | SUCCESS | rc=0 >> app01 [root@imzcy ~]# |
三、 copy
: 文件传输模块
Ansible 能够以并行的方式同时 SCP 大量的文件到多台机器. 命令如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
[root@imzcy ~]# ansible WebServer -m copy -a "src=/root/sshpass-1.06.tar.gz dest=/tmp/" 192.168.109.133 | SUCCESS => { "changed": true, "checksum": "633652e2160819ac7c7e1a351327027d2faa4fd6", "dest": "/tmp/sshpass-1.06.tar.gz", "gid": 0, "group": "root", "md5sum": "f59695e3b9761fb51be7d795819421f9", "mode": "0644", "owner": "root", "secontext": "unconfined_u:object_r:admin_home_t:s0", "size": 112205, "src": "/root/.ansible/tmp/ansible-tmp-1539181428.79-9294133749568/source", "state": "file", "uid": 0 } [root@imzcy ~]# [root@imzcy ~]# ansible WebServer -a "ls /tmp" 192.168.109.133 | SUCCESS | rc=0 >> ansible_ogstQ5 sshpass-1.06.tar.gz [root@imzcy ~]# |
四、 file
: 修改文件属性
使用 file 模块可以做到修改文件的属主和权限,(在这里可替换为 copy 模块,是等效的):
4.1、修改WebServer组下面所有服务器下/root/file.txt文件的权限及对应属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[root@imzcy ~]# ansible WebServer -m file -a "dest=/root/file.txt mode=600 owner=nobody group=nobody" 192.168.109.133 | SUCCESS => { "changed": true, "gid": 99, "group": "nobody", "mode": "0600", "owner": "nobody", "path": "/root/file.txt", "secontext": "unconfined_u:object_r:admin_home_t:s0", "size": 0, "state": "file", "uid": 99 } [root@imzcy ~]# |
4.2、使用 file 模块也可以创建目录,与执行 mkdir -p 效果类似
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[root@imzcy ~]# ansible WebServer -m file -a "dest=/root/aa/bb mode=755 owner=root group=root state=directory" 192.168.109.133 | SUCCESS => { "changed": true, "gid": 0, "group": "root", "mode": "0755", "owner": "root", "path": "/root/aa/bb", "secontext": "unconfined_u:object_r:admin_home_t:s0", "size": 6, "state": "directory", "uid": 0 } [root@imzcy ~]# |
4.3、删除目录(递归的删除)及删除文件
1 2 3 4 5 6 7 |
[root@imzcy ~]# ansible WebServer -m file -a "dest=/root/aa/bb state=absent" 192.168.109.133 | SUCCESS => { "changed": true, "path": "/root/aa/bb", "state": "absent" } [root@imzcy ~]# |
五、 yum
: 管理软件包
Ansible 提供对 yum 和 apt 的支持.这里是关于 yum 的示例。
5.1、确认一个软件包已经安装,但不去升级它(不存在的包会被安装)
1 2 3 4 5 6 7 8 9 10 |
[root@imzcy ~]# ansible WebServer -m yum -a "name=tree state=present" 192.168.109.133 | SUCCESS => { "changed": true, "msg": "", "rc": 0, "results": [ "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * base: mirrors.aliyun.com\n * extras: mirrors.aliyun.com\n * updates: ftp.sjtu.edu.cn\nResolving Dependencies\n--> Running transaction check\n---> Package tree.x86_64 0:1.6.0-10.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n tree x86_64 1.6.0-10.el7 base 46 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package\n\nTotal download size: 46 k\nInstalled size: 87 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : tree-1.6.0-10.el7.x86_64 1/1 \n Verifying : tree-1.6.0-10.el7.x86_64 1/1 \n\nInstalled:\n tree.x86_64 0:1.6.0-10.el7 \n\nComplete!\n" ] } [root@imzcy ~]# |
5.2、确认一个软件包的安装版本(如果目前软件包版本低于指定版本,会被更新!)
1 2 3 4 5 6 7 8 9 10 |
[root@imzcy ~]# ansible WebServer -m yum -a "name=tree-1.6.0 state=present" 192.168.109.133 | SUCCESS => { "changed": false, "msg": "", "rc": 0, "results": [ "tree-1.6.0-10.el7.x86_64 providing tree-1.6.0 is already installed" ] } [root@imzcy ~]# |
5.3、确认一个软件包还没有安装(已存在的软件包会被卸载,包括其依赖的包也会被卸载)
1 2 3 4 5 6 7 8 9 10 |
[root@imzcy ~]# ansible WebServer -m yum -a "name=tree state=absent" 192.168.109.133 | SUCCESS => { "changed": true, "msg": "", "rc": 0, "results": [ "已加载插件:fastestmirror\n正在解决依赖关系\n--> 正在检查事务\n---> 软件包 tree.x86_64.0.1.6.0-10.el7 将被 删除\n--> 解决依赖关系完成\n\n依赖关系解决\n\n================================================================================\n Package 架构 版本 源 大小\n================================================================================\n正在删除:\n tree x86_64 1.6.0-10.el7 @base 87 k\n\n事务概要\n================================================================================\n移除 1 软件包\n\n安装大小:87 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n 正在删除 : tree-1.6.0-10.el7.x86_64 1/1 \n 验证中 : tree-1.6.0-10.el7.x86_64 1/1 \n\n删除:\n tree.x86_64 0:1.6.0-10.el7 \n\n完毕!\n" ] } [root@imzcy ~]# |
六、 user
: 用户和组
使用 user 模块可以方便的创建账户,删除账户,或是管理现有的账户!
需要注意的是:使用user模块指定用户的密码时,不能使用明文密码!!!因为它是直接将你设置的密码写入到/etc/shadow文件对应用户第二字段那个位置的。由于/etc/shadow文件本身保存的都是加密后的密码,所以你ssh连接的话会一直报(Permission denied, please try again.)这个错误的,再到被连接服务器上查看ssh日志文件,相应记录都显示为(authentication failure.)。。所以我们这里使用python的passlib这个模块来创建加密的密码。
6.1、yum安装epel源,随后安装pip工具并更新它
1 2 3 |
[root@imzcy ~]# yum -y install epel-release [root@imzcy ~]# yum -y install python-pip [root@imzcy ~]# pip install --upgrade pip |
6.2、使用pip工具安装passlib模块
我这里提示已经存在1.6.5版本的passlib模块(不知道什么时候装过),所以pip没有联网安装。
1 2 3 |
[root@imzcy ~]# pip install passlib Requirement already satisfied: passlib in /usr/lib/python2.7/site-packages (1.6.5) [root@imzcy ~]# |
但是需要注意的是,我这边测试使用1.6.5版本的passlib创建加密密码时会有报错(AttributeError: type object 'sha512_crypt' has no attribute 'using'),所以如果之前已经安装过这个版本的,一定要要升级一下(我这边升级完后的版本是passlib-1.7.1 ,测试可以正常创建加密密码)!
1 |
[root@imzcy ~]# pip install --upgrade passlib |
6.3、创建加密密码(执行命令后,根据提示输入要加密的密码即可)
1 2 3 4 |
[root@imzcy ~]# python -c "from passlib.hash import sha512_crypt; import getpass; print(sha512_crypt.using(rounds=5000).hash(getpass.getpass()))" Password: $6$GitCjhgIh06zT3qB$57XYaKg/PeNS6JpGyF9Gh4cx.yrR/1zIqG5Ib7lSTfgzX7n6mPhhe3f/V5kMqSk28pgT6GOlPwoD4BSm5yOwL. [root@imzcy ~]# |
6.4、使用 user
模块创建用户
这里需要注意的是,因为生成的加密密码中,包含$符号。所以不能直接使用,需要使用\转义。如下所示,共有三处需要修改的地方!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[root@imzcy ~]# ansible WebServer -m user -a "name=zhang password='\$6\$uH/rLCpN.6dgaLDp\$P/XitmmM9/jqi9i5LXAS0l44l5ah4gLeRKnV8vVkum1sVh5THut87ThZNhvWBk1YWkCy5.fZSnD0THqn1IVKw.'" 192.168.109.133 | SUCCESS => { "append": false, "changed": false, "comment": "", "group": 1004, "home": "/home/zhang", "move_home": false, "name": "zhang", "password": "NOT_LOGGING_PASSWORD", "shell": "/bin/bash", "state": "present", "uid": 1004 } [root@imzcy ~]# |
6.5、使用上面创建的用户测试ssh连接正常
1 2 3 4 5 6 7 8 |
[root@imzcy ~]# ssh zhang@192.168.109.133 zhang@192.168.109.133's password: Last login: Fri Oct 19 22:56:22 2018 from 192.168.109.135 [zhang@app01 ~]$ [zhang@app01 ~]$ exit 登出 Connection to 192.168.109.133 closed. [root@imzcy ~]# |
6.6、如果ssh连接不过去,提示Permission denied, please try again.的话,那么可以检查下对应服务器/etc/shadow文件创建的用户那行第二字段显示的密码,和上面python生成的加密密码是否完全一致,如果不一样,调整好命令重新创建即可。
1 2 3 4 5 |
[root@imzcy ~]# ansible WebServer -m shell -a "grep zhang /etc/shadow" 192.168.109.133 | SUCCESS | rc=0 >> zhangsan:zhangsan:17822:0:99999:7::: zhang:$6$uH/rLCpN.6dgaLDp$P/XitmmM9/jqi9i5LXAS0l44l5ah4gLeRKnV8vVkum1sVh5THut87ThZNhvWBk1YWkCy5.fZSnD0THqn1IVKw.:17823:0:99999:7::: [root@imzcy ~]# |
更多 user
模块的其他共用(包括对组和组成员关系的操作),请参考此链接:
1 |
http://www.ansible.com.cn/docs/modules.html |
七、 git
: 加载源码
测试下来,它好像只会从github将源码下载下来。后续编译安装什么的还需要另行操作!
1 2 3 4 5 6 7 |
[root@imzcy ~]# ansible WebServer -m git -a "repo=https://github.com/nginx/nginx-releases.git dest=/opt/nginx version=HEAD" 192.168.109.133 | SUCCESS => { "after": "f01c6309faeddd6cb719419376cb61c4da08b3e6", "before": null, "changed": true } [root@imzcy ~]# |
因为Ansible 模块可通知到 change handlers ,所以当源码被更新时,我们可以告知 Ansible 这个信息,并执行指定的任务, 比如直接通过 git 部署 Perl/Python/PHP/Ruby, 部署完成后重启 apache。
八、 service
: 管理服务
8.1、确认某个服务在所有的webservers上都已经启动
1 |
[root@imzcy ~]# ansible WebServer -m service -a "name=httpd state=started" |
8.2、在所有的webservers上重启某个服务(译者注:可能是确认已重启的状态?)
1 |
[root@imzcy ~]# ansible WebServer -m service -a "name=httpd state=restarted" |
8.3、确认某个服务已经停止
1 |
[root@imzcy ~]# ansible WebServer -m service -a "name=httpd state=stopped" |
九、 setup
: 收集关于远程主机的事实
在 playbooks 中有对于 Facts 做描述,它代表的是一个系统中已发现的变量.These can be used to implement conditional execution of tasks but also just to get ad-hoc information about your system。
9.1、可通过如下方式查看所有的 facts
1 |
[root@imzcy ~]# ansible WebServer -m setup |
9.2、我们也可以对这个命令的输出做过滤,只输出特定的一些 facts。如下只输出CPU信息
1 2 3 4 5 6 7 8 9 10 11 12 |
[root@imzcy ~]# ansible WebServer -m setup -a "filter=ansible_processor" 192.168.109.133 | SUCCESS => { "ansible_facts": { "ansible_processor": [ "0", "GenuineIntel", "Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz" ] }, "changed": false } [root@imzcy ~]# |
本文内容学习自 Ansible中文权威指南:
1 |
http://www.ansible.com.cn/docs/intro_adhoc.html |
本文第六节:使用user模块创建用户部分,使用python的passlib模块加密密码方法参考下面文章:
1 |
http://www.mamicode.com/info-detail-2348892.html |