金鱼哥说Ansible:Ansible临时命令这招功夫就应该要这样耍

别以为学会了 管理Ansible配置文件(文章链接地址)这内功心法,就可以去闯荡江湖各种装逼。有心法没招式也是寸步难行啊。

别和我说你想无招胜有招。金鱼哥说Ansible:Ansible临时命令这招功夫就应该要这样耍_第1张图片

1. 扎马步:Ad-Hoc

简介

Ad-Hoc 指的临时意思,就像在命令行写的shell命令就是临时命令,在文件中写的shell命令就是脚本 。

Ad-Hoc 就是在命令行直接执行的内容,主要用于临时命令使用场景。

(说这么多废话,就是在命令行上运行需要的命令嘛,扎马步都解释这么多。)

语法

ansible host-pattern -m module [-a ‘module arguments’] [-i inventory]

指令 匹配规则的主机清单 -m 模块名 选项

  • host-pattern是inventory中定义的主机或主机组,可以使用 “.” 或 “*” 或 “:” 等特殊字符的匹配型字符串,host-pattern是必须项,不可忽略
常用选项
--version 显示版本
-a 模块参数(如果有)
-m module 指定模块,默认为command
-v 详细过程 –vv -vvv更详细
--list-hosts 显示主机列表,可简写--list
-C, --check 检查,并不执行
-T, --timeout=TIMEOUT 执行命令的超时时间,默认10s
-u, --user=REMOTE_USER 执行远程执行的用户
-U, SUDO_USER, --sudo-user 指定sodu用户
-b, --become 代替旧版的sudo 切换
--become-method 提权的方法
-k, --ask-pass 提示连接密码,默认Key验证
-K,--ask-become-pass 提示使用sudo密码

金鱼哥说Ansible:Ansible临时命令这招功夫就应该要这样耍_第2张图片

2. 招式:模块

这个存放各种招式的地方,难道是传说中的藏经阁?

位置

Ansible模块存放位置:/usr/lib/python2.7/site-packages/ansible/modules # 在系统默认的python目录

(不同python版本位置有所不同。)

官网模块描述信息

https://docs.ansible.com/ansible/latest/user_guide/modules.html

https://docs.ansible.com/ansible/2.9/user_guide/modules_intro.html

官网模块分类信息

https://docs.ansible.com/ansible/latest/modules/modules_by_category.html # 最新版本

https://docs.ansible.com/ansible/2.9/modules/modules_by_category.html#modules-by-category # 2.9版本

帮助

ansible-doc -l 查看列表

ansible-doc modulename 查看模块帮助文件

怎么说好呢,还是要善用帮助,多help一下去理解,总有好处。
金鱼哥说Ansible:Ansible临时命令这招功夫就应该要这样耍_第3张图片

3. 基础招式:ansible的简单使用

别说了那么多有的没的,还是最喜欢看演示。

金鱼哥说Ansible:Ansible临时命令这招功夫就应该要这样耍_第4张图片

示范环境:

[student@servera ~]$ cat hosts 
servera
serverb

[webs]
servera
serverb

1.测试主机连通性

ansible -i hosts webs -m ping
servera | SUCCESS => {
     
    "changed": false, 
    "ping": "pong"
}
serverb | SUCCESS => {
     
    "changed": false, 
    "ping": "pong"
}

ansible webs -m ping
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not
match 'all'

 [WARNING]: Could not match supplied host pattern, ignoring: webs

  • -i inventory 主机清单文件,不加此选项,默认是在/etc/ansible/hosts,(说白了,会匹配配置文件。)

  • -m 指定模块

注意

  • 在使用Ansible之前,请在目标主机上保存fingerprint指纹否则会出现Please add this host’s fingerprint to your known_hosts的错误

  • 使用ssh 用户@目标主机连接一下,输入yes,保存下指纹即可

(别和我说这个都不会?你真不会?马上踢出山,之后让你回去尝试一下,不就是首次ssh过去时那段OOXX的提示嘛。)

2.执行uptime命令,查看返回结果

[student@servera ~]$ ansible -i hosts webs -m command -a "uptime" 
servera | CHANGED | rc=0 >>
 00:11:00 up  4:42,  1 user,  load average: 0.00, 0.01, 0.05

serverb | CHANGED | rc=0 >>
 00:11:00 up 14 min,  1 user,  load average: 0.00, 0.01, 0.05
  • command是执行命令模块

  • -a 是模块的参数

  • 可以把主机写在选项的最后面,增加可读性

3.查看内核版本号

[student@servera ~]$ ansible -i hosts -m command -a "uname -r" webs
serverb | CHANGED | rc=0 >>
4.18.0-80.el8.x86_64

servera | CHANGED | rc=0 >>
4.18.0-80.el8.x86_64

4.增加一个用户

[student@servera ~]$ ansible -i hosts -m command -a "useradd test" webs
servera | FAILED | rc=1 >>
useradd: Permission denied.
useradd: cannot lock /etc/passwd; try again later.non-zero return code

serverb | FAILED | rc=1 >>
useradd: Permission denied.
useradd: cannot lock /etc/passwd; try again later.non-zero return code 
[student@servera ~]$ ansible -i hosts -m command -a "whoami" webs
serverb | CHANGED | rc=0 >>
student

servera | CHANGED | rc=0 >>
student
[student@servera ~]$ ansible -i hosts -m command -a "whoami" webs -u root
servera | CHANGED | rc=0 >>
root

serverb | CHANGED | rc=0 >>
root
[student@servera ~]$ ansible -i hosts -m command -a "useradd test" webs -u root
servera | CHANGED | rc=0 >>

serverb | CHANGED | rc=0 >>

5. 注意事项

主控端若不设置被控端用户(–user REMOTE_USER),则被管控时,默认被控端会使用主控端当前的用户(演示使用的是student用户)来进行相关的任务操作,因此,若被控端没有主控端当前用户的时候(例如,serverb没有student用户),就会报错。

总结,要对使用用户进行合理规划并设置好对应的权限。

(总觉被人忽悠,基础招式,我早会了,快上大招吧。)
金鱼哥说Ansible:Ansible临时命令这招功夫就应该要这样耍_第5张图片

4. 各种真经:ansible的常用模块

2015年底270多个模块,2016年达到540个,2018年01月12日有1378个模块,2018年07月15日1852个模块,2019年05月25日(ansible 2.7.10)时2080个模块,2020年03月02日有3387个模块,虽然模块众多,但最常用的模块也就2,30个而已,针对特定业务只用10几个模块。

示范环境:

[root@servera ~]# cat hosts 
servera
serverb

[test]
servera
serverb

ping

功能:尝试连接到主机,验证并返回pong成功。

  • 对于Windows目标,请改用win_ping模块。

  • 不使用icmp协议,使用ssh协议。

例子:

# ansible servera -m ping -i hosts
servera | SUCCESS => {
     
    "changed": false, 
    "ping": "pong"                > 返回pong表明成功通讯
}

command

功能:在远程节点上执行命令

  • 变量 和操作符号 “<”, “>”, “|”, “;” and “&” 不能正常工作。如果需要使用,请使用shell模块

  • Ansible默认不指定模块时,将使用此模块。

shell

功能:在远程节点上执行命令。与command模块使用一致,但是,变量 和操作符号 “<”, “>”, “|”, “;” and “&” 能正常工作。

下面2个例子对比能清晰的表示出不同的地方:

[root@servera ~]# ansible servera -m command -a 'echo $RANDOM' -i hosts
servera | CHANGED | rc=0 >>
$RANDOM

[root@servera ~]# ansible servera -m shell -a 'echo $RANDOM' -i hosts
servera | CHANGED | rc=0 >>
7483
  • 定义在 ~/.bashrc 或 ~/.bash_profile 中的环境变量shell模块由于没有加载,所以无法识别;如果需要使用自定义的环境变量,就需要在最开始,执行加载自定义脚本的语句。
# ansible servera -m shell -a "df -h | awk '{print $5}'" -i hosts   # “$”不能正常工作 
servera | CHANGED | rc=0 >>	
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G  1.2G   39G   3% /
devtmpfs        475M     0  475M   0% /dev
tmpfs           496M     0  496M   0% /dev/shm
tmpfs           496M   13M  483M   3% /run
tmpfs           496M     0  496M   0% /sys/fs/cgroup
tmpfs           100M     0  100M   0% /run/user/0

复杂命令,即使使用shell也可能会失败。
解决办法:写到脚本时,copy到远程,执行,再把需要的结果拉回执行命令的机器。

# ansible servera -m shell -a "df -hT|sed '1d'|head -1" -i hosts   # "|"能正常工作

servera | CHANGED | rc=0 >>
/dev/vda1      xfs        40G  1.2G   39G   3% /

script

功能:把脚本复制到远程节点后,在远程节点本地运行脚本。

给定的脚本将通过远程节点上的shell环境进行处理。

这个模块在远程系统上不需要python,就像原始脚本一样。

以上面不能正常工作(df -h | awk ‘{print $5}’)的例子来测试:

# cat test.sh 
#!/bin/bash
USE=`df -h | awk '{print $5}'`
echo $USE

# ansible servera -m script -a "/root/test.sh" -i hosts
servera | CHANGED => {
     
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to servera closed.\r\n", 
    "stderr_lines": [
        "Shared connection to servera closed."
    ], 
    "stdout": "Use% 3% 0% 0% 3% 0% 0%\r\n", 
    "stdout_lines": [
        "Use% 3% 0% 0% 3% 0% 0%"
    ]
}

copy

功能:复制文件或目录到远程节点。默认会覆盖目标文件

backup: 在覆盖之前将原文件备份,备份文件包含时间信息。有两个选项:yes|no

content: 用于替代"src",可以直接设定指定文件的内容,相当于echo 重定向内容到文件

dest: 必选项。要将源文件复制到的远程主机的绝对路径,如果源文件是一个目录,那么该路径也必须是个目录

directory_mode: 递归的设定目录的权限,默认为系统默认权限

force: 如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes

src: 要复制到远程主机的文件在本地的地址,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用 “/” 来结尾,则只复制目录里的内容,如果没有使用 “/” 来结尾,则包含目录在内的整个内容全部复制,类似于rsync

# ansible -i hosts servera -m copy -a 'src=/root/test.sh dest=/root backup=yes'
servera | CHANGED => {
     
    "changed": true, 
    "checksum": "cc0d01995c45d2dbaa45bc4035d45f02ef71b473", 
    "dest": "/root/test.sh", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "5b63433c46dc57d4d730361c5390fc6d", 
    "mode": "0644", 
    "owner": "root", 
    "secontext": "system_u:object_r:admin_home_t:s0", 
    "size": 53, 
    "src": "/root/.ansible/tmp/ansible-tmp-1599190670.37-70286513836843/source", 
    "state": "file", 
    "uid": 0
}

# ansible -i hosts servera -m command -a 'ls'
servera | CHANGED | rc=0 >>
anaconda-ks.cfg
original-ks.cfg
test.sh

复制目录时,斜线不要写

# ansible -i hosts servera -m copy -a 'src=/root/abc  dest=/root'
servera | CHANGED => {
     
    "changed": true, 	
    "checksum": "4e1243bd22c66e76c2ba9eddc1f91394e57f9f83", 
    "dest": "/root/abc/test.txt", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "d8e8fca2dc0f896fd7cb4cb0031ba249", 
    "mode": "0644", 
    "owner": "root", 
    "secontext": "system_u:object_r:admin_home_t:s0", 
    "size": 5, 
    "src": "/root/.ansible/tmp/ansible-tmp-1599190972.15-137237299762028/source", 
    "state": "file", 
    "uid": 0
}

根据内容生成文件,相当于echo abc123 > /root/123.txt

# ansible -i hosts servera -m copy -a 'content="abc123" dest=/root/123.txt'
servera | CHANGED => {
     
    "changed": true, 
    "checksum": "6367c48dd193d56ea7b0baad25b19455e529f5ee", 
    "dest": "/root/123.txt", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "e99a18c428cb38d5f260853678922e03", 
    "mode": "0644", 
    "owner": "root", 
    "secontext": "system_u:object_r:admin_home_t:s0", 
    "size": 6, 
    "src": "/root/.ansible/tmp/ansible-tmp-1599191087.61-13911557669155/source", 
    "state": "file", 
    "uid": 0
}

# ansible -i hosts servera -m command -a 'cat /root/123.txt'
servera | CHANGED | rc=0 >>
abc123

file

功能: 设置远程节点的文件的文件属性

force: 需要在两种情况下强制创建软链接,一种是源文件不存在但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no

group: 定义文件/目录的属组

mode: 定义文件/目录的权限

owner: 定义文件/目录的属主

path: 必选项,定义文件/目录的路径

recurse: 递归的设置文件的属性,只对目录有效

src: 要被链接的源文件的路径,只应用于state=link的情况

dest: 被链接到的路径,只应用于state=link的情况

state: 操作方法

directory:如果目录不存在,创建目录

file:即使文件不存在,也不会被创建

link:创建软链接

hard:创建硬链接

touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间

absent:删除目录、文件或者取消链接文件。相当于rm -rf

创建空文件,类似于touch

ansible -i hosts servera -m file -a 'path=/root/filemodule.txt state=touch mode=0666 owner=ftp'
servera | CHANGED => {
     
    "changed": true, 
    "dest": "/root/filemodule.txt", 
    "gid": 0, 
    "group": "root", 
    "mode": "0666", 
    "owner": "ftp", 
    "secontext": "unconfined_u:object_r:admin_home_t:s0", 
    "size": 0, 
    "state": "file", 
    "uid": 14
}

创建空目录, 类似于mkdir -p

ansible -i hosts servera -m file -a 'path=/root/filemodules state=directory mode=0666 owner=ftp' 
servera | CHANGED => {
     
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0666", 
    "owner": "ftp", 
    "path": "/root/filemodules", 
    "secontext": "unconfined_u:object_r:admin_home_t:s0", 
    "size": 6, 
    "state": "directory", 
    "uid": 14
}

创建软链接

 ansible -i hosts servera -m file -a 'path=/root/link.txt state=link src=filemodule.txt'
servera | CHANGED => {
     
    "changed": true, 
    "dest": "/root/link.txt", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "secontext": "unconfined_u:object_r:admin_home_t:s0", 
    "size": 14, 
    "src": "filemodule.txt", 
    "state": "link", 
    "uid": 0
}

cron

功能:管理计划任务

backup: 对远程主机上的原任务计划内容修改之前做备份

cron_file: 如果指定该选项,则用该文件替换远程主机上的cron.d目录下的用户的任务计划

day: 日(1-31,/2,……)

hour: 小时(0-23,/2,……)

minute: 分钟(0-59,/2,……)

month: 月(1-12,/2,……)

weekday: 周(0-7,*,……)

job: 要执行的任务,依赖于state=present

name: 该任务的描述

special_time: 指定什么时候执行,参数:reboot,yearly,annually,monthly,weekly,daily,hourly

state: 确认该任务计划是创建还是删除

user: 以哪个用户的身份执行

创建计划任务

# ansible -i hosts servera -m cron -a 'name="test cron job" minute=*/10 job="/usr/bin/wall hello world"'
servera | CHANGED => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "test cron job"
    ]
}

# ansible -i hosts servera -a 'crontab -l'
servera | CHANGED | rc=0 >>
#Ansible: test cron job
*/10 * * * * /usr/bin/wall hello world

禁用某个计划任务

正确的写法:必须完整的写完,包括name等属性

# ansible -i hosts servera -m cron -a 'disabled=yes name="test cron job" minute=*/10 job="/usr/bin/wall hello world"'
servera | CHANGED => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "test cron job"
    ]
}

# ansible -i hosts servera -m cron -a 'disabled=yes name="test cron job" job="/usr/bin/wall hello world"'
servera | CHANGED => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "test cron job"
    ]
}

# ansible -i hosts servera -a 'crontab -l'
servera | CHANGED | rc=0 >>
#Ansible: test cron job
#* * * * * /usr/bin/wall hello world

删除计划任务

# ansible -i hosts servera -m cron -a 'state=absent name="test cron job"'
servera | CHANGED => {
    "changed": true, 
    "envs": [], 
    "jobs": []
}

# ansible -i hosts servera -a 'crontab -l'
servera | CHANGED | rc=0 >>

yum

功能:使用yum包管理器来管理软件包

config_file: yum的配置文件

disable_gpg_check: 关闭gpg_check

disablerepo: 不启用某个源

enablerepo: 启用某个源

name: 要进行操作的软件包的名字,也可以传递一个url或者一个本地的rpm包的路径

state: Whether to install (‘present’ or ‘installed’, ‘latest’), or remove (‘absent’ or ‘removed’) a package.

​ (可选值: present, installed, latest, absent, removed) [Default: present]

# ansible -i hosts servera -m yum -a 'name=tree state=latest'
servera | CHANGED => {
     
    "ansible_facts": {
     
        "pkg_mgr": "yum"
    }, 
    "changed": true, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: langpacks, search-disabled-repos\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           rhel--server-dvd         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"
    ]
}

# ansible -i hosts servera -a 'rpm -q tree'
servera | CHANGED | rc=0 >>
tree-1.6.0-10.el7.x86_64

service

功能:配置管理服务

arguments: 给命令行提供一些选项 。可以使用别名 args

enabled: 是否开机启动 yes|no

name:必选项,服务名称

pattern: 定义一个模式,如果通过status指令来查看服务的状态时,没有响应,就会通过ps指令在进程中根据该模式进行查找,如果匹配到,则认为该服务依然在运行

runlevel: 运行级别

sleep:如果执行了restarted,在则stop和start之间沉睡几秒钟

state:对当前服务执行启动,停止、重启、重新加载等操作(started,stopped,restarted,reloaded)

# ansible -i hosts servera -m yum -a 'name=httpd state=latest'
# ansible -i hosts servera -m service -a 'name=httpd state=started'  > 一次只能操作一个服务
servera | CHANGED => {
     
    "changed": true, 
    "name": "httpd", 
    "state": "started", 
    "status": {
     
        "ActiveEnterTimestampMonotonic": "0", 
        "ActiveExitTimestampMonotonic": "0", 
        "ActiveState": "inactive",
        ............

user

功能:管理用户账号

很多选项,与useradd这类系统命令差不多

name: 用户名,可以使用别名user

范例:

创建用户

# ansible -i hosts servera -m user -a 'name=hunk shell=/sbin/nologin system=yes comment="name is hunk"'
servera | CHANGED => {
     
    "changed": true, 
    "comment": "name is hunk", 
    "create_home": true, 
    "group": 993, 
    "home": "/home/hunk", 
    "name": "hunk", 
    "shell": "/sbin/nologin", 
    "state": "present", 
    "system": true, 
    "uid": 996
}

删除用户

# ansible -i hosts servera -m user -a 'name=hunk state=absent'
servera | CHANGED => {
     
    "changed": true, 
    "force": false, 
    "name": "hunk", 
    "remove": false, 
    "state": "absent"
}

修改用户指定信息

# ansible -i hosts servera -m user -a 'name=hunk state=present comment=" hunk is my"'

remove:删除用户时一并删除用户家目录,需要与state=absent一起使用

# ansible -i hosts servera -m user -a 'name=hunk state=absent remove=yes'
servera | CHANGED => {
     
    "changed": true, 
    "force": false, 
    "name": "hunk", 
    "remove": true, 
    "state": "absent", 
    "stderr": "userdel: hunk mail spool (/var/spool/mail/hunk) not found\n", 
    "stderr_lines": [
        "userdel: hunk mail spool (/var/spool/mail/hunk) not found"
    ]
}

state: 操作方法。(present , absent)

groups: 添加辅助组

group: 指定用户的主组

以下这个例子注意看,group和groups所代表的含义不同。

  - name: add user
    user: name={
     {
      username }} group=ftp groups={
     {
      groupname }}

group

功能:添加组或删除组

group模块请求的是groupadd, groupdel, groupmod 三个指令

用法都是差不多的。

gid: 组id

name: 组名称

state: Present创建Absent删除

system: yes|no 是否为系统组

# ansible -i hosts servera -m group -a "name=abc state=present gid=1111"
servera | CHANGED => {
     
    "changed": true, 
    "gid": 1111, 
    "name": "abc", 
    "state": "present", 
    "system": false
}

# ansible -i hosts servera -m group -a "name=abc state=absent"
servera | CHANGED => {
     
    "changed": true, 
    "name": "abc", 
    "state": "absent"
}

总结

遇到不知道如何使用的模块,先 ansible-doc 一下,里面有各种使用选项的说明,同时留意下面的example,这些都是辅助你日后使用的好习惯。

多练习,多记忆,多发现。

(有哥们说,什么九阴真经,九阳真经都不适合他,他要去练OO葵XX花宝典。)
金鱼哥说Ansible:Ansible临时命令这招功夫就应该要这样耍_第6张图片

你可能感兴趣的:(金鱼哥说Ansible,linux,运维,云计算,自动化)