python:zabbix编程、ansible基础、ansible编程、ansible模块开发

Zabbix api概述
• Zabbix API允许你以编程方式检索和修改Zabbix的配置,并提供对历史数据的访问。它广泛用于:
– 创建新的应用程序以使用Zabbix
– 将Zabbix与第三方软件集成
– 自动执行常规任务

JSON-RPC
• Zabbix API是基于Web的API,作为Web前端的一部分提供。它使用JSON-RPC 2.0协议,这意味着两件事:
– 该API包含一组独立的方法
– 客户端和API之间的请求和响应使用JSON格式进行编码

API结构
• Zabbix API包含许多方法,这些方法都名义上分组为单组的API
• 每个方法执行一个特定任务。例如,方法host.create 隶属于 host 这个API ,用于创建新主机
• 历史上,API有时被称为“类”
• 大多数API至少包含四种方法: get,、create、update 和 delete ,分别是检索、创建、更新和删除数据。但是某些API提供一套完全不同的一组方法。

执行请求
• 设置前端后,,就可以使用远程HTTP请求来调用API。为此,需要向api_jsonrpc.php 位于前端目录中的文件发送HTTP POST请求。
• 请求的 Content-Type 头部必须设置为以下值之一:
– application/json-rpc
– application/json
– application/jsonrequest

官方文档页:https://www.zabbix.com/documentation/3.4/zh/manual
这里演示的环境路径是:/var/www/html/
那么zabbix api地址是:http://192.168.2.55/api_jsonrpc.php

通过zabbix提供的API接口,就可以使用python与其交互

import requests
import json

url = 'http://192.168.2.55/api_jsonrpc.php'
headers = {'Content-Type': 'application/json-rpc'}
###################################
# 获取zabbix api版本信息
# data = {
#     "jsonrpc": "2.0",  # zabbix固定值
#     "method": "apiinfo.version",   # 官方手册页上查询到的
#     "params": [],  # 参数
#     "id": 101  # 作业ID,随便指定一个值即可
# }
###################################
#工作流程
# • 在访问大多数Zabbix中的任何数据之前,需要登录并获取身份验证令牌
# • 取得令牌后,访问其他数据只要出示该令牌即可,不需要再进行身份验证
# • 通过zabbix api提供的各种方法实现数据的检索、项目的创建等
# 获取令牌,使用 user.login 方法登录并获取身份验证令牌
#jsonrpc - API使用的JSON-RPC协议的版本; Zabbix API实现JSON-RPC版本2.0
#• method - 调用的API方法
#• params - 将被传递给API方法的参数
#• id - 请求的任意标识符
#• auth -用户认证令牌; 因为我们还没有一个,它的设置None
#• 如果你正确提供了凭据,API返回的响应将包含用户
身份验证令牌
# data = {
#     "jsonrpc": "2.0",
#     "method": "user.login",
#     "params": {
#         "user": "admin",
#         "password": "123456"
#     },
#     "id": 1
# }
# 7f3dd136e378e30935a83ae0ceea8099
##################################
#检索主机
#• 有一个有效的用户身份验证令牌,可以用来访问Zabbix中的数据
#• 使用 host.get 方法检索所有已配置主机的ID、主机名和接口。auth 属性设置为获得的身份验证令牌
# 获取主机信息
# data = {
#     "jsonrpc": "2.0",
#     "method": "host.get",
#     "params": {
#         "output": "extend",
#         "filter": {
#             # "host": [
#             #     "Zabbix server",
#             #     "Linux server"
#             # ]
#         }
#     },
#     "auth": "7f3dd136e378e30935a83ae0ceea8099",
#     "id": 1
# }
###################################
# 删除主机
# data = {
#     "jsonrpc": "2.0",
#     "method": "host.delete",
#     "params": [
#         "10255",
#     ],
#     "auth": "7f3dd136e378e30935a83ae0ceea8099a",
#     "id": 1
# }
###################################
# 取出Linux Servers组号
# data = {
#     "jsonrpc": "2.0",
#     "method": "hostgroup.get",
#     "params": {
#         "output": "extend",
#         "filter": {
#             "name": [
#                 "Linux servers"
#             ]
#         }
#     },
#     "auth": "7f3dd136e378e30935a83ae0ceea8099",
#     "id": 1
# }
# groupid: 2
###################################
# 取出Template OS Linux模板的ID
# data = {
#     "jsonrpc": "2.0",
#     "method": "template.get",
#     "params": {
#         "output": "extend",
#         "filter": {
#             "host": [
#                 "Template OS Linux",
#             ]
#         }
#     },
#     "auth": "7f3dd136e378e30935a83ae0ceea8099",
#     "id": 1
# }
# 'templateid': '10001'
###################################
# 创建主机
data = {
    "jsonrpc": "2.0",
    "method": "host.create",
    "params": {
        "host": "nsd1812web1",
        "interfaces": [
            {
                "type": 1,
                "main": 1,
                "useip": 1,
                "ip": "192.168.4.2",
                "dns": "",
                "port": "10050"
            }
        ],
        "groups": [
            {
                "groupid": "2"
            }
        ],
        "templates": [
            {
                "templateid": "10001"
            }
        ],
        "inventory_mode": 0,
        "inventory": {
            "macaddress_a": "123456789012",
            "macaddress_b": "fsdalkjfsdaljfdsa"
        }
    },
    "auth": "7f3dd136e378e30935a83ae0ceea8099",
    "id": 1
}

###################################
r = requests.post(url, data=json.dumps(data), headers=headers)
print(r.json())

############################################################################
Ansible简介
• Ansible是一个配置管理和配置工具,类似于Chef,Puppet或Salt
• 这是一款很简单也很容易入门的部署工具,它使用SSH连接到服务器并运行配置好的任务
• 服务器上不用安装任何多余的软件,只需要开启ssh,所有工作都交给client端的ansible负责

准备环境,启动三台虚拟机:

node4.tedu.cn192.168.4.4/24
node5.tedu.cn192.168.4.5/24
node6.tedu.cn192.168.4.6/24

名称解析(在192.168.4.254主机上配置,并将配置后的/etc/hosts文件拷贝至以上3台主机对应的目录):

[root@room9pc01 ~]# for i in {4..6}
> do
> echo -e "192.168.4.$i\tnode$i.tedu.cn\tnode$i" >>/etc/hosts
> done

收集主机密钥:

[root@room9pc01 ~]# ssh-keyscan 192.168.4.{4..6} node{4..6} node{4..6}.tedu.cn >> ~/.ssh/known_hosts

安装ansible

[root@room9pc01 ansible_pkg]# ls
ansible-2.7.2.tar.gz
asn1crypto-0.24.0-py2.py3-none-any.whl
bcrypt-3.1.4-cp36-cp36m-manylinux1_x86_64.whl
cffi-1.11.5-cp36-cp36m-manylinux1_x86_64.whl
cryptography-2.4.2-cp34-abi3-manylinux1_x86_64.whl
idna-2.7-py2.py3-none-any.whl
Jinja2-2.10-py2.py3-none-any.whl
MarkupSafe-1.1.0-cp36-cp36m-manylinux1_x86_64.whl
paramiko-2.4.2-py2.py3-none-any.whl
pyasn1-0.4.4-py2.py3-none-any.whl
pycparser-2.19.tar.gz
PyNaCl-1.3.0-cp34-abi3-manylinux1_x86_64.whl
PyYAML-3.13.tar.gz
setuptools-40.6.2-py2.py3-none-any.whl
six-1.11.0-py2.py3-none-any.whl
[root@room9pc01 ansible_pkg]# pip3 install *

配置ansible的基础应用环境

[root@room9pc01 ~]# mkdir myansible
[root@room9pc01 ~]# cd myansible
[root@room9pc01 myansible]# vim ansible.cfg
[defaults]
inventory = hosts
remote_user = root
[root@room9pc01 myansible]# vim hosts
[dbservers]
node4.tedu.cn

[webservers]
node5.tedu.cn
node6.tedu.cn
[root@room9pc01 myansible]# ansible all -m ping -k

使用playbook
• Playbooks是Ansible的配置、部署、编排语言。
• 它们可以被描述为一个需要希望远程主机执行命令的方案,或者一组程序运行的命令集合
• Playbook由一到多个Play组成
• 每个play可以指定哪些主机执行哪些任务
• 执行任务一般通过调用模块来实现

Yaml简介
• Playbooks的格式是YAML
• 语法做到最小化,意在避免 playbooks 成为一种编程语言或是脚本
• 使用 YAML 是因为它像 XML 或 JSON 是一种利于人们读写的数据格式

Yaml语法
• 每一个 YAML 文件都是从一个列表开始
• 列表中的每一项都是一个键值对, 通常它们被称为一个“哈希 或“字典”
• 所有的 YAML 文件开始行都应该是 —。这是 YAML 格式的一部分,表明一个文件的开始
• 列表中的所有成员都开始于相同的缩进级别,并且使用一个 "- " 作为开头(一个横杠和一个空格)
• 一个字典是由一个简单的 键: 值 的形式组成(冒号后面必须是一个空格)

配置VIM
• Yaml的缩进不能使用tab键
• 建议缩进为两个空格
• 为了实现yml文件按tab键缩进两个空格,可以按以下方式对vim进行定制

[root@room9pc01 myansible]# vim ~/.vimrc
set ai
set ts=4
set et
set encoding=utf8
autocmd FileType yaml setlocal sw=2 ts=2 et ai

创建playbook,实现免密登陆

[root@room9pc01 myansible]# ansible-doc autorized_key
[root@room9pc01 myansible]# ssh-keygen		//生成密钥
[root@room9pc01 myansible]# vim auth.yml
---
- name: user auth key
  hosts: all
  tasks:
    - name: upload root pub key
      authorized_key:
        user: root
        state: present
        key: "{{ lookup('file', '/root/.ssh/id_rsa.pub') }}"
[root@room9pc01 myansible]# ansible-playbook --syntax-check auth.yml		//检查yml脚本语法

playbook: auth.yml
[root@room9pc01 myansible]# ansible-playbook auth.yml -k

通过playbook配置yum

[root@room9pc01 myansible]# mkdir files
[root@room9pc01 myansible]# vim files/server.repo
[server]
name= server
baseurl=ftp://192.168.4.254/rhel7
enabled=1
gpgcheck=0
[root@room9pc01 myansible]# vim yum.yml
---
- name: upload yum repo file
  hosts: all
  tasks:
    - name: upload server.repo
      copy:
        src: files/server.repo
        dest: /etc/yum.repos.d/server.repo
[root@room9pc01 myansible]# ansible-playbook --syntax-check yum.yml
[root@room9pc01 myansible]# ansible-playbook yum.yml
[root@room9pc01 myansible]# ansible dbservers -m yum -a "list=mariadb-server"		//检查web服务器是否安装了mariadb-server

案例:通过playbook在dbservers上配置mariadb,在webservers上配置apache

[root@room9pc01 myansible]# vim lamp.yml
---
- name: configure dbservers
  hosts: dbservers
  tasks:
    - name: install mariadb
      yum:
        name: mariadb-server
        state: present
    - name: start mariadb
      service:
        name: mariadb
        state: started
        enabled: yes

- name: configure webservers
  hosts: webservers
  tasks:
    - name: install apache
      yum:
        name: [httpd, php, php-mysql]
        state: latest
    - name: start httpd
      service:
        name: httpd
        state: started
        enabled: yes
[root@room9pc01 myansible]# ansible-playbook --syntax-check lamp.yml
[root@room9pc01 myansible]# ansible-playbook lamp.yml

#####################################################################################
ansible编程基础

ansible python api

官方手册页:https://docs.ansible.com/ ->Ansible Documentation -> 搜索python api。把python api example中的代码复制粘贴到adhoc.py

命名元组
• 命名元组与普通元组一样,有相同的表现特征,其添加的功能就是可以根据名称引用元组中的项
• collections 模块提供了namedtuple()函数,用于创建自定义的元组数据类型

>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y', 'z'])
>>> p1 = Point(10, 20, 25)
>>> len(p1)
3
>>> p1[0]
10
>>> p1[1:]
(20, 25)
>>> p1.x
10
>>> p1.y
20
>>> p1.z
25

Ansible常用属性
• from ansible.parsing.dataloader import DataLoader
– 用来加载解析yaml文件或JSON内容,并且支持vault的解密
• from ansible.vars.manager import VariableManager
– 管理变量的类,包括主机,组,扩展等变量
• from ansible.inventory.manager import InventoryManager
– 用于创建主机清单,主机清单的源采用配置文件或是逗号分开主机名字符串
• from ansible.playbook.play import Play
– 用于创建play对象,能够通过play_source提供的信息自动创建任务对象
• from ansible.executor.task_queue_manager import TaskQueueManager
– 用于处理进程池中的多进程。队列管理器负责加载play策略插件,以便在选定的主机上执行任务
• import ansible.constants as C
– 存储ansible一些预定义变量

ad-hoc模式
使用TaskQueueManager
• 创建TaskQueueManager实例,用于管理子进程、通过主机列表和任务建立对象
• TaskQueueManager需要主机清单参数、主机变量参数、连接选项等
• 不管是执行ad-hoc还是playbook都需要以下模块

#!/usr/bin/env python
import	shutil
from	collections	import	namedtuple
from	ansible.parsing.dataloader import	DataLoader
from	ansible.vars.manager import	VariableManager
from	ansible.inventory.manager import	InventoryManager
from	ansible.playbook.play import	Play
from	ansible.executor.task_queue_manager import	TaskQueueManager
import	ansible.constants as	C

play_source =		dict(
name	=	"Ansible Play",
hosts	=	'localhost',
gather_facts =	'no',
tasks	=	[
dict(action=dict(module='shell',	args='mkdir /tmp/mytestdir'),	
register='shell_out'),
]
)
play	=	Play().load(play_source,	variable_manager=variable_manager,	
loader=loader)

设置参数
• 运行命令时有很多参数要指定,这些参往往很长,可
以先把它们提前定义出来

Options	=	namedtuple('Options',	['connection',	'module_path',	'forks',	
'become',	'become_method',	'become_user',	'check',	'diff'])
options	=	Options(connection='local',	module_path=[''],	forks=10,	
become=None,	become_method=None,	become_user=None,	
check=False,	diff=False)
loader	=	DataLoader()
passwords	=	dict(vault_pass='secret')
inventory	=	InventoryManager(loader=loader,	sources='localhost,')
variable_manager =	VariableManager(loader=loader,	
inventory=inventory)

######################################################################

[root@room9pc01 day03]# vim adhoc.py
import shutil
from collections import namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars.manager import VariableManager
from ansible.inventory.manager import InventoryManager
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
import ansible.constants as C

# since API is constructed for CLI it expects certain options to always be set, named tuple 'fakes' the args parsing options object
# 此处定义了执行ansible命令时的选项
# connection定义连接方式,local表示本机,ssh表示ssh,smart表示自动选择
# module_path指定自定义的模块位置
# forks指定启动的进程数目
# become:如果使用普通用户远程登陆服务器,那么切换成其他用户该怎么切换
# check: 不真正执行操作,而是预言操作的结果
# diff 显示修改小文件前后的变化
Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'diff'])
options = Options(connection='ssh', module_path=['/to/mymodules'], forks=10, become=None, become_method=None, become_user=None, check=False, diff=False)

# initialize needed objects
# DataLoader用于查找并解析yaml、json、ini文件,把它们转换成python的数据类型
loader = DataLoader() # Takes care of finding and reading yaml, json and ini files
# 设置密码
passwords = dict()

# create inventory, use path to host config file as source or hosts in a comma separated string
# 定义主机清单,可以将各主机用逗号隔开的字符串,也可以指定文件路径列表
# inventory = InventoryManager(loader=loader, sources='localhost,')
inventory = InventoryManager(loader=loader, sources=['myansible/hosts'])

# variable manager takes care of merging all the different sources to give you a unifed view of variables available in each context
# 变量管理器
variable_manager = VariableManager(loader=loader, inventory=inventory)

# create datastructure that represents our play, including tasks, this is basically what our YAML loader does internally.
play_source =  dict(
        name = "Ansible Play",  # play的名字
        hosts = 'webservers',    # 指定在哪些主机上执行命令
        gather_facts = 'no',
        tasks = [
            dict(action=dict(module='shell', args='ls'), register='shell_out'),
            dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}')))
         ]
    )

# Create play object, playbook objects use .load instead of init or new methods,
# this will also automatically create the task objects from the info provided in play_source
# 通过上面的配置,创建一个play
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)

# Run it - instantiate task queue manager, which takes care of forking and setting up all objects to iterate over host list and tasks
# 创建任管理器,执行play
tqm = None
try:
    tqm = TaskQueueManager(
              inventory=inventory,
              variable_manager=variable_manager,
              loader=loader,
              options=options,
              passwords=passwords,
          )
    result = tqm.run(play) # most interesting data for a play is actually sent to the callback's methods
finally:
    # we always need to cleanup child procs and the structres we use to communicate with them
    if tqm is not None:
        tqm.cleanup()

    # Remove ansible tmpdir
    shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
########################################################################################
[root@room9pc01 myansible]# vim adhoc2.py 
import shutil
from collections import namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars.manager import VariableManager
from ansible.inventory.manager import InventoryManager
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
import ansible.constants as C

def adhoc(sources=None, hosts=None, module=None, args=None):
    Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'diff'])
    options = Options(connection='ssh', module_path=['/to/mymodules'], forks=10, become=None, become_method=None, become_user=None, check=False, diff=False)
    loader = DataLoader()
    passwords = dict()
    inventory = InventoryManager(loader=loader, sources=sources)
    variable_manager = VariableManager(loader=loader, inventory=inventory)
    play_source = dict(
            name="Ansible Play",  # play的名字
            hosts=hosts,    # 指定在哪些主机上执行命令
            gather_facts='no',
            tasks=[
                dict(action=dict(module=module, args=args), register='shell_out'),
             ]
        )
    play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
    tqm = None
    try:
        tqm = TaskQueueManager(
                  inventory=inventory,
                  variable_manager=variable_manager,
                  loader=loader,
                  options=options,
                  passwords=passwords,
              )
        result = tqm.run(play)
    finally:
        if tqm is not None:
            tqm.cleanup()

        shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
if __name__ == '__main__':
    sources = ['hosts']
    hosts = 'webservers'
    module = 'shell'
    args = 'useradd alice'
    adhoc(sources, hosts, module, args)
[root@room9pc01 myansible]# python3 adhoc2.py
##############################################################################
[root@room9pc01 myansible]# vim runpb.py
from collections import namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars.manager import VariableManager
from ansible.inventory.manager import InventoryManager
from ansible.executor.playbook_executor import PlaybookExecutor

Options = namedtuple(
    'Options',
    [
        'connection',
        'remote_user',
        'ask_sudo_pass',
        'verbosity',
        'ask_pass',
        'module_path',
        'forks',
        'become',
        'become_method',
        'become_user',
        'check',
        'listhosts',
        'listtasks',
        'listtags',
        'syntax',
        'sudo_user',
        'sudo',
        'diff'
    ]
)
options = Options(
    connection='smart',
    remote_user=None,
    ask_pass=None,
    sudo_user=None,
    forks=5,
    sudo=None,
    ask_sudo_pass=False,
    verbosity=5,
    module_path=None,
    become=None,
    become_method=None,
    become_user=None,
    check=False,
    diff=False,
    listhosts=None,
    listtasks=None,
    listtags=None,
    syntax=None
)
loader = DataLoader()
passwords = dict()

def runpb(pb_path, sources):
    inventory = InventoryManager(loader=loader, sources=sources)
    variable_manager = VariableManager(loader=loader, inventory=inventory)
    playbook = PlaybookExecutor(
        playbooks=pb_path,
        inventory=inventory,
        variable_manager=variable_manager,
        loader=loader,
        options=options,
        passwords=passwords
    )
    result = playbook.run()
    return result

if __name__ == '__main__':
    runpb(pb_path=['lamp.yml'], sources=['hosts'])

#####################################################################################################
ansible模块开发

官方模块
• Ansible官方已经提供了大量模块,在编写模块之前,可以查看是否已有现成模块
• 官方已发布模块
http://docs.ansible.com/ansible/modules.html
• 官方正在开发的模块
https://github.com/ansible/ansible/labels/module

模块执行流程
• 将模块文件读入内存,然后添加传递给模块的参数,最后将模块中所需要的类添加到内存,由zipfile压缩后,再由base64进行编码,写入到模板文件内
• 通过默认的连接方式(一般是ssh),ansible连接到远程主机,创建临时目录,并关闭连接
• 打开另外一个ssh连接,将模板文件以sftp方式传送到刚刚创建的临时目录中,写完后关闭连接
• 打开一个ssh连接将任务对象赋予可执行权限,执行成功后关闭连接
• 最后,ansible将再打开一个新连接来执行模块,并删除临时目录及其所有内容
• 模块的结果是从标准输出stdout中获取json格式的字符串。ansible将解析和处理此字符串

[root@room9pc01 myansible]# mkdir library		//自定义模块目录
[root@room9pc01 myansible]# cd library/
[root@room9pc01 library]# pwd
/root/桌面/myansible/library
[root@room9pc01 library]# export ANSIBLE_LIBRARY=/root/桌面/myansible/library		//使用 ANSIBLE_LIBRARY环境变量指定自定义模块存放路径	

编写模块,用于在远程主机上将一个文件拷贝到目标位置

[root@room8pc16 library]# vim mycopy.py
import shutil
from ansible.module_utils.basic import AnsibleModule

def main():
    module = AnsibleModule(
        argument_spec=dict(
            yuan=dict(required=True, type='str'),
            mubiao=dict(required=True, type='str')
        )
    )
    shutil.copy(module.params['yuan'], module.params['mubiao'])
    module.exit_json(changed=True)

if __name__ == '__main__':
    main()
[root@room8pc16 myansible]# ansible dbservers -m mycopy -a "yuan=/etc/hosts mubiao=/tmp/zj.txt"
[root@node4 ~]# ls /tmp/zj.txt 
/tmp/zj.txt

案例:

  • 测试把一张图片放到web服务器的根目录下,如url是:http://192.168.4.5/people.jpg
  • 通过ansible使用download模块,要求dbservers下载图片到/home下
[root@room9pc01 myansible]# ansible dbservers -m download -a "url=http://192.168.4.5/people.jpg local=/home/"

执行时报错,提示没有wget模块。原因是ansible会将download模块拷贝到远程dbservers服务器,在dbservers上执行download,但是dbservers上没有安装wget模块。因此需要在dbservers上安装wget模块

[root@room9pc01 ~]# pip3 download wget --trusted-host mirrors.163.com		//下载wget模块
[root@room9pc01 ~]# scp wget-3.2.zip 192.168.4.4:/tmp
[root@node4 ~]# ls /tmp
zj.txt
wget-3.2.zip
[root@node4 ~]# cd /tmp
[root@node4 tmp]# unzip wget-3.2.zip 
[root@node4 tmp]# cd wget-3.2/
[root@node4 wget-3.2]# python setup.py install		//dbservers上安装wget模块
[root@node4 wget-3.2]# python
>>> import wget
>>>
########################################################################
[root@room9pc01 myansible]# cd library/
[root@room9pc01 library]# vim download.py
import wget
from ansible.module_utils.basic import AnsibleModule

def main():
    module = AnsibleModule(
        argument_spec=dict(
            url=dict(required=True, type='str'),
            local=dict(required=True, type='str')
        )
    )
    wget.download(module.params['url'], module.params['local'])
    module.exit_json(changed=True)

if __name__ == '__main__':
    main()
[root@room9pc01 library]# cd ..
[root@room9pc01 myansible]# ansible dbservers -m download -a "url=http://192.168.4.5/people.jpg local=/home/"		//ansible执行自定义download模块
node4.tedu.cn | CHANGED => {
    "changed": true
}
[root@node4 ~]# ls /home		//图片下载到dbservers对应目录下
lisi  people.jpg

ansible-cmdb模块
用于将ansible收集下来的主机信息转换成html页面

[root@room9pc01 ansible-cmdb_pkgs]# pip3 install *
[root@room9pc01 ansible-cmdb_pkgs]# vim /usr/local/bin/ansible-cmdb
  8 PY_BIN=$(which python3)    # 第8行改为python3,默认是python2
[root@room9pc01 myansible]# ansible all -m setup --tree /tmp/out		# 通过setup模块收集远程主机信息并保存到/tmp/out/目录
[root@room9pc01 myansible]# ansible-cmdb /tmp/out/ > /tmp/hosts.html		# 利用ansible-cmdb分析/tmp/out/下的文件,生成html
[root@room9pc01 myansible]# firefox /tmp/hosts.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值