Commit 05947704 by see.liuh@gmail.com

创建文档

0 parents
Showing 137 changed files with 2002 additions and 0 deletions
# watchmen
我们这套系统叫运维更合适,无奈公司已经有运维了,所以中文名采用自检系统,还好有代号,叫它watchmen吧
这套系统需要开发、测试、运维人员共同完善,所以在这里创建这个公共项目。希望大家完善文档,改错、增加使用心得等等。
Issues作为交流中心,有什么想法和要求可以创建Issue
\ No newline at end of file
# ansible_playback
存放自己写好的ansible playback文件。需要在当前文件添加文档,简述用法和注意事项
## playback1
说明...
\ No newline at end of file
# awesome script
跟运维相关的好脚本,分享一下吧。
## script1
说明...
概述
=======
文安自检系统(代号:watchmen)文档
watchmen试运行在繁星2代上,所以此文档内容与繁星2代深度耦合
watchmen由3个组件组成: elk日志 + zabbix监测 + ansible批量控制 。 思路概述见 《自检系统思路概述ppt.pdf》
开发人员、测试人员、运维人员均会用到watchmen系统,使用svn或git共同维护此文档,将内容逐渐完善,将自己的使用实例、心得记录在文档中
术语
--------
- 繁星2代:由40颗TX1芯片组成,每颗芯片有独立的操作系统,芯片之间用网络互通。一个繁星有4个网口,对应4颗主芯片,可与外部网络联通。主芯片有双网口,与其他子芯片组成内部子网络。
结构
--------
从节点:
- filebeat (日志收集)
- zabbix_agent (监测项状态上报)
主节点:
- zabbix_agent (监测项状态上报)
- zabbix_proxy (检测项转发代理)
- haproxy (日志转发代理)
- ansible (批量控制)
服务器:
- zabbix_server (zabbix服务端)
- zabbix_front (zabbix web)
- postgres (zabbix数据库)
- elasticsearch (日志系统服务端)
- kibana (日志系统web)
繁星2代网络隔离,只有主节点与外部网络联通,所以需要用zabbix_proxy和haproxy做代理,并且ansible部署在主节点,使用主节点对从节点批量控制
ansible集群管理工具
=======================================
离线安装包: smb://192.168.9.1/公共模块/繁星/繁星二代/自检系统/ansible_offline_tx1
playback实例在 ansible_playback_example 目录。
在繁星中增加ansible,作为集群管理工具。ansible工作的流程是,读取/etc/ansible/hosts主机列表,批量的、自动的使用ssh远程到主机上执行指令,我们可以用它获得子节点的状态,批量配置、更新程序
我们有三种使用方法:
1. 写python或shell脚本,在脚本中编写复杂的指令组合,利用ansible的command模块将脚本和所需文件上传、执行。--此方法学习成本低,易上手。初级使用方法
2. 使用ansible提供的module+playback。 module相当于shell命令(copy/ls/ps/apt-get等等),playback相当于shell脚本,将module组合执行。 --此方法需要需要学习各module的功能和参数,playback语法(yml),优点是反馈更清晰,流程掌控更好,playback比shell和python好写些。
3. 编写python脚本,使用ansible-api。 --此方法最高级,我能想到的需要使用此方法的应用途径:需要解析反馈信息并根据反馈做出不同反应;需要在自己的服务中利用ansible实现批量控制功能,比如批量升级服务,需要将各子节点升级进度,升级状态,错误信息反馈到web。
中文说明文档:http://www.ansible.com.cn/docs/
常用模块使用方法:https://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_linux_032_ansible02.html 。
安装
-------------------------------------------
- 安装
繁星的离线包已放在sdv,放在主节点上执行install.sh即可
在自己主机上安装: pip install ansible 。然后安装sshpass(支持在配置文件中增加密码免询问)
配置
------------------------------------------
- 配置主机列表
.. code-block:: shell
mkdir /etc/ansible
vim /etc/ansible/hosts
文件实例
.. code-block:: shell
[starnet1]
ubuntu@192.168.66.7
#指定密码,支持sudo不询问密码
ubuntu@192.168.66.12 ansible_sudo_pass='ubuntu'
ubuntu@192.168.66.27 ansible_sudo_pass='ubuntu'
ubuntu@192.168.66.32 ansible_sudo_pass='ubuntu'
ubuntu@192.168.66.4 ansible_sudo_pass='ubuntu'
[starnet2]
#公司内部使用这种配置方法。
192.168.66.[2:41] ansible_ssh_pass="ubuntu" ansible_ssh_user="ubuntu" ansible_sudo_pass='ubuntu'
- **非交互式用户名密码方式(推荐公司内部采用此方式,方便但安全性低)**
此方法需要安装sshpass。离线包已包含。密码需要已明文卸载配置中,不安全,在安全要求高的环境中禁止使用。但这个方法节省了对每个主机执行ssh-copy-id,是最方便的。参考配置文件中的starnet2组。在执行命令前,需要配置环境变量 export ANSIBLE_HOST_KEY_CHECKING=False,否则会报错。
执行 ansible starnet2 -m ping, 会向192.168.66.2,192.168.66.3 ... 192.168.66.41 测试是否连通。
- ssh公钥方式
.. code-block:: shell
ssh-keygen #一路回车
ssh-copy-id ubuntu@目标节点IP
#测试是否成功
ssh ubuntu@ip #不需要输入密码就能登录则说明成功
#也可以用root账户,输入密码。所有主机拷贝一次,后续就可以免密登陆了
#测试ping所有主机
ansible all -m ping
- 交互式用户名密码方式(询问密码)
.. code-block:: shell
ansible starnet1 -m ping --user=ubuntu -k
使用
-------------------------------------------
“上传文件夹,执行脚本” 。这种模式可以批量部署程序
- 执行多条指令方式
.. code-block:: shell
#拷贝文件/文件夹
`ansible starnet -m copy -a "src=./ansible_offline_tx1 /home/ubuntu/"`
#在主机上执行shell命令
`ansible starnet -m command -a "chmod +x /home/ubuntu/ansible_offline_tx1/install.sh"`
`ansible starnet -m command -a "bash /home/ubuntu/ansible_offline_tx1/install.sh"`
以上两条指令结合,可满足大部分需求。
- playback方式
playback文件内容:
.. code-block:: shell
---
- hosts: starnet
sudo: yes
tasks:•
- name: copy dir to remote
copy: src=ansible_offline_tx1 dest=/home/ubuntu/ansible_offline_tx1
- name: run script
command: chmod +x install.sh
args:
chdir: /home/ubuntu/ansible_offline_tx1/
command: bash install.sh
args:
chdir: /home/ubuntu/ansible_offline_tx1/
保存 ansible_offline_tx1.yml
执行playback
.. code-block:: shell
ansible-playback ansible_offline_tx1.yml
ansible提供了非常多的module,常用模块使用方法:https://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_linux_032_ansible02.html。
ansible-doc -l #可查看所有模块
ansible-doc 模块名 #查看某模块的使用方法,比如 ansible-doc apt ; ansible-doc pip ; ansible-doc ps
我这里的介绍只是快速入门方法,还有很多强大的功能,比如copy的backup特性,幂性,hosts的多级分组,定时任务等等 建议通读一遍中文说明文档:http://www.ansible.com.cn/docs/
elk日志系统
===============
ELK组合是日志系统的经典组合。但是Logstash是java程序,占用内存资源比较大,前端将其换成轻量级的filebeat。haproxy放在主节点上做代理转发。
filebeat(日志收集)+ elasticsearch(日志存储搜索)+kibana(ui展示)+haproxy(代理转发)
安装
------------------------------------------
离线安装包: smb://192.168.9.1/公共模块/繁星/繁星二代/自检系统/(elk_tx1、elk_server、haproxy_tx1)
filebeat使用源码放在主机上编译。 elk三个工程使用官方下载的tar.gz的包。都是java程序,直接就能运行。
繁星2代已编译好filebeat,其他平台需按照下面步骤编译:
filebeat编译安装参考:
https://blog.csdn.net/lk142500/article/details/7953584
ubuntu14安装golang1.10:
https://www.cnblogs.com/senlinyang/p/8777384.html
配置
---------------------------------------------
elasticsearch-6.4.0配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.. code-block:: shell
# 修改 elasticsearch-6.4.0/config/elasticsearch.yml
# 开放所有ip访问
network.host: 0.0.0.0
# 修改系统参数,否则运行会报错
vi /etc/sysctl.conf
vm.max_map_count=655360
sysctl -p
kibana-6.4.0-linux-x86_64配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.. code-block:: shell
# 修改 kibana-6.4.0-linux-x86_64/config/kibana.yml
# 开放所有ip访问
server.host: "0.0.0.0"
# 配置elasticsearch的访问地址
elasticsearch.url: "http://127.0.0.1:9200"
filebeat配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.. code-block:: shell
- type: log
# 改成true
enabled: true
# 配置日志路径,可配置多个,支持通配符但层级格式必须相符
paths:
- /root/Log/Ops/*/*.log
- /root/Log/VASvr/*/*.log
# 日志编码格式。如果不一致,配置两个《- type: log》块。
encoding: gbk
# 本机标签,在kibana搜索时可以以beat.name为过滤条件
name: "myname-192.168.5.99"
haproxy配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.. code-block:: shell
# 编辑/etc/haproxy/haproxy.cfg 在末尾增加下面配置
# 将本机所有9200端口数据转发至服务器9200端口
listen elastic_proxy
bind 0.0.0.0:9200
mode tcp
server s1 192.168.9.133:9200
使用
------------------------------------------------------
kibana访问地址: http://ip:5601
quick start
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Discover是查看、搜索日志的主要页面。如果有filebeat上报日志,第一次进入Discover会自动跳转,创建Index Patterns。
.. image:: ./images/elk-01.png
.. image:: ./images/elk-02.png
创建完毕后,在Discover中可以看到日志内容了,鼠标移到message,点add添加到“selected fields”中,日志内容看起来会清晰些。
.. image:: ./images/elk-03.png
Management->Elasticsearch->Index Management中会自动生成类似“filebeat-7.0.0-alpha1-2018.09.29”的行。
进入Management->Kibana->Index Patterns可查看、删除、重新创建Index Patterns
仅以上配置,利用搜索栏和Add a filter, 以主机、文件名、时间、关键字等等组合条件,就能满足绝大多数需求。
其他使用技巧在下面补充
kibana页面上的日志搜索技巧
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
kikana Discover页面的搜索栏支持的查询语法名叫Lucene query。elasticsearch底层使用Lucene,api和kibana都支持Lucene语法。
lucene query语法参考:https://blog.csdn.net/feifantiyan/article/details/54411183
下面列出几个使用实例:
- 查找beat.name为8.133的设备上日志文件路径中包含"Ops/2018-9-30"的日志
.. code-block:: shell
source:?*\/Ops\/2018-09-30?* AND beat.name:8.133
zabbix监测系统
===============
安装
--------------------------------
使用docker安装/运行方式(建议使用此方式)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
离线安装包: smb://192.168.9.1/公共模块/繁星/繁星二代/自检系统/(zabbix_agent_proxy_tx1、zabbix_docker)
有docker离线包zabbix_docker,拷贝到有docker的主机上,加载镜像:
.. code-block:: shell
docker load < postgres9.6.docker.images
# 屏幕会返回镜像的id,假设是:id-1
# 给镜像命名
docker tag id-1 postgres:9.6
# 下面两个镜像不需要命名,如果load后运行docker images 发现名字和版本都是none,则手动命名
docker load < zabbix-server-pgsql.docker.images
# docker tag id-2 zabbix/zabbix-server-pgsql:ubuntu-3.4.13
docker load < zabbix-web-nginx-pgsql.docker.images
# docker tag id-3 zabbix/zabbix-web-nginx-pgsql:ubuntu-3.4.13
# 加载完毕,docker images应该能显示
root@user-ubuntu:~/zabbix_docker# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
zabbix/zabbix-web-nginx-pgsql ubuntu-3.4.13 bf422197fafe 4 weeks ago 254 MB
zabbix/zabbix-server-pgsql ubuntu-3.4.13 af4434f6332b 4 weeks ago 224 MB
postgres 9.6 4023a747a01a 20 months ago 265 MB
本地安装/运行方式(坑多)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
**此方法不同的机器上可能遇到不同的问题,下面的说明只能作为参考。 **
我用网上说的apt-get方式装,无法成功。web界面使用不正常,所以采用源码方式装。zabbix-3.4.13.tar.gz
环境依赖安装按照以下步骤:
https://blog.csdn.net/yannanxiu/article/details/54924198
zabbix-proxy zabbix-server zabbix-front-php 用源码安装,参考:
https://www.zabbix.com/documentation/3.4/zh/manual/installation/install
数据库安装,建立zabbix用户,建立zabbix数据库,运行zabbix-3.4.13/database/postgresql/中的3个脚本。命令行:
.. code-block:: shell
su postgres
createdb zabbix
createuser -SDRP zabbix
su root
cat ./zabbix-3.4.13/zabbix-3.4.13/database/postgresql/{schema,images,data}.sql.gz | psql -h 127.0.0.1 zabbix postgres
或者带界面的postgres客户端做也行。自行选择
zabbix-fornt(web界面)
# 从源码拷贝到apache2
sudo cp -r zabbix-3.4.13/frontends/php/ /var/www/html/zabbix
- zabbix_sender报错
.. code-block:: shell
root@tegra-ubuntu:/home/ubuntu# zabbix_sender -s "192.168.5.198" -z "192.168.5.133" -k "keytrtest" -o "1133"
info from server: "processed: 0; failed: 1; total: 1; seconds spent: 0.000026"
这里failed: 1说明失败了。
注意看item的type必须是Zabbix trapper
server主动获取,在zabbix_agent.conf增加的item的type是Zabbix trapper
配置
----------------------------
zabbix_agent配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
**需要在系统配置开机启动**
zabbix_agentd安装包是在tx1上编译的。zabbix_agent_proxy_tx1的install.sh会将配置文件拷贝到
/usr/local/etc/zabbix_agent.conf
.. code-block:: shell
# 填写主节点ip
Server=192.168.5.177
ServerActive=192.168.5.177
# 主节点运行的是proxy,在默认情况下这样填写
Hostname=Zabbix proxy
AllowRoot=1
修改完重启进程
zabbix_proxy配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
**需要在系统配置开机启动**
zabbix_proxy安装包是在tx1上编译的。zabbix_agent_proxy_tx1的install.sh会将配置文件拷贝到
/usr/local/etc/zabbix_proxy.conf
.. code-block:: shell
# zabbix_server主机ip
Server=192.168.9.133
# 需和zabbix_agent配置的Hostname对应
Hostname=Zabbix proxy
# zabbix_proxy数据库目录,如果是使用install.sh脚本安装的,会放在/root/UserApp下。
DBName=/root/UserApp/zabbix_proxy.db
# 多长间隔从zabbix_server拉取配置(秒)
ConfigFrequency=120
AllowRoot=1
zabbix_server配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
**需要在系统配置开机启动**
zabbix_server在docker运行,在每次启动容器的时候会将必要参数传入,zabbix_docker/dockerrun_zabbix.sh已写好,运行即可
使用
------------------------------------------
访问路径: http://ip:9210
第一次运行会有一些额外步骤,按照提示下一步即可
quick start
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
添加proxy,注意Proxy name必须和 zabbix_proxy配置中的Hostname相同。其他配置默认即可。点add添加成功
.. image:: ./images/zabbix-01.png
添加host,Configuration->Hosts->Create host
.. image:: ./images/zabbix-02.png
红框都是需要填写修改的。Groups可以自己建,给设备分组。Monitored by proxy必须选择正确的proxy代理
.. image:: ./images/zabbix-03.png
点Template配置模板,模板决定了有哪些监测项。select选择一个模板,模板后续我们会自己创建,这里先选择Template OS Linux,包含了很多linux的监测项
点小add后再点大add
.. image:: ./images/zabbix-04.png
添加成功
Dashboard可以浏览状态、报警等,Edit dashboard可以自定义。比如Problems中提示我的主机掉线了。
.. image:: ./images/zabbix-05.png
如果想有目的的查询监测项状态,可以打开Monitoring->Lastest data。可以在过滤条件选择感兴趣的主机和检测项组
可以看到最后的值,可以点Graph看数值历史折线图。
.. image:: ./images/zabbix-06.png
.. image:: ./images/zabbix-07.png
这是最基本的使用,后续添加如何自定义监测项,利用api批量添加主机、动态管理监测项等功能。
修订历史
================
2018.10.17
------------
1. zabbix agent和proxy配置文件增加 AllowRoot=1,使其可以用root账户运行
2. 错别字修改,watchman改成watchmen,明明是想用DC漫画的watchmen :)
2018.10.10
------------
1. 修改了zabbix_agent安装方法。由deb包安装改成编译安装。deb版本较低,一些定义好的item不支持。改成3.4版本源码编译的,与zabbix_proxy一起安装
2018.10.09
------------
1. 新建文档,增加了watchmen各组件最基本的安装、配置、quickstart文档
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXPROJ = face_camera_api
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
\ No newline at end of file
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: dfe5f3b56cb39b7b38b15961f34e3f20
tags: 645f666f9bcd5a90fca523b33c5a78b7
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>1. 概述 &mdash; watchmen 1.0 documentation</title>
<link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="2. ansible集群管理工具" href="20-ansible.html" />
<link rel="prev" title="Welcome to watchmen’s documentation!" href="index.html" />
<script src="_static/js/modernizr.min.js"></script>
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search">
<a href="index.html" class="icon icon-home"> watchmen
</a>
<div class="version">
1.0
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<p class="caption"><span class="caption-text">Contents:</span></p>
<ul class="current">
<li class="toctree-l1 current"><a class="current reference internal" href="#">1. 概述</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#id2">1.1. 术语</a></li>
<li class="toctree-l2"><a class="reference internal" href="#id3">1.2. 结构</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="20-ansible.html">2. ansible集群管理工具</a></li>
<li class="toctree-l1"><a class="reference internal" href="30-elk.html">3. elk日志系统</a></li>
<li class="toctree-l1"><a class="reference internal" href="40-zabbix.html">4. zabbix监测系统</a></li>
<li class="toctree-l1"><a class="reference internal" href="99-history.html">5. 修订历史</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="index.html">watchmen</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="index.html">Docs</a> &raquo;</li>
<li>1. 概述</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/10-summary.rst.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<div class="section" id="id1">
<h1>1. 概述<a class="headerlink" href="#id1" title="Permalink to this headline"></a></h1>
<p>文安自检系统(代号:watchmen)文档</p>
<p>watchmen试运行在繁星2代上,所以此文档内容与繁星2代深度耦合</p>
<p>watchmen由3个组件组成: elk日志 + zabbix监测 + ansible批量控制 。 思路概述见 《自检系统思路概述ppt.pdf》</p>
<p>开发人员、测试人员、运维人员均会用到watchmen系统,使用svn或git共同维护此文档,将内容逐渐完善,将自己的使用实例、心得记录在文档中</p>
<div class="section" id="id2">
<h2>1.1. 术语<a class="headerlink" href="#id2" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li>繁星2代:由40颗TX1芯片组成,每颗芯片有独立的操作系统,芯片之间用网络互通。一个繁星有4个网口,对应4颗主芯片,可与外部网络联通。主芯片有双网口,与其他子芯片组成内部子网络。</li>
</ul>
</div>
<div class="section" id="id3">
<h2>1.2. 结构<a class="headerlink" href="#id3" title="Permalink to this headline"></a></h2>
<p>从节点:</p>
<ul class="simple">
<li>filebeat (日志收集)</li>
<li>zabbix_agent (监测项状态上报)</li>
</ul>
<p>主节点:</p>
<ul class="simple">
<li>zabbix_agent (监测项状态上报)</li>
<li>zabbix_proxy (检测项转发代理)</li>
<li>haproxy (日志转发代理)</li>
<li>ansible (批量控制)</li>
</ul>
<p>服务器:</p>
<ul class="simple">
<li>zabbix_server (zabbix服务端)</li>
<li>zabbix_front (zabbix web)</li>
<li>postgres (zabbix数据库)</li>
<li>elasticsearch (日志系统服务端)</li>
<li>kibana (日志系统web)</li>
</ul>
<p>繁星2代网络隔离,只有主节点与外部网络联通,所以需要用zabbix_proxy和haproxy做代理,并且ansible部署在主节点,使用主节点对从节点批量控制</p>
</div>
</div>
</div>
</div>
<footer>
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
<a href="20-ansible.html" class="btn btn-neutral float-right" title="2. ansible集群管理工具" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right"></span></a>
<a href="index.html" class="btn btn-neutral" title="Welcome to watchmen’s documentation!" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left"></span> Previous</a>
</div>
<hr/>
<div role="contentinfo">
<p>
&copy; Copyright 2018, liuhang.
</p>
</div>
Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT:'./',
VERSION:'1.0',
LANGUAGE:'None',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt'
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/js/theme.js"></script>
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>5. 修订历史 &mdash; watchmen 1.0 documentation</title>
<link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="prev" title="4. zabbix监测系统" href="40-zabbix.html" />
<script src="_static/js/modernizr.min.js"></script>
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search">
<a href="index.html" class="icon icon-home"> watchmen
</a>
<div class="version">
1.0
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<p class="caption"><span class="caption-text">Contents:</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="10-summary.html">1. 概述</a></li>
<li class="toctree-l1"><a class="reference internal" href="20-ansible.html">2. ansible集群管理工具</a></li>
<li class="toctree-l1"><a class="reference internal" href="30-elk.html">3. elk日志系统</a></li>
<li class="toctree-l1"><a class="reference internal" href="40-zabbix.html">4. zabbix监测系统</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">5. 修订历史</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#id2">5.1. 2018.10.17</a></li>
<li class="toctree-l2"><a class="reference internal" href="#id3">5.2. 2018.10.10</a></li>
<li class="toctree-l2"><a class="reference internal" href="#id4">5.3. 2018.10.09</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="index.html">watchmen</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="index.html">Docs</a> &raquo;</li>
<li>5. 修订历史</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/99-history.rst.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<div class="section" id="id1">
<h1>5. 修订历史<a class="headerlink" href="#id1" title="Permalink to this headline"></a></h1>
<div class="section" id="id2">
<h2>5.1. 2018.10.17<a class="headerlink" href="#id2" title="Permalink to this headline"></a></h2>
<ol class="arabic simple">
<li>zabbix agent和proxy配置文件增加 AllowRoot=1,使其可以用root账户运行</li>
<li>错别字修改,watchman改成watchmen,明明是想用DC漫画的watchmen :)</li>
</ol>
</div>
<div class="section" id="id3">
<h2>5.2. 2018.10.10<a class="headerlink" href="#id3" title="Permalink to this headline"></a></h2>
<ol class="arabic simple">
<li>修改了zabbix_agent安装方法。由deb包安装改成编译安装。deb版本较低,一些定义好的item不支持。改成3.4版本源码编译的,与zabbix_proxy一起安装</li>
</ol>
</div>
<div class="section" id="id4">
<h2>5.3. 2018.10.09<a class="headerlink" href="#id4" title="Permalink to this headline"></a></h2>
<ol class="arabic simple">
<li>新建文档,增加了watchmen各组件最基本的安装、配置、quickstart文档</li>
</ol>
</div>
</div>
</div>
</div>
<footer>
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
<a href="40-zabbix.html" class="btn btn-neutral" title="4. zabbix监测系统" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left"></span> Previous</a>
</div>
<hr/>
<div role="contentinfo">
<p>
&copy; Copyright 2018, liuhang.
</p>
</div>
Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT:'./',
VERSION:'1.0',
LANGUAGE:'None',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt'
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/js/theme.js"></script>
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>
\ No newline at end of file
概述
=======
文安自检系统(代号:watchmen)文档
watchmen试运行在繁星2代上,所以此文档内容与繁星2代深度耦合
watchmen由3个组件组成: elk日志 + zabbix监测 + ansible批量控制 。 思路概述见 《自检系统思路概述ppt.pdf》
开发人员、测试人员、运维人员均会用到watchmen系统,使用svn或git共同维护此文档,将内容逐渐完善,将自己的使用实例、心得记录在文档中
术语
--------
- 繁星2代:由40颗TX1芯片组成,每颗芯片有独立的操作系统,芯片之间用网络互通。一个繁星有4个网口,对应4颗主芯片,可与外部网络联通。主芯片有双网口,与其他子芯片组成内部子网络。
结构
--------
从节点:
- filebeat (日志收集)
- zabbix_agent (监测项状态上报)
主节点:
- zabbix_agent (监测项状态上报)
- zabbix_proxy (检测项转发代理)
- haproxy (日志转发代理)
- ansible (批量控制)
服务器:
- zabbix_server (zabbix服务端)
- zabbix_front (zabbix web)
- postgres (zabbix数据库)
- elasticsearch (日志系统服务端)
- kibana (日志系统web)
繁星2代网络隔离,只有主节点与外部网络联通,所以需要用zabbix_proxy和haproxy做代理,并且ansible部署在主节点,使用主节点对从节点批量控制
ansible集群管理工具
=======================================
离线安装包: smb://192.168.9.1/公共模块/繁星/繁星二代/自检系统/ansible_offline_tx1
playback实例在 ansible_playback_example 目录。
在繁星中增加ansible,作为集群管理工具。ansible工作的流程是,读取/etc/ansible/hosts主机列表,批量的、自动的使用ssh远程到主机上执行指令,我们可以用它获得子节点的状态,批量配置、更新程序
我们有三种使用方法:
1. 写python或shell脚本,在脚本中编写复杂的指令组合,利用ansible的command模块将脚本和所需文件上传、执行。--此方法学习成本低,易上手。初级使用方法
2. 使用ansible提供的module+playback。 module相当于shell命令(copy/ls/ps/apt-get等等),playback相当于shell脚本,将module组合执行。 --此方法需要需要学习各module的功能和参数,playback语法(yml),优点是反馈更清晰,流程掌控更好,playback比shell和python好写些。
3. 编写python脚本,使用ansible-api。 --此方法最高级,我能想到的需要使用此方法的应用途径:需要解析反馈信息并根据反馈做出不同反应;需要在自己的服务中利用ansible实现批量控制功能,比如批量升级服务,需要将各子节点升级进度,升级状态,错误信息反馈到web。
中文说明文档:http://www.ansible.com.cn/docs/
常用模块使用方法:https://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_linux_032_ansible02.html 。
安装
-------------------------------------------
- 安装
繁星的离线包已放在sdv,放在主节点上执行install.sh即可
在自己主机上安装: pip install ansible 。然后安装sshpass(支持在配置文件中增加密码免询问)
配置
------------------------------------------
- 配置主机列表
.. code-block:: shell
mkdir /etc/ansible
vim /etc/ansible/hosts
文件实例
.. code-block:: shell
[starnet1]
ubuntu@192.168.66.7
#指定密码,支持sudo不询问密码
ubuntu@192.168.66.12 ansible_sudo_pass='ubuntu'
ubuntu@192.168.66.27 ansible_sudo_pass='ubuntu'
ubuntu@192.168.66.32 ansible_sudo_pass='ubuntu'
ubuntu@192.168.66.4 ansible_sudo_pass='ubuntu'
[starnet2]
#公司内部使用这种配置方法。
192.168.66.[2:41] ansible_ssh_pass="ubuntu" ansible_ssh_user="ubuntu" ansible_sudo_pass='ubuntu'
- **非交互式用户名密码方式(推荐公司内部采用此方式,方便但安全性低)**
此方法需要安装sshpass。离线包已包含。密码需要已明文卸载配置中,不安全,在安全要求高的环境中禁止使用。但这个方法节省了对每个主机执行ssh-copy-id,是最方便的。参考配置文件中的starnet2组。在执行命令前,需要配置环境变量 export ANSIBLE_HOST_KEY_CHECKING=False,否则会报错。
执行 ansible starnet2 -m ping, 会向192.168.66.2,192.168.66.3 ... 192.168.66.41 测试是否连通。
- ssh公钥方式
.. code-block:: shell
ssh-keygen #一路回车
ssh-copy-id ubuntu@目标节点IP
#测试是否成功
ssh ubuntu@ip #不需要输入密码就能登录则说明成功
#也可以用root账户,输入密码。所有主机拷贝一次,后续就可以免密登陆了
#测试ping所有主机
ansible all -m ping
- 交互式用户名密码方式(询问密码)
.. code-block:: shell
ansible starnet1 -m ping --user=ubuntu -k
使用
-------------------------------------------
“上传文件夹,执行脚本” 。这种模式可以批量部署程序
- 执行多条指令方式
.. code-block:: shell
#拷贝文件/文件夹
`ansible starnet -m copy -a "src=./ansible_offline_tx1 /home/ubuntu/"`
#在主机上执行shell命令
`ansible starnet -m command -a "chmod +x /home/ubuntu/ansible_offline_tx1/install.sh"`
`ansible starnet -m command -a "bash /home/ubuntu/ansible_offline_tx1/install.sh"`
以上两条指令结合,可满足大部分需求。
- playback方式
playback文件内容:
.. code-block:: shell
---
- hosts: starnet
sudo: yes
tasks:•
- name: copy dir to remote
copy: src=ansible_offline_tx1 dest=/home/ubuntu/ansible_offline_tx1
- name: run script
command: chmod +x install.sh
args:
chdir: /home/ubuntu/ansible_offline_tx1/
command: bash install.sh
args:
chdir: /home/ubuntu/ansible_offline_tx1/
保存 ansible_offline_tx1.yml
执行playback
.. code-block:: shell
ansible-playback ansible_offline_tx1.yml
ansible提供了非常多的module,常用模块使用方法:https://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_linux_032_ansible02.html。
ansible-doc -l #可查看所有模块
ansible-doc 模块名 #查看某模块的使用方法,比如 ansible-doc apt ; ansible-doc pip ; ansible-doc ps
我这里的介绍只是快速入门方法,还有很多强大的功能,比如copy的backup特性,幂性,hosts的多级分组,定时任务等等 建议通读一遍中文说明文档:http://www.ansible.com.cn/docs/
elk日志系统
===============
ELK组合是日志系统的经典组合。但是Logstash是java程序,占用内存资源比较大,前端将其换成轻量级的filebeat。haproxy放在主节点上做代理转发。
filebeat(日志收集)+ elasticsearch(日志存储搜索)+kibana(ui展示)+haproxy(代理转发)
安装
------------------------------------------
离线安装包: smb://192.168.9.1/公共模块/繁星/繁星二代/自检系统/(elk_tx1、elk_server、haproxy_tx1)
filebeat使用源码放在主机上编译。 elk三个工程使用官方下载的tar.gz的包。都是java程序,直接就能运行。
繁星2代已编译好filebeat,其他平台需按照下面步骤编译:
filebeat编译安装参考:
https://blog.csdn.net/lk142500/article/details/7953584
ubuntu14安装golang1.10:
https://www.cnblogs.com/senlinyang/p/8777384.html
配置
---------------------------------------------
elasticsearch-6.4.0配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.. code-block:: shell
# 修改 elasticsearch-6.4.0/config/elasticsearch.yml
# 开放所有ip访问
network.host: 0.0.0.0
# 修改系统参数,否则运行会报错
vi /etc/sysctl.conf
vm.max_map_count=655360
sysctl -p
kibana-6.4.0-linux-x86_64配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.. code-block:: shell
# 修改 kibana-6.4.0-linux-x86_64/config/kibana.yml
# 开放所有ip访问
server.host: "0.0.0.0"
# 配置elasticsearch的访问地址
elasticsearch.url: "http://127.0.0.1:9200"
filebeat配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.. code-block:: shell
- type: log
# 改成true
enabled: true
# 配置日志路径,可配置多个,支持通配符但层级格式必须相符
paths:
- /root/Log/Ops/*/*.log
- /root/Log/VASvr/*/*.log
# 日志编码格式。如果不一致,配置两个《- type: log》块。
encoding: gbk
# 本机标签,在kibana搜索时可以以beat.name为过滤条件
name: "myname-192.168.5.99"
haproxy配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.. code-block:: shell
# 编辑/etc/haproxy/haproxy.cfg 在末尾增加下面配置
# 将本机所有9200端口数据转发至服务器9200端口
listen elastic_proxy
bind 0.0.0.0:9200
mode tcp
server s1 192.168.9.133:9200
使用
------------------------------------------------------
kibana访问地址: http://ip:5601
quick start
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Discover是查看、搜索日志的主要页面。如果有filebeat上报日志,第一次进入Discover会自动跳转,创建Index Patterns。
.. image:: ./images/elk-01.png
.. image:: ./images/elk-02.png
创建完毕后,在Discover中可以看到日志内容了,鼠标移到message,点add添加到“selected fields”中,日志内容看起来会清晰些。
.. image:: ./images/elk-03.png
Management->Elasticsearch->Index Management中会自动生成类似“filebeat-7.0.0-alpha1-2018.09.29”的行。
进入Management->Kibana->Index Patterns可查看、删除、重新创建Index Patterns
仅以上配置,利用搜索栏和Add a filter, 以主机、文件名、时间、关键字等等组合条件,就能满足绝大多数需求。
其他使用技巧在下面补充
kibana页面上的日志搜索技巧
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
kikana Discover页面的搜索栏支持的查询语法名叫Lucene query。elasticsearch底层使用Lucene,api和kibana都支持Lucene语法。
lucene query语法参考:https://blog.csdn.net/feifantiyan/article/details/54411183
下面列出几个使用实例:
- 查找beat.name为8.133的设备上日志文件路径中包含"Ops/2018-9-30"的日志
.. code-block:: shell
source:?*\/Ops\/2018-09-30?* AND beat.name:8.133
zabbix监测系统
===============
安装
--------------------------------
使用docker安装/运行方式(建议使用此方式)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
离线安装包: smb://192.168.9.1/公共模块/繁星/繁星二代/自检系统/(zabbix_agent_proxy_tx1、zabbix_docker)
有docker离线包zabbix_docker,拷贝到有docker的主机上,加载镜像:
.. code-block:: shell
docker load < postgres9.6.docker.images
# 屏幕会返回镜像的id,假设是:id-1
# 给镜像命名
docker tag id-1 postgres:9.6
# 下面两个镜像不需要命名,如果load后运行docker images 发现名字和版本都是none,则手动命名
docker load < zabbix-server-pgsql.docker.images
# docker tag id-2 zabbix/zabbix-server-pgsql:ubuntu-3.4.13
docker load < zabbix-web-nginx-pgsql.docker.images
# docker tag id-3 zabbix/zabbix-web-nginx-pgsql:ubuntu-3.4.13
# 加载完毕,docker images应该能显示
root@user-ubuntu:~/zabbix_docker# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
zabbix/zabbix-web-nginx-pgsql ubuntu-3.4.13 bf422197fafe 4 weeks ago 254 MB
zabbix/zabbix-server-pgsql ubuntu-3.4.13 af4434f6332b 4 weeks ago 224 MB
postgres 9.6 4023a747a01a 20 months ago 265 MB
本地安装/运行方式(坑多)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
**此方法不同的机器上可能遇到不同的问题,下面的说明只能作为参考。 **
我用网上说的apt-get方式装,无法成功。web界面使用不正常,所以采用源码方式装。zabbix-3.4.13.tar.gz
环境依赖安装按照以下步骤:
https://blog.csdn.net/yannanxiu/article/details/54924198
zabbix-proxy zabbix-server zabbix-front-php 用源码安装,参考:
https://www.zabbix.com/documentation/3.4/zh/manual/installation/install
数据库安装,建立zabbix用户,建立zabbix数据库,运行zabbix-3.4.13/database/postgresql/中的3个脚本。命令行:
.. code-block:: shell
su postgres
createdb zabbix
createuser -SDRP zabbix
su root
cat ./zabbix-3.4.13/zabbix-3.4.13/database/postgresql/{schema,images,data}.sql.gz | psql -h 127.0.0.1 zabbix postgres
或者带界面的postgres客户端做也行。自行选择
zabbix-fornt(web界面)
# 从源码拷贝到apache2
sudo cp -r zabbix-3.4.13/frontends/php/ /var/www/html/zabbix
- zabbix_sender报错
.. code-block:: shell
root@tegra-ubuntu:/home/ubuntu# zabbix_sender -s "192.168.5.198" -z "192.168.5.133" -k "keytrtest" -o "1133"
info from server: "processed: 0; failed: 1; total: 1; seconds spent: 0.000026"
这里failed: 1说明失败了。
注意看item的type必须是Zabbix trapper
server主动获取,在zabbix_agent.conf增加的item的type是Zabbix trapper
配置
----------------------------
zabbix_agent配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
**需要在系统配置开机启动**
zabbix_agentd安装包是在tx1上编译的。zabbix_agent_proxy_tx1的install.sh会将配置文件拷贝到
/usr/local/etc/zabbix_agent.conf
.. code-block:: shell
# 填写主节点ip
Server=192.168.5.177
ServerActive=192.168.5.177
# 主节点运行的是proxy,在默认情况下这样填写
Hostname=Zabbix proxy
AllowRoot=1
修改完重启进程
zabbix_proxy配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
**需要在系统配置开机启动**
zabbix_proxy安装包是在tx1上编译的。zabbix_agent_proxy_tx1的install.sh会将配置文件拷贝到
/usr/local/etc/zabbix_proxy.conf
.. code-block:: shell
# zabbix_server主机ip
Server=192.168.9.133
# 需和zabbix_agent配置的Hostname对应
Hostname=Zabbix proxy
# zabbix_proxy数据库目录,如果是使用install.sh脚本安装的,会放在/root/UserApp下。
DBName=/root/UserApp/zabbix_proxy.db
# 多长间隔从zabbix_server拉取配置(秒)
ConfigFrequency=120
AllowRoot=1
zabbix_server配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
**需要在系统配置开机启动**
zabbix_server在docker运行,在每次启动容器的时候会将必要参数传入,zabbix_docker/dockerrun_zabbix.sh已写好,运行即可
使用
------------------------------------------
访问路径: http://ip:9210
第一次运行会有一些额外步骤,按照提示下一步即可
quick start
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
添加proxy,注意Proxy name必须和 zabbix_proxy配置中的Hostname相同。其他配置默认即可。点add添加成功
.. image:: ./images/zabbix-01.png
添加host,Configuration->Hosts->Create host
.. image:: ./images/zabbix-02.png
红框都是需要填写修改的。Groups可以自己建,给设备分组。Monitored by proxy必须选择正确的proxy代理
.. image:: ./images/zabbix-03.png
点Template配置模板,模板决定了有哪些监测项。select选择一个模板,模板后续我们会自己创建,这里先选择Template OS Linux,包含了很多linux的监测项
点小add后再点大add
.. image:: ./images/zabbix-04.png
添加成功
Dashboard可以浏览状态、报警等,Edit dashboard可以自定义。比如Problems中提示我的主机掉线了。
.. image:: ./images/zabbix-05.png
如果想有目的的查询监测项状态,可以打开Monitoring->Lastest data。可以在过滤条件选择感兴趣的主机和检测项组
可以看到最后的值,可以点Graph看数值历史折线图。
.. image:: ./images/zabbix-06.png
.. image:: ./images/zabbix-07.png
这是最基本的使用,后续添加如何自定义监测项,利用api批量添加主机、动态管理监测项等功能。
修订历史
================
2018.10.17
------------
1. zabbix agent和proxy配置文件增加 AllowRoot=1,使其可以用root账户运行
2. 错别字修改,watchman改成watchmen,明明是想用DC漫画的watchmen :)
2018.10.10
------------
1. 修改了zabbix_agent安装方法。由deb包安装改成编译安装。deb版本较低,一些定义好的item不支持。改成3.4版本源码编译的,与zabbix_proxy一起安装
2018.10.09
------------
1. 新建文档,增加了watchmen各组件最基本的安装、配置、quickstart文档
.. face_camera_api documentation master file, created by
sphinx-quickstart on Fri Nov 10 10:22:03 2017.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to watchmen's documentation!
===========================================
.. toctree::
:maxdepth: 4
:numbered:
:caption: Contents:
10-summary
20-ansible
30-elk
40-zabbix
99-history
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../fonts/fontawesome-webfont.eot");src:url("../fonts/fontawesome-webfont.eot?#iefix") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff") format("woff"),url("../fonts/fontawesome-webfont.ttf") format("truetype"),url("../fonts/fontawesome-webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up{height:auto;max-height:100%}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}
This diff could not be displayed because it is too large.
/*
* doctools.js
* ~~~~~~~~~~~
*
* Sphinx JavaScript utilities for all documentation.
*
* :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
/**
* select a different prefix for underscore
*/
$u = _.noConflict();
/**
* make the code below compatible with browsers without
* an installed firebug like debugger
if (!window.console || !console.firebug) {
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
"dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
"profile", "profileEnd"];
window.console = {};
for (var i = 0; i < names.length; ++i)
window.console[names[i]] = function() {};
}
*/
/**
* small helper function to urldecode strings
*/
jQuery.urldecode = function(x) {
return decodeURIComponent(x).replace(/\+/g, ' ');
};
/**
* small helper function to urlencode strings
*/
jQuery.urlencode = encodeURIComponent;
/**
* This function returns the parsed url parameters of the
* current request. Multiple values per key are supported,
* it will always return arrays of strings for the value parts.
*/
jQuery.getQueryParameters = function(s) {
if (typeof s === 'undefined')
s = document.location.search;
var parts = s.substr(s.indexOf('?') + 1).split('&');
var result = {};
for (var i = 0; i < parts.length; i++) {
var tmp = parts[i].split('=', 2);
var key = jQuery.urldecode(tmp[0]);
var value = jQuery.urldecode(tmp[1]);
if (key in result)
result[key].push(value);
else
result[key] = [value];
}
return result;
};
/**
* highlight a given string on a jquery object by wrapping it in
* span elements with the given class name.
*/
jQuery.fn.highlightText = function(text, className) {
function highlight(node, addItems) {
if (node.nodeType === 3) {
var val = node.nodeValue;
var pos = val.toLowerCase().indexOf(text);
if (pos >= 0 &&
!jQuery(node.parentNode).hasClass(className) &&
!jQuery(node.parentNode).hasClass("nohighlight")) {
var span;
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
if (isInSVG) {
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
} else {
span = document.createElement("span");
span.className = className;
}
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
document.createTextNode(val.substr(pos + text.length)),
node.nextSibling));
node.nodeValue = val.substr(0, pos);
if (isInSVG) {
var bbox = span.getBBox();
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
rect.x.baseVal.value = bbox.x;
rect.y.baseVal.value = bbox.y;
rect.width.baseVal.value = bbox.width;
rect.height.baseVal.value = bbox.height;
rect.setAttribute('class', className);
var parentOfText = node.parentNode.parentNode;
addItems.push({
"parent": node.parentNode,
"target": rect});
}
}
}
else if (!jQuery(node).is("button, select, textarea")) {
jQuery.each(node.childNodes, function() {
highlight(this, addItems);
});
}
}
var addItems = [];
var result = this.each(function() {
highlight(this, addItems);
});
for (var i = 0; i < addItems.length; ++i) {
jQuery(addItems[i].parent).before(addItems[i].target);
}
return result;
};
/*
* backward compatibility for jQuery.browser
* This will be supported until firefox bug is fixed.
*/
if (!jQuery.browser) {
jQuery.uaMatch = function(ua) {
ua = ua.toLowerCase();
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
/(msie) ([\w.]+)/.exec(ua) ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
[];
return {
browser: match[ 1 ] || "",
version: match[ 2 ] || "0"
};
};
jQuery.browser = {};
jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
}
/**
* Small JavaScript module for the documentation.
*/
var Documentation = {
init : function() {
this.fixFirefoxAnchorBug();
this.highlightSearchWords();
this.initIndexTable();
},
/**
* i18n support
*/
TRANSLATIONS : {},
PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
LOCALE : 'unknown',
// gettext and ngettext don't access this so that the functions
// can safely bound to a different name (_ = Documentation.gettext)
gettext : function(string) {
var translated = Documentation.TRANSLATIONS[string];
if (typeof translated === 'undefined')
return string;
return (typeof translated === 'string') ? translated : translated[0];
},
ngettext : function(singular, plural, n) {
var translated = Documentation.TRANSLATIONS[singular];
if (typeof translated === 'undefined')
return (n == 1) ? singular : plural;
return translated[Documentation.PLURALEXPR(n)];
},
addTranslations : function(catalog) {
for (var key in catalog.messages)
this.TRANSLATIONS[key] = catalog.messages[key];
this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
this.LOCALE = catalog.locale;
},
/**
* add context elements like header anchor links
*/
addContextElements : function() {
$('div[id] > :header:first').each(function() {
$('<a class="headerlink">\u00B6</a>').
attr('href', '#' + this.id).
attr('title', _('Permalink to this headline')).
appendTo(this);
});
$('dt[id]').each(function() {
$('<a class="headerlink">\u00B6</a>').
attr('href', '#' + this.id).
attr('title', _('Permalink to this definition')).
appendTo(this);
});
},
/**
* workaround a firefox stupidity
* see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
*/
fixFirefoxAnchorBug : function() {
if (document.location.hash && $.browser.mozilla)
window.setTimeout(function() {
document.location.href += '';
}, 10);
},
/**
* highlight the search words provided in the url in the text
*/
highlightSearchWords : function() {
var params = $.getQueryParameters();
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
if (terms.length) {
var body = $('div.body');
if (!body.length) {
body = $('body');
}
window.setTimeout(function() {
$.each(terms, function() {
body.highlightText(this.toLowerCase(), 'highlighted');
});
}, 10);
$('<p class="highlight-link"><a href="javascript:Documentation.' +
'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>')
.appendTo($('#searchbox'));
}
},
/**
* init the domain index toggle buttons
*/
initIndexTable : function() {
var togglers = $('img.toggler').click(function() {
var src = $(this).attr('src');
var idnum = $(this).attr('id').substr(7);
$('tr.cg-' + idnum).toggle();
if (src.substr(-9) === 'minus.png')
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
else
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
}).css('display', '');
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
togglers.click();
}
},
/**
* helper function to hide the search marks again
*/
hideSearchWords : function() {
$('#searchbox .highlight-link').fadeOut(300);
$('span.highlighted').removeClass('highlighted');
},
/**
* make the url absolute
*/
makeURL : function(relativeURL) {
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
},
/**
* get the current relative url
*/
getCurrentURL : function() {
var path = document.location.pathname;
var parts = path.split(/\//);
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
if (this === '..')
parts.pop();
});
var url = parts.join('/');
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
},
initOnKeyListeners: function() {
$(document).keyup(function(event) {
var activeElementType = document.activeElement.tagName;
// don't navigate when in search box or textarea
if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') {
switch (event.keyCode) {
case 37: // left
var prevHref = $('link[rel="prev"]').prop('href');
if (prevHref) {
window.location.href = prevHref;
return false;
}
case 39: // right
var nextHref = $('link[rel="next"]').prop('href');
if (nextHref) {
window.location.href = nextHref;
return false;
}
}
}
});
}
};
// quick alias for translations
_ = Documentation.gettext;
$(document).ready(function() {
Documentation.init();
});
\ No newline at end of file
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.0',
LANGUAGE: 'None',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt'
};
\ No newline at end of file
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
/* sphinx_rtd_theme version 0.4.1 | MIT license */
/* Built 20180727 10:07 */
require=function n(e,i,t){function o(s,a){if(!i[s]){if(!e[s]){var l="function"==typeof require&&require;if(!a&&l)return l(s,!0);if(r)return r(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var u=i[s]={exports:{}};e[s][0].call(u.exports,function(n){var i=e[s][1][n];return o(i||n)},u,u.exports,n,e,i,t)}return i[s].exports}for(var r="function"==typeof require&&require,s=0;s<t.length;s++)o(t[s]);return o}({"sphinx-rtd-theme":[function(n,e,i){var jQuery="undefined"!=typeof window?window.jQuery:n("jquery");e.exports.ThemeNav={navBar:null,win:null,winScroll:!1,winResize:!1,linkScroll:!1,winPosition:0,winHeight:null,docHeight:null,isRunning:!1,enable:function(n){var e=this;void 0===n&&(n=!0),e.isRunning||(e.isRunning=!0,jQuery(function(i){e.init(i),e.reset(),e.win.on("hashchange",e.reset),n&&e.win.on("scroll",function(){e.linkScroll||e.winScroll||(e.winScroll=!0,requestAnimationFrame(function(){e.onScroll()}))}),e.win.on("resize",function(){e.winResize||(e.winResize=!0,requestAnimationFrame(function(){e.onResize()}))}),e.onResize()}))},enableSticky:function(){this.enable(!0)},init:function(n){n(document);var e=this;this.navBar=n("div.wy-side-scroll:first"),this.win=n(window),n(document).on("click","[data-toggle='wy-nav-top']",function(){n("[data-toggle='wy-nav-shift']").toggleClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift")}).on("click",".wy-menu-vertical .current ul li a",function(){var i=n(this);n("[data-toggle='wy-nav-shift']").removeClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift"),e.toggleCurrent(i),e.hashChange()}).on("click","[data-toggle='rst-current-version']",function(){n("[data-toggle='rst-versions']").toggleClass("shift-up")}),n("table.docutils:not(.field-list,.footnote,.citation)").wrap("<div class='wy-table-responsive'></div>"),n("table.docutils.footnote").wrap("<div class='wy-table-responsive footnote'></div>"),n("table.docutils.citation").wrap("<div class='wy-table-responsive citation'></div>"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var i=n(this);expand=n('<span class="toctree-expand"></span>'),expand.on("click",function(n){return e.toggleCurrent(i),n.stopPropagation(),!1}),i.prepend(expand)})},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),i=e.find('[href="'+n+'"]');if(0===i.length){var t=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(i=e.find('[href="#'+t.attr("id")+'"]')).length&&(i=e.find('[href="#"]'))}i.length>0&&($(".wy-menu-vertical .current").removeClass("current"),i.addClass("current"),i.closest("li.toctree-l1").addClass("current"),i.closest("li.toctree-l1").parent().addClass("current"),i.closest("li.toctree-l1").addClass("current"),i.closest("li.toctree-l2").addClass("current"),i.closest("li.toctree-l3").addClass("current"),i.closest("li.toctree-l4").addClass("current"))}catch(o){console.log("Error expanding nav for anchor",o)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,i=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(i),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current"),e.siblings().find("li.current").removeClass("current"),e.find("> ul li.current").removeClass("current"),e.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:e.exports.ThemeNav,StickyNav:e.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],i=0;i<e.length&&!window.requestAnimationFrame;++i)window.requestAnimationFrame=window[e[i]+"RequestAnimationFrame"],window.cancelAnimationFrame=window[e[i]+"CancelAnimationFrame"]||window[e[i]+"CancelRequestAnimationFrame"];window.requestAnimationFrame||(window.requestAnimationFrame=function(e,i){var t=(new Date).getTime(),o=Math.max(0,16-(t-n)),r=window.setTimeout(function(){e(t+o)},o);return n=t+o,r}),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(n){clearTimeout(n)})}()},{jquery:"jquery"}]},{},["sphinx-rtd-theme"]);
\ No newline at end of file
.highlight .hll { background-color: #ffffcc }
.highlight { background: #eeffcc; }
.highlight .c { color: #408090; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #007020; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */
.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #007020 } /* Comment.Preproc */
.highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */
.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #333333 } /* Generic.Output */
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0044DD } /* Generic.Traceback */
.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #007020 } /* Keyword.Pseudo */
.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #902000 } /* Keyword.Type */
.highlight .m { color: #208050 } /* Literal.Number */
.highlight .s { color: #4070a0 } /* Literal.String */
.highlight .na { color: #4070a0 } /* Name.Attribute */
.highlight .nb { color: #007020 } /* Name.Builtin */
.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
.highlight .no { color: #60add5 } /* Name.Constant */
.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #007020 } /* Name.Exception */
.highlight .nf { color: #06287e } /* Name.Function */
.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #bb60d5 } /* Name.Variable */
.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #208050 } /* Literal.Number.Bin */
.highlight .mf { color: #208050 } /* Literal.Number.Float */
.highlight .mh { color: #208050 } /* Literal.Number.Hex */
.highlight .mi { color: #208050 } /* Literal.Number.Integer */
.highlight .mo { color: #208050 } /* Literal.Number.Oct */
.highlight .sa { color: #4070a0 } /* Literal.String.Affix */
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
.highlight .sx { color: #c65d09 } /* Literal.String.Other */
.highlight .sr { color: #235388 } /* Literal.String.Regex */
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #06287e } /* Name.Function.Magic */
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
\ No newline at end of file
No preview for this file type
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
No preview for this file type
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!