<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>绿色记忆 &#187; Monitoring</title>
	<atom:link href="https://blog.gmem.cc/tag/monitoring/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.gmem.cc</link>
	<description></description>
	<lastBuildDate>Mon, 06 Apr 2026 12:46:48 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.9.14</generator>
	<item>
		<title>使用Grafana展示时间序列数据</title>
		<link>https://blog.gmem.cc/time-series-data-renderering-with-grafana</link>
		<comments>https://blog.gmem.cc/time-series-data-renderering-with-grafana#comments</comments>
		<pubDate>Tue, 09 Aug 2016 03:18:54 +0000</pubDate>
		<dc:creator><![CDATA[Alex]]></dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[K8S]]></category>
		<category><![CDATA[Monitoring]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[TSDB]]></category>

		<guid isPermaLink="false">https://blog.gmem.cc/?p=12721</guid>
		<description><![CDATA[<p>简介 Grafana是一个独立运行的系统，内置了Web服务器。它可以基于仪表盘的方式来展示、分析时间序列数据。 Grafana支持多种数据源，例如：Graphite、OpenTSDB、InfluxDB、Elasticsearch。你可以混合使用多种数据源。它对Graphite有以下增强的支持： 点击修改Metrics路径的每一个片断 快速的添加函数，支持点击函数参数以修改之 修改函数顺序 丰富的模板支持 在UI方面，Grafana具有以下特性： 丰富的、基于客户端的图表组件：Bar图、区域图、线图。支持多Y轴 支持点击/选择以缩放（Zoom）时间区间 支持混合多种图表组件，一起展示或者堆叠展示 支持定制图表的配色，支持黑白两种主题 支持拖放仪表盘面板（Panel），支持多种面板类型 支持脚本化仪表盘、仪表盘模板 通过来自数据源的事件（例如Graphite的Events），可以对仪表进行标注 核心概念 术语 说明 数据源（Data Source） Grafana支持多种存储后端，这些后端称为数据源Grafana为每种数据源开发了查询编辑器（ Query <a class="read-more" href="https://blog.gmem.cc/time-series-data-renderering-with-grafana">[...]</a></p>
<p>The post <a rel="nofollow" href="https://blog.gmem.cc/time-series-data-renderering-with-grafana">使用Grafana展示时间序列数据</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></description>
				<content:encoded><![CDATA[<div class="wri_content_clear_both"><div class="blog_h1"><span class="graybg">简介</span></div>
<p>Grafana是一个独立运行的系统，内置了Web服务器。它可以基于仪表盘的方式来展示、分析时间序列数据。</p>
<p>Grafana支持多种数据源，例如：Graphite、OpenTSDB、InfluxDB、Elasticsearch。你可以混合使用多种数据源。它对Graphite有以下增强的支持：</p>
<ol>
<li>点击修改Metrics路径的每一个片断</li>
<li>快速的添加函数，支持点击函数参数以修改之</li>
<li>修改函数顺序</li>
<li>丰富的模板支持</li>
</ol>
<p>在UI方面，Grafana具有以下特性：</p>
<ol>
<li>丰富的、基于客户端的图表组件：Bar图、区域图、线图。支持多Y轴</li>
<li>支持点击/选择以缩放（Zoom）时间区间</li>
<li>支持混合多种图表组件，一起展示或者堆叠展示</li>
<li>支持定制图表的配色，支持黑白两种主题</li>
<li>支持拖放仪表盘面板（Panel），支持多种面板类型</li>
<li>支持脚本化仪表盘、仪表盘模板</li>
<li>通过来自数据源的事件（例如Graphite的Events），可以对仪表进行标注</li>
</ol>
<div class="blog_h2"><span class="graybg">核心概念</span></div>
<table class=" fixed-word-wrap full-width">
<thead>
<tr>
<td style="width: 25%; text-align: center;">术语</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>数据源（Data Source）</td>
<td>Grafana支持多种存储后端，这些后端称为数据源<br />Grafana为每种数据源开发了查询编辑器（ Query Editor）以匹配后端的特点</td>
</tr>
<tr>
<td>组织（Organization）</td>
<td>引入组织机构的概念，以便一个Grafana实例可以被多个可能不受信任的组织使用</td>
</tr>
<tr>
<td>用户（User）</td>
<td>Grafana用户可以归属于1个或者多个组织</td>
</tr>
<tr>
<td>行（Row）</td>
<td>仪表盘中的逻辑分段</td>
</tr>
<tr>
<td>面板（Panel）</td>
<td>
<p>仪表盘中最基本的可视化单元，每个面板提供查询编辑器。Grafana目前内置了Graph, Singlestat, Dashlist和Text这几种面板</p>
<p>每种面板都具有一些样式、格式化选项，你可以利用它们设计出漂亮的图表</p>
<p>可以通过拖拽，在仪表盘中重新放置面板，也可以缩放其大小</p>
</td>
</tr>
<tr>
<td>查询编辑器（Query Editor）</td>
<td>依据特定数据源设计的表单，用以查询需要的Metrics</td>
</tr>
<tr>
<td>仪表盘（Dashboard）</td>
<td>一系列面板的集合，这些面板被组织在一个或者多个行中</td>
</tr>
</tbody>
</table>
<div class="blog_h1"><span class="graybg">安装与配置</span></div>
<div class="blog_h2"><span class="graybg">安装Grafana</span></div>
<div class="blog_h3"><span class="graybg">独立安装</span></div>
<p>依次执行下面的命令完成安装：</p>
<pre class="crayon-plain-tag"># CentOS
yum install initscripts fontconfig
wget https://grafanarel.s3.amazonaws.com/builds/grafana-3.1.1-1470047149.x86_64.rpm
rpm -Uvh grafana-3.1.1-1470047149.x86_64.rpm</pre>
<p>设置为开机启动：</p>
<pre class="crayon-plain-tag">/bin/systemctl daemon-reload
/bin/systemctl enable grafana-server.service</pre>
<p>启动服务：</p>
<pre class="crayon-plain-tag">systemctl start grafana-server.service</pre>
<div class="blog_h3"><span class="graybg">K8S</span></div>
<pre class="crayon-plain-tag">helm repo update gmem
helm del --purge grafana
helm install gmem/grafana --name grafana --namespace kube-system

# 执行下面的命令获得初始密码
kubectl get secret --namespace kube-system grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo</pre>
<p>值覆盖情况参考：<a href="https://github.com/gmemcc/charts/tree/master/grafana">https://github.com/gmemcc/charts/tree/master/grafana</a></p>
<div class="blog_h3"><span class="graybg">常用插件</span></div>
<pre class="crayon-plain-tag">grafana-cli plugins install grafana-kubernetes-app
grafana-cli plugins install natel-plotly-panel
grafana-cli plugins install kentik-app
grafana-cli plugins install alexanderzobnin-zabbix-app
grafana-cli plugins install grafana-worldmap-panel
grafana-cli plugins install grafana-clock-panel
grafana-cli plugins install grafana-piechart-panel
grafana-cli plugins install percona-percona-app
grafana-cli plugins install digrich-bubblechart-panel
grafana-cli plugins install digiapulssi-breadcrumb-panel
grafana-cli plugins install petrslavotinek-carpetplot-panel
grafana-cli plugins install neocat-cal-heatmap-panel
grafana-cli plugins install briangann-gauge-panel
grafana-cli plugins install jdbranham-diagram-panel</pre>
<p>安装插件后，需要重新启动Grafana服务：<pre class="crayon-plain-tag">service grafana-server restart</pre></p>
<div class="blog_h2"><span class="graybg">配置文件</span></div>
<div class="blog_h3"><span class="graybg">环境变量配置</span></div>
<p>当Grafana服务启动时，会读取<pre class="crayon-plain-tag">/etc/sysconfig/grafana-server</pre> 中的环境变量。你可以修改日志目录、数据存储目录等变量。</p>
<p>默认的，日志文件存储目录为/var/log/grafana，数据存储目录为/var/lib/grafana。默认使用SQLite数据库/var/lib/grafana/grafana.db。</p>
<div class="blog_h3"><span class="graybg">主配置文件</span></div>
<p>如果基于deb/rpm包进行安装，则主配置文件的位置为：<pre class="crayon-plain-tag">/etc/grafana/grafana.ini</pre> 。使用命令行参数 --config可以覆盖此位置。主配置文件说明如下：</p>
<table class=" fixed-word-wrap full-width">
<thead>
<tr>
<td style="width: 90px; text-align: center;">段</td>
<td style="width: 25%; text-align: center;">配置项</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td> </td>
<td>instance_name</td>
<td>Grafana服务的名称，默认为${HOSTNAME}，即环境变量HOMENAME的值</td>
</tr>
<tr>
<td rowspan="2">[paths]</td>
<td>data</td>
<td>在何处存放SQLite3数据库文件、基于文件的Session，以及其它数据</td>
</tr>
<tr>
<td>logs</td>
<td>在何处存放日志</td>
</tr>
<tr>
<td rowspan="5">[server]</td>
<td>http_addr</td>
<td>内置Web服务的监听地址，默认绑定所有地址</td>
</tr>
<tr>
<td>http_port</td>
<td>内置Web服务的监听端口，默认3000</td>
</tr>
<tr>
<td>protocol</td>
<td>http或者https</td>
</tr>
<tr>
<td>cert_file</td>
<td>https证书文件</td>
</tr>
<tr>
<td>cert_key</td>
<td>https证书密钥</td>
</tr>
<tr>
<td rowspan="6">[database]</td>
<td>type</td>
<td>数据库类型：mysql、postgres或者sqlite3</td>
</tr>
<tr>
<td>path</td>
<td>sqlite3数据库文件路径</td>
</tr>
<tr>
<td>host</td>
<td>mysql或postgres的主机:端口，例如<pre class="crayon-plain-tag">127.0.0.1:3306</pre> </td>
</tr>
<tr>
<td>name</td>
<td>数据库名称默认grafana</td>
</tr>
<tr>
<td>user</td>
<td>数据库用户</td>
</tr>
<tr>
<td>password</td>
<td>数据库密码</td>
</tr>
<tr>
<td rowspan="5">[security]</td>
<td>admin_user</td>
<td>Grafana管理员用户，默认admin</td>
</tr>
<tr>
<td>admin_password</td>
<td>Grafana管理员密码，默认admin</td>
</tr>
<tr>
<td>login_remember_days</td>
<td>记住登陆的最大天数</td>
</tr>
<tr>
<td>secret_key</td>
<td>用于签名记住登陆的Cookie</td>
</tr>
<tr>
<td>disable_gravatar</td>
<td>禁用头像</td>
</tr>
<tr>
<td>[log]</td>
<td>mode</td>
<td>日志记录方式，console、file或者syslog。可以用空格分开多个方式</td>
</tr>
<tr>
<td> </td>
<td>level</td>
<td>日志记录级别，debug、info、warn、error、critical</td>
</tr>
</tbody>
</table>
<div class="blog_h1"><span class="graybg">使用Grafana</span></div>
<p>使用Grafana的日常工作包括：用户管理、系统管理、仪表盘设计、数据源管理，等等。所有这些工作都在Web界面<pre class="crayon-plain-tag">http://GRAFANA_HOST:3000</pre>  完成。该界面比较友好，适合最终用户。</p>
<div class="blog_h2"><span class="graybg">配置Graphite数据源</span></div>
<p>点击Web界面左上角的图标，下拉列表中选择Data Sources，即可管理数据源。</p>
<p>点击Add data source按钮，添加新的数据源，参考下图：</p>
<p><img class="aligncenter size-full wp-image-12739" src="https://blog.gmem.cc/wp-content/uploads/2016/08/grafana-ds-cfg.png" alt="grafana-ds-cfg" width="478" height="440" /></p>
<p>注意Access设置成proxy，则数据通过Grafana间接获取，否则，数据直接通过客户端获取。添加Graphite数据源后，可以点击Dashboards选项卡，获得其预置的仪表盘Graphite Carbon Metrics并导入到Grafana中。</p>
<div class="blog_h2"><span class="graybg">设计仪表盘</span></div>
<p>点击Web界面左上角的图标，下拉列表中选择Dashboards  ⇨ New，可以新建仪表盘。在新仪表盘中，点击左侧的绿条，可以添加新的面板；点击右下侧ADD ROW按钮则可以新建一行。</p>
<p>&nbsp;</p>
</div><p>The post <a rel="nofollow" href="https://blog.gmem.cc/time-series-data-renderering-with-grafana">使用Grafana展示时间序列数据</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.gmem.cc/time-series-data-renderering-with-grafana/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Graphite学习笔记</title>
		<link>https://blog.gmem.cc/graphite-study-note</link>
		<comments>https://blog.gmem.cc/graphite-study-note#comments</comments>
		<pubDate>Mon, 11 Jul 2016 08:33:51 +0000</pubDate>
		<dc:creator><![CDATA[Alex]]></dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Monitoring]]></category>
		<category><![CDATA[TSDB]]></category>
		<category><![CDATA[学习笔记]]></category>

		<guid isPermaLink="false">https://blog.gmem.cc/?p=12245</guid>
		<description><![CDATA[<p>简介 Graphite是一个开源项目，可以作为时间序列数据库（TSDB）使用，当你需要存储随着时间变化的数值时，应当考虑使用时间序列数据库。 除了数据的存储、查询外，Graphite还提供数据可视化（UI层）功能，它可以很好的在廉价的硬件上运行。你可以使用Graphite来监控网站、应用程序、网络服务器等的性能数据（Metrics），轻松实现基于时间维的分析。 Graphite本身不负责性能数据的采集，但是它提供了简单易用的接口，公共这些接口你可以把基于数字的性能数据存储到Graphite中。 术语 术语 说明 datapoint 数据点，存放在timestamp bucket中的数值。timestamp bucket中的默认值是None function 时间序列（ time-series）函数，用来转换、合并、计算多个series resolution 分辨率，也称precision。序列中，一个数据点所跨越（代表）的秒数。分辨率确定了存储数据点频率如果一个series每N秒存储一个数据点，则其分辨率为N retention 驻留，series中包含的数据点的个数 series 一已命名的数据点的集合，每个series由其名称唯一确定，名称由点号分隔的字符串组成也称为Metrics、Metric series series <a class="read-more" href="https://blog.gmem.cc/graphite-study-note">[...]</a></p>
<p>The post <a rel="nofollow" href="https://blog.gmem.cc/graphite-study-note">Graphite学习笔记</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></description>
				<content:encoded><![CDATA[<div class="wri_content_clear_both"><div class="blog_h1"><span class="graybg">简介</span></div>
<p><a href="http://graphiteapp.org/">Graphite</a>是一个开源项目，可以作为时间序列数据库（TSDB）使用，当你需要存储<span style="background-color: #c0c0c0;">随着时间变化的数值</span>时，应当考虑使用时间序列数据库。</p>
<p>除了<span style="background-color: #c0c0c0;">数据的存储、查询</span>外，Graphite还提供<span style="background-color: #c0c0c0;">数据可视化</span>（UI层）功能，它可以很好的在廉价的硬件上运行。你可以使用Graphite来监控网站、应用程序、网络服务器等的性能数据（Metrics），轻松实现基于时间维的分析。</p>
<p>Graphite本身不负责性能数据的采集，但是它提供了简单易用的接口，公共这些接口你可以把基于数字的性能数据存储到Graphite中。</p>
<div class="blog_h2"><span class="graybg">术语</span></div>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 20%; text-align: center;">术语</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>datapoint</td>
<td>数据点，存放在timestamp bucket中的数值。timestamp bucket中的默认值是None</td>
</tr>
<tr>
<td>function</td>
<td>时间序列（ time-series）函数，用来转换、合并、计算多个series</td>
</tr>
<tr>
<td>resolution</td>
<td>分辨率，也称precision。序列中，一个数据点所跨越（代表）的秒数。分辨率确定了存储数据点频率<br />如果一个series每N秒存储一个数据点，则其分辨率为N</td>
</tr>
<tr>
<td>retention</td>
<td>驻留，series中包含的数据点的个数</td>
</tr>
<tr>
<td>series</td>
<td>一已命名的数据点的集合，每个series由其名称唯一确定，名称由点号分隔的字符串组成<br />也称为Metrics、Metric series</td>
</tr>
<tr>
<td>series list</td>
<td>包含通配符的series名称，匹配多个series</td>
</tr>
<tr>
<td>target</td>
<td>图形展示时的数据源，可以是metrics名称、metrics通配符、或者基于前两者的函数调用表达式</td>
</tr>
<tr>
<td>timestamp</td>
<td>数据点所关联的时间，1970-01-01到产生数据点那一刻的秒数</td>
</tr>
<tr>
<td>timestamp bucket</td>
<td>经过舍入后，能够整除分辨率的timestamp</td>
</tr>
</tbody>
</table>
<div class="blog_h2"><span class="graybg">架构</span></div>
<p>Graphite由三个组件构成：</p>
<ol>
<li>Carbon：一个基于<a href="https://twistedmatrix.com/">Twisted</a>（Python事件驱动网络框架）的守护程序，负责监听外部的时间序列数据</li>
<li>Whisper：一个简单的存储时间序列数据的数据库，设计上和<a href="http://oss.oetiker.ch/rrdtool/">RRDtool</a>类似 </li>
<li>Graphite-Web：一个基于<a href="https://www.djangoproject.com/">Django</a>（Python Web框架）的Web应用，使用<a href="https://www.cairographics.org/">Cairo</a>（一个2D图形库）来渲染性能数据的图表，使用<a href="https://www.sencha.com/products/extjs/">ExtJS</a>作为基础UI框架</li>
</ol>
<p>下面是Graphite的架构图：<img class="aligncenter size-full wp-image-12262" src="https://blog.gmem.cc/wp-content/uploads/2016/07/graphite-arch.png" alt="graphite-arch" width="100%" /></p>
<p>一旦你把数据送给Carbon，它就立刻可以在Webapp的图表中显示，因为数据在被写入文件系统之前，会驻留在缓存中。</p>
<p>除了使用Graphite Webapp，你也可以通过URL API，将图表嵌入到自己的应用程序中去。如何使用Graphite</p>
<div class="blog_h2"><span class="graybg">如何使用Graphite</span></div>
<p>使用Graphite来监控你的性能数据，你需要完成以下工作：</p>
<ol>
<li>理解Graphite组件的职责和相互关系</li>
<li>安装Graphite及其依赖</li>
<li>基础的配置，让Graphite能运行起来</li>
<li>设计Metrics路径</li>
<li>配置Metrics的驻留规则、聚合规则等</li>
<li>向Graphite发送Metrics</li>
<li>从Graphite获取Metrics并展示</li>
</ol>
<div class="blog_h3"><span class="graybg">Metrics路径设计</span></div>
<p>Metrics路径由点号分隔的字符串构成，类似于Python的包名称。路径是Metrics的标识。</p>
<p>你应当仔细的设计此路径的命名空间，以反映出所有Metrics之间的层次关系。例如servers.zircon.cpu，这个三级路径设计中，第一级表示设备类别，第二级表示设备名称，第三级表示监测点类型。</p>
<div class="blog_h1"><span class="graybg">理解Graphite组件</span></div>
<div class="blog_h2"><span class="graybg">Carbon</span></div>
<p>Carbon由一系列的守护进程组成，这些守护进程共同组成Graphite的存储后端。在最小化的安装下，只有一个守护进程carbon-cache.py。根据需要你可以启用carbon-relay.py、carbon-aggregator.py以便实现Metrics分发、定制聚合规则。各Carbon守护进程简介如下：</p>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 20%; text-align: center;">守护进程</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>缓存进程<br />carbon-cache</td>
<td>
<p>缓存进程的程序文件是carbon-cache.py。它通过多种协议接收Metrics，然后尽可能高效的将其写入磁盘。从实现角度来说，缓存进程先把Metrics存放在RAM中，然后定期的通过whisper库进行入库</p>
<p>缓存进程提供一个查询服务供Graphite Webapp使用，用来快速获取位于内存中的Metrics数据点</p>
<p>要定制此进程的行为，可以修改carbon.conf的[cache]段、storage-schemas.conf、storage-aggregation.conf</p>
</td>
</tr>
<tr>
<td>中继进程<br />carbon-relay</td>
<td>
<p>该进程可以担任这两个职责之一：复制（<span style="color: #404040;">replication</span>）和分片（<span style="color: #404040;">sharding</span>）</p>
<p>要定制此进程的行为，可以修改carbon.conf的[relay]段、relay-rules.conf</p>
</td>
</tr>
<tr>
<td>前置聚合进程<br />carbon-aggregator</td>
<td>
<p>前置于缓存进程运行，能够在存入whisper之前，缓冲、聚合Metrics。当不需要细粒度的数据时启用该进程，可以减少I/O和.wsp文件的大小</p>
<p>要定制此进程的行为，可以修改carbon.conf的[aggregator]段、aggregation-rules.conf</p>
</td>
</tr>
</tbody>
</table>
<div class="blog_h2"><span class="graybg">Whisper</span></div>
<p>Whisper是一个固定大小（fixed-size）的数据库，其设计和用途与RRD（round-robin-database）类似。它能提供快速、可靠的数值数据的存储。</p>
<p>Whisper能够对最近的数据进行高分辨率的存储，而对久远的历史数据，自动降低其存储精度（减少样本数量）。</p>
<p>在大多数场景下，Whisper有足够好的性能。它比RRDtool慢，主要原因是Whisper基于Python编写，这个性能差异很小，通常不需要考虑。</p>
<p>Whisper数据库以文件方式存放在磁盘上，扩展名.wsp。Carbon会为每个Metrics创建一个.wsp文件，路径的最后一节作为文件的basename，路径的其它部分形成目录层次。</p>
<div class="blog_h3"><span class="graybg">数据点</span></div>
<p>在Whisper中存储的每一个数值，称为数据点（Data Points）。</p>
<p>在磁盘上，数据点以大端、双精度浮点数存储。每个数据还附带一个时间戳信息，时间戳为1970-01-01到数据采集时间的秒数。</p>
<div class="blog_h3"><span class="graybg">归档</span></div>
<p>一个Whisper数据库文件可以包含一个或者多个“归档”，归档是数据文件中的逻辑段。</p>
<p>每个归档具有不同的数据分辨率（一定时间段内，数据点数量越多，则分辨率越高）。归档以最高分辨率（最小驻留时间） —— 最低分辨率（最长驻留时间）的顺序，在数据库文件中顺序排列。</p>
<p>为了精确的从高分辨率向低分辨率的归档聚合，高分辨率归档和它之后的低分辨率归档，其分辨率应当具有整除关系。例如，第一个归档分辨率为60秒/数据点，那么第二个归档可以是300秒/数据点，第三个归档可以是3600秒/数据点。</p>
<p>一个数据库的总计驻留时间（存放的数据点跨越的时间），由最长驻留时间的（最后一个）归档确定。因为之前的那些归档，时间区间都是它的子区间。</p>
<div class="blog_h3"><span class="graybg">聚合</span></div>
<p>把数据点转移到低分辨率归档时，面临着如何把多个数据点转变为单个数据点的问题。Whisper支持average、sum、last、max、min等聚合函数。</p>
<p>注意，这里的聚合和Carbon提供的前置聚合不是一回事。</p>
<div class="blog_h3"><span class="graybg">多归档的读写策略</span></div>
<p>当Whisper向一个多归档数据写入Metrics时，数据点将被同时写入到所有的归档中。这意味着聚合动作随时可能发生。</p>
<p>当从Whisper中获取数据时，第一个能完整覆盖所需区间的归档被使用。</p>
<div class="blog_h3"><span class="graybg">磁盘空间利用率问题</span></div>
<p>Whisper的磁盘利用效率不高，因为：</p>
<ol>
<li>每个数据点要附加一个时间戳信息</li>
<li>由于归档的时间区间有重叠，因此数据存在冗余</li>
<li>归档中的时间槽位（time-slots）总是占据着磁盘空间，不管有没有值存储在其中</li>
</ol>
<p>这些特征是故意的，主要出于性能方面的考虑。</p>
<div class="blog_h3"><span class="graybg">Whisper与RRD的区别</span></div>
<ol>
<li>RRD不能去填充以前的时间槽位。这意味着每一条数据都必须是更新的，不会“补录”</li>
<li>RRD不能很好的支持不规则的数据更新。如果RRD接收到一条数据，但是后续数据没有到来，则前一条数据可能丢失</li>
</ol>
<div class="blog_h1"><span class="graybg">安装与配置</span></div>
<div class="blog_h2"><span class="graybg">检查并安装依赖</span></div>
<div class="blog_h3"><span class="graybg">检查依赖</span></div>
<pre class="crayon-plain-tag">git clone https://github.com/graphite-project/graphite-web.git
graphite-web/check-dependencies.py
# 根据输出的提示来判断缺少哪些依赖，然后安装</pre>
<div class="blog_h3"><span class="graybg">安装依赖</span></div>
<pre class="crayon-plain-tag">yum -y install python-devel     # Carbon 依赖于 Python Development Headers

yum install pycairo             # Cairo库的Python绑定

pip install django              # Web框架
pip install django-tagging

pip install pytz

yum install fontconfig

yum install -y memcached        # 可选，缓存支持
pip install python-memcached    
                                # 可选，RDDTool
yum install cairo-devel libxml2-devel pango-devel pango libpng-devel freetype freetype-devel libart_lgpl-devel rrdtool-devel

pip install python-rrdtool      # 可选，RRD支持

pip install whitenoise          # 用于Web静态文件处理

yum install pyOpenSSL           # OpenSSL的Python绑定
pip install service_identity    # SSL相关</pre>
<div class="blog_h2"><span class="graybg">通过pip安装Craphite组件</span></div>
<pre class="crayon-plain-tag">pip install https://github.com/graphite-project/ceres/tarball/master
pip install whisper
pip install carbon
pip install graphite-web</pre>
<div class="blog_h3"><span class="graybg">设置目录权限</span></div>
<pre class="crayon-plain-tag">sudo groupadd graphite
sudo usermod -a -G graphite root
sudo usermod -a -G graphite apache
sudo chgrp -R graphite /opt/graphite/storage
sudo chmod -R 770 /opt/graphite/storage</pre>
<div class="blog_h2"><span class="graybg">默认安装布局</span></div>
<p>Whisper被安装到Python全局site-packages目录，另外两个Graphite组件安装到<pre class="crayon-plain-tag">/opt/graphite</pre>，该目录（记为<pre class="crayon-plain-tag">$GRAPHITE_ROOT</pre>  ）的布局如下：</p>
<table class=" fixed-word-wrap full-width">
<thead>
<tr>
<td style="width: 20%; text-align: center;">子目录</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>bin</td>
<td>一些脚本</td>
</tr>
<tr>
<td>conf</td>
<td>配置文件</td>
</tr>
<tr>
<td>lib</td>
<td>一些Python依赖库，Carbon的PYTHONPATH</td>
</tr>
<tr>
<td>storage</td>
<td>存储SQLite数据文件。该目录记为<pre class="crayon-plain-tag">$STORAGE_DIR</pre> </td>
</tr>
<tr>
<td>storage/log</td>
<td>Carbon和Graphite-web的日志</td>
</tr>
<tr>
<td>storage/rrd</td>
<td>待读取的RRD文件</td>
</tr>
<tr>
<td>storages/whisper</td>
<td>Whisper数据文件</td>
</tr>
<tr>
<td>webapp</td>
<td>
<p>Graphite-web的Web资源、PYTHONPATH</p>
</td>
</tr>
<tr>
<td>webapp/graphite</td>
<td>
<p>标准的Django工程结构<br />local_settings.py所在位置</p>
</td>
</tr>
<tr>
<td>webapp/content</td>
<td>静态Web资源</td>
</tr>
</tbody>
</table>
<div class="blog_h2"><span class="graybg">配置Graphite-web数据库</span></div>
<p>你需要让Graphite-web的底层框架Django执行数据库的初始化。此数据库被用来存放用户设置、仪表盘，以及支持事件功能。</p>
<p>默认情况下，Graphite-web使用位于$STORAGE_DIR/graphite.db的SQLite数据库。如果要运行多个Graphite-web实例，则必须使用MySQL等数据库以便多个实例可以共享数据。 </p>
<div class="blog_h3"><span class="graybg">配置SQLite</span></div>
<p>执行下面的命令初始化SQLite数据库：</p>
<pre class="crayon-plain-tag">PYTHONPATH=/opt/graphite/webapp django-admin.py migrate --settings=graphite.settings --run-syncdb
# 完毕后 $STORAGE_DIR/graphite.db自动创建</pre>
<p>Django应用需要在Web服务器中运行，Web服务器需要对SQLite数据文件有读写权限。假设你使用Apache2，运行Apache2的用户为apache，则需要执行：</p>
<pre class="crayon-plain-tag">sudo chgrp graphite /opt/graphite/storage/graphite.db</pre>
<div class="blog_h2"><span class="graybg">配置WebApp</span></div>
<div class="blog_h3"><span class="graybg">httplocal_settings.py</span></div>
<p>Graphite不建议修改settings.py，所有定制化的配置，都应该在此文件中进行。常用的设置项如下表：</p>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 30%; text-align: center;">设置项</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>TIME_ZONE</td>
<td>时区，规范化的<a href="https://en.wikipedia.org/wiki/Tz_database#Names_of_time_zones">时区名称</a>。默认America/Chicago</td>
</tr>
<tr>
<td>DEBUG</td>
<td>是否启用Django错误页面。默认False</td>
</tr>
<tr>
<td>FLUSHRRDCACHED</td>
<td>如果设置，在从RRD文件获取数据前，执行<pre class="crayon-plain-tag">rrdtool flushcached</pre> <br />设置为rrdcached的地址或者Socket（例如unix:/var/run/rrdcached.sock）</td>
</tr>
<tr>
<td>MEMCACHE_HOSTS</td>
<td>如果设置，启用对计算出的目标、渲染过的图片的缓存。如果运行Graphite Web应用集群，则每个实例应当设置为一样的值<br />设置为memcached主机的数组，例如：['10.10.10.10:11211', '10.10.10.12:11211']</td>
</tr>
<tr>
<td>DEFAULT_CACHE_DURATION</td>
<td>数据、图片默认缓存时间。默认值60</td>
</tr>
<tr>
<td>DEFAULT_CACHE_POLICY</td>
<td>默认缓存策略。为元组的数组，每个元组指定最小查询时间、数据缓存时间<br />通过该设置，你可以让大的查询缓存更长时间。例如：<br />
<pre class="crayon-plain-tag">DEFAULT_CACHE_POLICY = [
    (0, 60), # 默认缓存60秒
    (7200, 120) # &gt;= 2小时以上时间范围的查询，缓存2分钟
] </pre>
</td>
</tr>
<tr>
<td>GRAPHITE_ROOT</td>
<td>Graphite的安装目录。默认/opt/graphite </td>
</tr>
<tr>
<td>CONF_DIR</td>
<td>额外Graphite-web配置文件目录。默认/opt/graphite/conf</td>
</tr>
<tr>
<td>STORAGE_DIR</td>
<td>存储目录。WHISPER_DIR、RRD_DIR、LOG_DIR、INDEX_FILE参照的基准目录</td>
</tr>
<tr>
<td>STATIC_ROOT</td>
<td>Graphite-web的静态文件目录。默认/opt/graphite/static<br />该目录一开始会不存在，你需要在设置STATIC_ROOT、STATIC_URL后执行：<br />
<pre class="crayon-plain-tag"># 如果报Unknown command: 'collectstatic' 说明INSTALLED_APPS中缺少
# django.contrib.staticfiles	
PYTHONPATH=/opt/graphite/webapp django-admin.py collectstatic 
    --noinput --settings=graphite.settings</pre></p>
<p>你还需要在Web服务器中把/static这个前缀映射到此目录，里Apache2为例：</p>
<pre class="crayon-plain-tag">Alias /static/ "/opt/graphite/static"</pre>
<p>如果你安装了whitenoise包，静态文件可以直接由Graphite webapp来处理，不通过Web服务器</p>
</td>
</tr>
<tr>
<td>DASHBOARD_CONF</td>
<td>仪表盘的配置文件。默认$CONF_DIR/dashboard.conf</td>
</tr>
<tr>
<td>GRAPHTEMPLATES_CONF</td>
<td>图形模板的配置文件。默认$CONF_DIR/graphTemplates.conf </td>
</tr>
<tr>
<td>WHISPER_DIR</td>
<td> Whisper数据文件目录。默认/opt/graphite/storage/whisper</td>
</tr>
<tr>
<td>RRD_DIR</td>
<td> RRD数据文件目录。默认/opt/graphite/storage/rrd</td>
</tr>
<tr>
<td>LOG_DIR</td>
<td> Graphite webapp的日志目录。默认$TORAGE_DIR/log/webapp</td>
</tr>
<tr>
<td>INDEX_FILE</td>
<td>搜索索引位置。默认/opt/graphite/storage/index<br />由build-index.sh脚本生成，运行Web应用的用户必须有写权限</td>
</tr>
<tr>
<td>URL_PREFIX</td>
<td>URL前缀</td>
</tr>
</tbody>
</table>
<p>我们的配置如下：</p>
<pre class="crayon-plain-tag"># 如果不设置，会导致报错：AttributeError: 'Settings' object has no attribute 'URL_PREFIX
URL_PREFIX = '/'</pre>
<div class="blog_h3"><span class="graybg">安装Apache和mod_wsgi</span></div>
<p>多种Web服务器可以用于运行基于Django的Web应用，这里我们选择Apache2。在CentOS下安装Apache2：</p>
<pre class="crayon-plain-tag">yum install httpd</pre>
<p>要让Apache2能够运行Python Web应用，需要安装模块mod_wsgi。参考<a href="https://blog.gmem.cc/django-study-note#mod-wsgi">Django学习笔记</a>完成mod_wsgi的构建与安装。</p>
<div class="blog_h3"><span class="graybg">配置Graphite虚拟主机</span></div>
<p>在/opt/graphite/examples/目录下，example-graphite-vhost.conf可以作为Apache虚拟主机的模板，复制该文件到/etc/httpd/conf.d/目录下，然后修改：</p>
<pre class="crayon-plain-tag">&lt;IfModule !wsgi_module.c&gt;
    LoadModule wsgi_module modules/mod_wsgi.so
&lt;/IfModule&gt;
WSGISocketPrefix run/wsgi
&lt;VirtualHost *:7767&gt;
        ServerName xcentos7.local
        DocumentRoot "/opt/graphite/webapp"
        ErrorLog /opt/graphite/storage/log/webapp/error.log
        CustomLog /opt/graphite/storage/log/webapp/access.log common
        WSGIDaemonProcess graphite processes=5 threads=5 display-name='%{GROUP}' inactivity-timeout=120
        WSGIProcessGroup graphite
        WSGIApplicationGroup %{GLOBAL}
        WSGIImportScript /opt/graphite/conf/graphite.wsgi process-group=graphite application-group=%{GLOBAL}
        WSGIScriptAlias / /opt/graphite/conf/graphite.wsgi
        Alias /content/ /opt/graphite/webapp/content/
        &lt;Directory /opt/graphite/webapp/content/&gt;
            Require all granted
        &lt;/Directory&gt;
        &lt;Directory /opt/graphite/conf/&gt;
            Require all granted
        &lt;/Directory&gt;
&lt;/VirtualHost&gt;</pre>
<div class="blog_h3"><span class="graybg">验证配置</span></div>
<p>如果配置没有问题，启动Web服务器后访问：<pre class="crayon-plain-tag">http://GRAPHITE_HOST:GRAPHITE_PORT/render</pre> ，会显示一张330x250大小的图片，上面写着No Data。</p>
<div class="blog_h2"><span class="graybg">配置Carbon</span></div>
<p>所有Carbon守护进程可以基于多种通信协议，监听时间序列数据，并且对数据进行不同的处理。</p>
<p>Carbon的配置文件位于/opt/graphite/conf/目录，默认情况下没有预置的配置文件，但是Graphite提供了若干配置文件样例。你可以复制这些配置文件并定制：</p>
<pre class="crayon-plain-tag">pushd /opt/graphite/conf
cp carbon.conf.example carbon.conf
cp storage-schemas.conf.example storage-schemas.conf</pre>
<div class="blog_h3"><span class="graybg">carbon.conf</span></div>
<p>这是主配置文件，为每个Carbon守护进程定义配置项。该配置文件按段区分不同守护进程的配置：</p>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 14%; text-align: center;">配置项段</td>
<td style="width: 30%; text-align: center;">配置项</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="17">[cache]   </td>
<td>
<p><span style="font-size: 8pt;">ENABLE_LOGROTATION</span></p>
</td>
<td>
<p> 是否启用每日的日志轮转，启用后每天创建一个日志</p>
</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">USER </span></td>
<td>运行该进程的用户 </td>
</tr>
<tr>
<td><span style="font-size: 8pt;">MAX_CACHE_SIZE</span></td>
<td>内存中Metrics缓存的最大尺寸</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">MAX_UPDATES_PER_SECOND</span></td>
<td>每秒执行whisper的update_many()调用的最大次数，对应磁盘IO的次数，该配置项避免过度的磁盘使用</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">MAX_CREATES_PER_MINUTE</span></td>
<td>对每分钟最多创建的.wsp文件的个数进行软限制。超过限制的新Metrics对应的.wsp文件不会被创建，Metrics也被丢弃</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">LINE_RECEIVER_INTERFACE</span></td>
<td rowspan="2">接收文本格式数据的监听端口，默认0.0.0.0:2003</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">LINE_RECEIVER_PORT</span></td>
</tr>
<tr>
<td><span style="font-size: 8pt;">PICKLE_RECEIVER_INTERFACE<br /></span></td>
<td rowspan="2">接收Pickle格式数据的监听端口，默认0.0.0.0:2004</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">PICKLE_RECEIVER_PORT</span></td>
</tr>
<tr>
<td><span style="font-size: 8pt;">ENABLE_UDP_LISTENER</span></td>
<td>是否启用UDP监听</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">UDP_RECEIVER_INTERFACE</span></td>
<td rowspan="2">通过UDP接收数据的监听端口，默认0.0.0.0:2003</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">UDP_RECEIVER_PORT</span></td>
</tr>
<tr>
<td><span style="font-size: 8pt;">LOG_LISTENER_CONNECTIONS</span></td>
<td>对成功的连接请求记录日志</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">CACHE_QUERY_INTERFACE</span></td>
<td rowspan="2">缓存查询服务的监听端口，默认0.0.0.0：7002</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">CACHE_QUERY_PORT</span></td>
</tr>
<tr>
<td><span style="font-size: 8pt;">USE_FLOW_CONTROL</span></td>
<td>是否进行流量控制。如果设置为True，那么达到MAX_CACHE_SIZE后，会暂停接收数据，直到缓存占用小于MAX_CACHE_SIZE的95%</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">CACHE_WRITE_STRATEGY</span></td>
<td>按何种顺序将缓存从内存中移除，并写入到磁盘的策略：sorted、max、naive</td>
</tr>
<tr>
<td rowspan="13">[relay]</td>
<td><span style="font-size: 8pt;">LINE_RECEIVER_INTERFACE</span></td>
<td rowspan="2">
<p>接收文本格式数据的监听端口，默认0.0.0.0:2003</p>
</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">LINE_RECEIVER_PORT</span></td>
</tr>
<tr>
<td><span style="font-size: 8pt;">PICKLE_RECEIVER_INTERFACE</span></td>
<td rowspan="2">接收Pickle格式数据的监听端口，默认0.0.0.0:2004</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">PICKLE_RECEIVER_PORT</span></td>
</tr>
<tr>
<td><span style="font-size: 8pt;">LOG_LISTENER_CONNECTIONS</span></td>
<td>对成功的连接请求记录日志</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">USER</span></td>
<td>运行该进程的用户</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">RELAY_METHOD</span></td>
<td>
<p>设置为rules：则该进程可以代替carbon-cache.py，然后中继所有Metrics给多个作为后端的carbon-cache.py</p>
<p>设置为consistent-hashing：则依据DESTINATIONS定义的分片策略，分发Metrics给多个作为后端的carbon-cache.py</p>
</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">REPLICATION_FACTOR</span></td>
<td>RELAY_METHOD=consistent-hashing时，可以指定N，从而把每个数据点分发到N台机器</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">DESTINATIONS</span></td>
<td>转发的目标，每个目标的格式是IP:PORT<br />RELAY_METHOD=rules时relay-rules.conf每个servers都要在此字段定义</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">MAX_DATAPOINTS_PER_MESSAGE</span></td>
<td>单个转发报文中包含的数据点的最大个数</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">MAX_QUEUE_SIZE</span></td>
<td>待转发的队列最大包含多少数据点</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">QUEUE_LOW_WATERMARK_PCT</span></td>
<td>队列低水位的百分比，0-1之间</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">USE_FLOW_CONTROL</span></td>
<td>是否进行流量控制。如果设置为True，那么达到MAX_QUEUE_SIZE后，会暂停接收数据，直到转发队列低于QUEUE_LOW_WATERMARK_PCT</td>
</tr>
<tr>
<td rowspan="13">[aggregator]</td>
<td><span style="font-size: 8pt;"> LINE_RECEIVER_INTERFACE</span></td>
<td rowspan="2">接收文本格式数据的监听端口，默认0.0.0.0:2023</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">LINE_RECEIVER_PORT</span></td>
</tr>
<tr>
<td><span style="font-size: 8pt;">PICKLE_RECEIVER_INTERFACE</span></td>
<td rowspan="2">接收Pickle格式数据的监听端口，默认0.0.0.0:2004</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">PICKLE_RECEIVER_PORT</span></td>
</tr>
<tr>
<td><span style="font-size: 8pt;">LOG_LISTENER_CONNECTIONS</span></td>
<td>对成功的连接请求记录日志</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">USER</span></td>
<td>运行该进程的用户</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">FORWARD_ALL</span></td>
<td>如果设置为True，除了根据aggregation-rules.conf进行聚合外，还把原始数据转发给DESTINATIONS</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">DESTINATIONS</span></td>
<td>聚合后的数据发送到的地方</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">REPLICATION_FACTOR</span></td>
<td>如果设置为N，则把数据转发给N个DESTINATION</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">MAX_QUEUE_SIZE</span></td>
<td>待转发的队列最大包含多少数据点</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">USE_FLOW_CONTROL</span></td>
<td>是否进行流量控制。如果设置为True，那么达到MAX_QUEUE_SIZE后，会暂停接收数据，直到转发队列低于80%</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">MAX_DATAPOINTS_PER_MESSAGE</span></td>
<td>单个转发报文中包含的数据点的最大个数</td>
</tr>
<tr>
<td><span style="font-size: 8pt;">MAX_AGGREGATION_INTERVALS</span></td>
<td>控制最多记住多少数据点，只有这些数据点才参与聚合<br />仅最近MAX_AGGREGATION_INTERVALS  * intervalSize秒内的数据点会被记住</td>
</tr>
</tbody>
</table>
<div class="blog_h3"><span class="graybg">storage-schemas.conf</span></div>
<p>这个配置文件用于定义Metrics的驻留率（ retention rates）——即Metrics的数据点（datapoints）以什么频率保存，保存多长时间。关于该配置文件，需要注意：</p>
<ol>
<li>该配置文件可以由多个段（Section）组成。每个段定义一个存储规则</li>
<li>这些规则按照从上到下的顺序对Metrics进行匹配，第一个匹配的规则对Metrics生效</li>
<li>匹配Metrics时，采用的是正则表达式</li>
<li>对于一个Metrics，其存储规则在接收到第一个数据时固化。因而修改此配置文件不会影响到既有的.wsp文件。要应用到既有的.wsp可以调用whisper-resize.py</li>
</ol>
<p>每个规则由三个部分组成：</p>
<pre class="crayon-plain-tag"># 段名称（规则名称），主要是文档用途。在匹配段的Metrics被创建时，日志creates.log中会显示此名称
[rulename]
# 匹配Metrics路径（Metrics的全限定名称，点号分隔）的正则式
# 举例：^servers\.www.*\.workers\.busyWorkers$
pattern=regex
# 驻留率表达式，数据点间隔:存留天数，时间后缀s,m,h,d,y分别表示秒、分、小时、天、年
# 举例：10s:14d 表示每个数据点表示10秒（相当于每10秒采集数据一次），并且存储14天的数据
retentions=retention rate</pre>
<p>注意，你可以指定多重驻留率表达式（retention rate），逗号分隔每个表达式。一般从最高精度:最短存留时间开始指定，直到最低精度:最长存留时间。例如：<pre class="crayon-plain-tag">15s:7d,1m:21d,15m:5y</pre> 表示7天内每15秒存留一个采样，而大于21天小于5年的则每15分钟一个采样。</p>
<p>设置多重驻留率表达式，可以在保存足够长时间的历史数据的前提下，尽量减少磁盘I/O和消耗的存储空间。当跨越驻留表达式的时间区间（上例中7天，21天）后，whisper会自动降低采样率（downsamples），<span style="background-color: #c0c0c0;">默认算法是取平均值</span>，可以通过storage-aggregation.conf定制聚合方式</p>
<div class="blog_h3"><span class="graybg">storage-aggregation.conf</span></div>
<p>这个配置文件定义如何在降低采样率（转换为低精度存储时） 如何对数据进行聚合。该文件的格式与storage-schemas.conf类似：</p>
<pre class="crayon-plain-tag">[rulename]
pattern = rexexp
# 0-1之间的浮点数，默认0.5。聚合区间内的值，至少多少比例为非空，聚合后的值才是非空
xFilesFactor = 0.5
# 数据聚合方式，默认average
aggregationMethod = average | sum | min | max | last</pre>
<p>同样的，修改此文件不会影响已经生成的.wsp文件， 要应用到既有的.wsp文件，可以调用whisper-set-aggregation-method.py。</p>
<div class="blog_h3"><span class="graybg">relay-rules.conf</span></div>
<p>这个配置文件指定中继规则——即需要把何种Metrics转发给何种后端。中继由Carbon的中继进程负责执行。该文件格式如下：</p>
<pre class="crayon-plain-tag">[rulename]
pattern = regex
servers = ip:port,ip:port,...</pre>
<div class="blog_h3"><span class="graybg">aggregation-rules.conf</span></div>
<p>该配置文件定义聚合出来的Metrics——由几个Metrics聚合而成的新的Metrics。聚合由Carbon的聚合进程负责执行。</p>
<p>注意：这里的聚合storage-aggregation.conf提及的聚合不同。后者用于单一Metrics的降低采样，而前者用于生成新的Metrics。</p>
<p>与其它配置文件不同，该文件一旦更改，立即生效。</p>
<p>该文件的格式如下：</p>
<pre class="crayon-plain-tag"># 捕获任何匹配input_pattern的Metrics，使用method聚合成新的Metrics：output_template
# frequency：每隔多久执行一次聚合
# method：可选sum/avg
output_template (frequency) = method input_pattern</pre>
<p>举例，假设你的Metrics的命名规则是：</p>
<pre class="crayon-plain-tag">&lt;env&gt;.applications.&lt;app&gt;.&lt;server&gt;.&lt;metric&gt;</pre>
<p>这是你可以配置如下聚合规则，来计算所有应用程序的请求的总数：</p>
<pre class="crayon-plain-tag">&lt;env&gt;.applications.&lt;app&gt;.all.requests (60) = sum &lt;env&gt;.applications.&lt;app&gt;.*.requests</pre>
<p>在此规则下，下面的Metrics：</p>
<pre class="crayon-plain-tag">test.applications.pems.221.request
test.applications.pems.6.request
test.applications.pems.5.request
test.applications.pems.201.request</pre>
<p>会每个60秒求和并生成 <pre class="crayon-plain-tag">test.applications.pems.all.request</pre> 的一个数据点。</p>
<div class="blog_h3"><span class="graybg">rewrite-rules.conf </span></div>
<p>该配置文件定义Metrics名称的改写规则。 与其它配置文件不同，该文件一旦更改，立即生效。该文件的格式如下：</p>
<pre class="crayon-plain-tag">[pre]
# pre段的规则，在接收到数据后立即执行改写
[post]
# post段的规则，在聚合完毕后执行改写
regex-pattern = replacement-text</pre>
<p> 举例：</p>
<pre class="crayon-plain-tag"># \1表示第一个捕获，即[a-z0-9]+
^collectd\.([a-z0-9]+)\. = \1.system.
# collectd.prod.cpu-0.idle-time 会被改写为 prod.system.cpu-0.idle-item</pre>
<div class="blog_h3"><span class="graybg">whitelist.conf和blacklist.conf </span></div>
<p>Carbon提供黑白名单功能。白名单：仅仅接受其中列出的Metrics；黑名单：拒绝其中列出Metrics。</p>
<p>要启用黑白名单功能，需要修改carbon.conf，设置<pre class="crayon-plain-tag">USE_WHITELIST = True</pre> </p>
<div class="blog_h2"><span class="graybg">启动Graphite</span></div>
<p>如何启动Graphite Webapp依赖于其运行的Web服务软件，以Apache为例：</p>
<pre class="crayon-plain-tag"># CentOS 7
systemctl restart httpd</pre>
<p>Carbon组件需要执行下面的命令来启动：</p>
<pre class="crayon-plain-tag">/opt/graphite/bin/carbon-cache.py start</pre>
<p>SQLite是一个“文件数据库”，不需要启动。如果Graphite Webapp使用其它数据库，例如MySQL，则需要启动之。 </p>
<div class="blog_h1"><span class="graybg">向Graphite发送数据点</span></div>
<div class="blog_h2"><span class="graybg">数据格式</span></div>
<p>你可以通过多种方式向Graphite（的Carbon组件）发送Metrics数据点。主要的三种数据格式是：Plaintext、Pickle、AMQP </p>
<div class="blog_h3"><span class="graybg">Plaintext协议</span></div>
<p>这种方式非常简单，你可以用如下格式来发送一条Metrics数据点：</p>
<pre class="crayon-plain-tag">&lt;metric path&gt; &lt;metric value&gt; &lt;metric timestamp&gt;
# 举例：
servers.zircon.cpu 85 1470303923</pre>
<p>出于测试目的，你可以直接通过命令向Carbon发送Metrics数据：</p>
<pre class="crayon-plain-tag">PORT=2003
SERVER=127.0.0.1
echo "servers.zircon.cpu 85 `date +%s`" | nc ${SERVER} ${PORT}</pre>
<div class="blog_h3"><span class="graybg">Pickle协议</span></div>
<p>Pickle是Python下的对象串行化框架，Pickle协议即它的串行化格式协议。使用该协议，你可以一次发送多个Metrics，并且串行化后的数据比较紧凑，因此Pickle协议性能更好。</p>
<p>下面是构建Pickle报文的示例代码：</p>
<pre class="crayon-plain-tag">listOfMetricTuples = [
    (path, (timestamp, value)),
    ...
]
payload = pickle.dumps(listOfMetricTuples, protocol=2)
header = struct.pack("!L", len(payload))
message = header + payload
# 然后通过Socket把message发送出去即可</pre>
<div class="blog_h2"><span class="graybg">客户端示例</span></div>
<div class="blog_h3"><span class="graybg">简单Pickle客户端</span></div>
<pre class="crayon-plain-tag">import pickle
import socket
import struct
import sys
import time
from time import sleep

import psutil


def get_cpu_load():
    load = psutil.cpu_percent()
    print load
    return load


if __name__ == '__main__':
    CARBON_HOST = '172.16.87.132'
    CARBON_PORT = 2004
    s = socket.socket()
    try:
        s.connect((CARBON_HOST, CARBON_PORT))
        while True:
            data = [
                ('servers.zircon.cpu', (time.time(), get_cpu_load()))
            ]
            pkg = pickle.dumps(data, 1)
            s.sendall(struct.pack('!L', len(pkg)))
            s.sendall(pkg)
            sleep(5)
    except socket.error:
        raise SystemExit("Failed to connect to %(host)s:%(port)" % {'host': CARBON_HOST, 'port': CARBON_PORT})
    except KeyboardInterrupt:
        sys.stderr.write("\nExiting on CTRL-C\n")
        sys.exit(0) </pre>
<div class="blog_h1"><span class="graybg">从Graphite获取数据</span></div>
<p>要从Graphite获取数据用于展示，可以使用Graphite Webapp暴露的Render URL API（RUA）。你可以通过</p>
<pre class="crayon-plain-tag">http://GRAPHITE_HOST:GRAPHITE_PORT/render</pre>
<p>访问此API。要向RUA传递参数，可以使用URL请求参数方式：<pre class="crayon-plain-tag">&amp;name=value</pre> 。注意大部分的参数名、函数名是大小写敏感的。</p>
<p>下面列出几个RUA的URL示例：</p>
<pre class="crayon-plain-tag"># Zircon的CPU负载图，获取800x600的图片
http://graphite/render?target=servers.zircon.cpu&amp;height=800&amp;width=600
# 最近12小时，所有服务器的CPU负载平均值
http://graphite/render?target=averageSeries(servers.*.load)&amp;from=-12hours
# 获取原始数据而不是图片，JSON格式
http://graphite/render?target=servers.zircon.cpu&amp;format=json</pre>
<div class="blog_h2"><span class="graybg">target参数</span></div>
<p>该参数用来指定从何处获取数据，你可以指定：</p>
<ol>
<li>单个Metrics路径</li>
<li>带有通配符的的Metrics路径，匹配多个Metrics</li>
<li>函数调用，针对作为入参的Metrics进行各种转换、合并操作</li>
</ol>
<div class="blog_h3"><span class="graybg">通配符</span></div>
<p>你可以在路径中使用三种风格的通配符：</p>
<ol>
<li><pre class="crayon-plain-tag">*</pre> 可以匹配0-N个字符，例如<pre class="crayon-plain-tag">servers.dev-*.cpu</pre> ，可以匹配所有开发服务器的CPU负载Metrics。</li>
<li><pre class="crayon-plain-tag">[...]</pre> 可以匹配列表中枚举的单个字符，例如<pre class="crayon-plain-tag">servers.dev-[a-z0-9].cpu</pre> ，可以匹配dev-0、dev-1等服务器的CPU负载Metrics。</li>
<li><pre class="crayon-plain-tag">{...}</pre> 可以匹配列表中枚举的单个字符串，例如<pre class="crayon-plain-tag">servers.{dev-0,dev-1}.cpu</pre> ，匹配dev-0、dev-2的CPU负载Metrics。</li>
</ol>
<p>注意：所有通配符都<span style="background-color: #c0c0c0;">不能跨越点号</span>。 </p>
<div class="blog_h3"><span class="graybg">template函数</span></div>
<p>你可以指定target为template函数调用，从而在Metrics路径中使用变量，例如：</p>
<pre class="crayon-plain-tag"># $varname 用来声明变量占位符
# template[varname]参数用来传递变量值
&amp;target=template(servers.$servername.cpu)&amp;template[servername]=zircon

# 可以使用数字代替变量名
&amp;target=template(servers.$1.cpu)&amp;template[1]=zircon

# template可以内嵌其它函数
&amp;target=template(constantLine($number))&amp;template[number]=123</pre>
<div class="blog_h3"><span class="graybg">所有函数</span></div>
<p>可用的函数较多，这里不一一列举说明，参见<a href="http://graphite.readthedocs.io/en/latest/functions.html">官方文档</a>。</p>
<div class="blog_h2"><span class="graybg">from/until参数</span></div>
<p>这两个可选参数用来指定相对或者绝对的时间区间（time period）。from表示区间起点，如果忽略，默认值是24小时之前；until表示区间终点，如果或略，默认值是当前时间点。</p>
<div class="blog_h3"><span class="graybg">相对时间</span></div>
<p>如果要使用相对时间，需要加上<pre class="crayon-plain-tag">-</pre> 前缀（负号），后面跟着数值和时间单位。时间单位包括：</p>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 25%; text-align: center;">时间单位</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>s</td>
<td>秒</td>
</tr>
<tr>
<td>min</td>
<td>分钟</td>
</tr>
<tr>
<td>h</td>
<td>小时</td>
</tr>
<tr>
<td>d</td>
<td>天</td>
</tr>
<tr>
<td>w</td>
<td>周</td>
</tr>
<tr>
<td>mon</td>
<td>月（30天）</td>
</tr>
<tr>
<td>y</td>
<td>年（365天）</td>
</tr>
</tbody>
</table>
<div class="blog_h3"><span class="graybg">绝对时间</span></div>
<p>你可以指定<pre class="crayon-plain-tag">HH:MM_YYYYMMDD</pre> 、<pre class="crayon-plain-tag">YYYYMMDD</pre> 、<pre class="crayon-plain-tag"> MM/DD/YY</pre> 等格式的时间绝对值。</p>
<div class="blog_h2"><span class="graybg">format参数</span></div>
<p>该参数用来指定要获取的数据的格式。 支持以下取值：</p>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 15%; text-align: center;">格式</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>png</td>
<td>根据指定的width、height，直接把数据渲染为PNG图片</td>
</tr>
<tr>
<td>raw</td>
<td>原始数据，分为多行，每行格式为：<br />
<pre class="crayon-plain-tag">&lt;target name&gt;,&lt;start timestamp&gt;,&lt;end timestamp&gt;,&lt;series step&gt;|[data]*</pre></p>
<p> 示例：</p>
<pre class="crayon-plain-tag">entries,1311836008,1311836013,1|1.0,2.0,3.0,5.0,6.0</pre>
</td>
</tr>
<tr>
<td>csv</td>
<td>基于逗号分隔符的格式，每行表示一个数据点。示例：<br />
<pre class="crayon-plain-tag">entries,2011-07-28 01:53:28,1.0
entries,2011-07-28 01:53:29,2.0
entries,2011-07-28 01:53:30,3.0
entries,2011-07-28 01:53:31,5.0
entries,2011-07-28 01:53:32,6.0</pre>
</td>
</tr>
<tr>
<td>json</td>
<td>
<p>JSON数组格式，示例：
<pre class="crayon-plain-tag">[{
  "target": "entries",
  "datapoints": [
    [1.0, 1311836008],
    [2.0, 1311836009],
    [3.0, 1311836010],
    [5.0, 1311836011],
    [6.0, 1311836012]
  ]
}]</pre>
<p>可以和jsonp参数联用，以便把数据包装成函数调用，进行跨域请求</p>
<p>可以和maxDataPoints参数联用，限定最大的数据点个数。超过数量的数据点将被压缩掉</p>
<p>可以和noNullPoints参数联用，移除所有Null值的数据点</p>
</td>
</tr>
<tr>
<td>svg</td>
<td>渲染为SVG图片格式</td>
</tr>
<tr>
<td>pdf</td>
<td>渲染为PDF文档</td>
</tr>
<tr>
<td>dygraph</td>
<td>dygraphs是一个快速、灵活的JavaScript图表（Chart）库。该格式返回dygraphs支持的数据格式。示例：<br />
<pre class="crayon-plain-tag">{
  "labels" : [
    "Time",
    "entries"
  ],
  "data" : [
    [1468791890000, 0.0],
    [1468791900000, 0.0]
  ]
}</pre>
</td>
</tr>
<tr>
<td>rickshaw</td>
<td>rickshaw是一个简单的JavaScript图表库。该格式返回rickshaw支持的数据格式。示例：<br />
<pre class="crayon-plain-tag">[{
  "target": "entries",
  "datapoints": [{
    "y": 0.0,
    "x": 1468791890
  }, {
    "y": 0.0,
    "x": 1468791900
  }]
}]</pre>
</td>
</tr>
<tr>
<td>pickle</td>
<td>返回Pickle串行化格式，设置MIME类型为application/pickle。反串行化后的对象示例：<br />
<pre class="crayon-plain-tag">[
  {
    'name' : 'summarize(test.data, "30min", "sum")',
    'start': 1335398400,
    'end'  : 1335425400,
    'step' : 1800,
    'values' : [None, None, 1.0, None],
  }
]</pre>
</td>
</tr>
</tbody>
</table>
<div class="blog_h2"><span class="graybg">图形参数</span></div>
<p>你可以指定多个参数，来控制生成的图形的样式：</p>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 22%; text-align: center;">参数</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>areaAlpha</td>
<td>启用areaMode时，填充区域的透明度。0-1之间的浮点数</td>
</tr>
<tr>
<td>areaMode</td>
<td>填充曲线与X轴之间的区域，形成Area图，可以取值：<br />none 不进行填充<br />first 填充第一个目标<br />all  填充所有目标<br />stacked 堆叠模式，填充所有目标，一个目标的取值为前面所有其它目标的取值+该目标的取值</td>
</tr>
<tr>
<td>bgcolor</td>
<td>背景颜色。示例：<br />
<pre class="crayon-plain-tag"># 颜色名称
&amp;bgcolor=blue
# HEX代码
&amp;bgcolor=2222FF
# HEX代码，包含透明度
&amp;bgcolor=5522FF60</pre>
</td>
</tr>
<tr>
<td>cacheTimeout</td>
<td>被渲染出的图形，其有效缓存时间</td>
</tr>
<tr>
<td>colorList</td>
<td>多个Target时，每个Target的颜色，逗号分隔颜色代码</td>
</tr>
<tr>
<td>drawNullAsZero</td>
<td>是否把空值渲染为0</td>
</tr>
<tr>
<td>fontBold</td>
<td>是否使用粗体</td>
</tr>
<tr>
<td>fontItalic</td>
<td>是否使用斜体</td>
</tr>
<tr>
<td>fontName</td>
<td>字体名称，该字体必须安装在Graphite服务器上</td>
</tr>
<tr>
<td>fontSize</td>
<td>字体大小，大于1的浮点数</td>
</tr>
<tr>
<td>graphOnly</td>
<td>是否不显示网格线、X/Y轴和图例</td>
</tr>
<tr>
<td>graphType</td>
<td>图表类型，line或者pie</td>
</tr>
<tr>
<td>hideLegend</td>
<td>是否隐藏图例</td>
</tr>
<tr>
<td>hideAxes</td>
<td rowspan="3">是否隐藏X/Y轴</td>
</tr>
<tr>
<td>hideXAxis</td>
</tr>
<tr>
<td>hideYAxis</td>
</tr>
<tr>
<td>hideGrid</td>
<td>是否隐藏网格线</td>
</tr>
<tr>
<td>height</td>
<td rowspan="2">图形的高度、宽度，单位像素</td>
</tr>
<tr>
<td>width</td>
</tr>
<tr>
<td>leftColor</td>
<td>在双Y轴模式下，设置与左轴关联的Metrics的颜色</td>
</tr>
<tr>
<td>rightColor</td>
<td>在双Y轴模式下，设置与右轴关联的Metrics的颜色</td>
</tr>
<tr>
<td>leftDashed</td>
<td>在双Y轴模式下，是否以虚线绘制与左轴关联的Metrics</td>
</tr>
<tr>
<td>rightDashed</td>
<td>在双Y轴模式下，是否以虚线绘制与右轴关联的Metrics</td>
</tr>
<tr>
<td>leftWidth</td>
<td>在双Y轴模式下，设置与左轴关联的Metrics的线条宽度</td>
</tr>
<tr>
<td>rightWidth</td>
<td>在双Y轴模式下，设置与右轴关联的Metrics的线条宽度</td>
</tr>
<tr>
<td>lineMode</td>
<td>设置线条绘制的行为：<br />slope：从一个数据点向下一个数据点绘制斜线，Null值的区间不被绘制<br />connected：与slope类似，但是数据点总是被连接起来，无论它们之间是否存在Null值<br />staircase：绘制直方图</td>
</tr>
<tr>
<td>lineWidth</td>
<td>线条的宽度</td>
</tr>
<tr>
<td>majorGridLineColor</td>
<td>网格线主色</td>
</tr>
<tr>
<td>minorGridLineColor</td>
<td>网格线从色</td>
</tr>
<tr>
<td>minorY</td>
<td>每两个网格主线之间，有几个从线，Y方向</td>
</tr>
<tr>
<td>margin</td>
<td>图形四周的边距</td>
</tr>
<tr>
<td>maxDataPoints</td>
<td>使用</td>
</tr>
<tr>
<td>minXStep</td>
<td>
<p>两个连续的数据点之间，间隔的最小像素</p>
<p>如果数据点过多，则压缩，以满足此配置</p>
</td>
</tr>
<tr>
<td>noCache</td>
<td>禁止图片缓存</td>
</tr>
<tr>
<td>pieLabels</td>
<td>饼图标签如何显示，horizontal或者rotated</td>
</tr>
<tr>
<td>pieMode</td>
<td>饼图聚合方式：<br />average，取series中非空数据点的平均值<br />maximum，取series中非空数据点的最大值<br />minimum，取series中非空数据点的最小值</td>
</tr>
<tr>
<td>valueLabels</td>
<td>如何显示饼图分块的标签：<br />none，不显示<br />numbers，显示原始值<br />percent，显示百分比</td>
</tr>
<tr>
<td>valueLabelsColor</td>
<td>如何显示饼图分块的标签的颜色</td>
</tr>
<tr>
<td>valueLabelsMin</td>
<td>饼图中，分块占比小于此数值的分块，不显示其标签</td>
</tr>
<tr>
<td>title</td>
<td>在图形顶端显示的标题</td>
</tr>
<tr>
<td>vtitle</td>
<td>Y轴标题，垂直显示</td>
</tr>
<tr>
<td>vtitleRight</td>
<td>双Y轴模式下，右Y轴的标题</td>
</tr>
<tr>
<td>tz</td>
<td>用于显示时间值的时区</td>
</tr>
</tbody>
</table>
<div class="blog_h1"><span class="graybg">展示Graphite数据</span></div>
<p>上一章内容我们讨论了如何获取Graphite数据。通过Render URL API，我们不但可以获得文本数据，还可以直接获得渲染好的图片。这意味着通过Render URL API本身就可以实现Metrics的渲染，你只需要把生成的图片嵌入到自己的应用程序中即可。</p>
<p>Graphite Webapp本身提供了基于ExtJS的一个管理界面，你可以通过<pre class="crayon-plain-tag">http://GRAPHITE_HOST:GRAPHITE_PORT/admin</pre> 浏览Metrics。</p>
<p>Graphite生成的Metrics曲线的图片，不是非常美观，而静态图片也缺乏交互性。因此，实际项目中常常结合使用第三方基于JavaScript的Charts库来做展示，例如：</p>
<ol>
<li><a href="http://grafana.org/">Grafana</a>：UI比较绚丽，支持设计仪表盘、时间区间联动。参见：<a href="/time-series-data-renderering-with-grafana">使用Grafana展示时间序列数据</a></li>
<li><a href="http://jondot.github.io/graphene/">Graphene</a>：一个较为简单的，基于D3.js和Backbone.js的Graphite仪表盘工具</li>
</ol>
<div class="blog_h1"><span class="graybg">Graphite事件</span></div>
<p>除了简单的，基于Key/Value的Metrics数据，Graphite还可以存储、展示随机出现的数据——事件。</p>
<p>事件不适合存储在Whisper中，因此它被存储在Graphite的Webapp的数据库中（默认使用SQLite）。</p>
<div class="blog_h2"><span class="graybg">发布事件</span></div>
<p>通过向<pre class="crayon-plain-tag">http://GRAPHITE_HOST:GRAPHITE_PORT/events/</pre> 发送POST请求，即可发布Graphite事件。事件使用JSON格式编码在请求体中：</p>
<pre class="crayon-plain-tag">{ 
    "what": "事件类型", 
    "tags": "标签",
    "data": "事件相关的数据" 
}</pre>
<div class="blog_h2"><span class="graybg">查询事件</span></div>
<p>指定target为<pre class="crayon-plain-tag">event(*tags)</pre> 函数调用，即可通过<pre class="crayon-plain-tag">/render</pre> 查询事件，例如</p>
<pre class="crayon-plain-tag">[
   {
      "target" : "events(mytag)",
      "datapoints" : [
         [
            1,
            1388966651
         ],
         [
            3,
            1388966652
         ]
      ]
   }
]</pre>
<p>你也可以通过<pre class="crayon-plain-tag">/render/events/get_data</pre> 获得原始的事件数据，例如：</p>
<pre class="crayon-plain-tag">[
   {
      "when" : 1392046352,
      "tags" : "mytag",
      "data" : "...",
      "id" : 2,
      "what" : "Event - deploy"
   }
] </pre>
<div class="blog_h1"><span class="graybg">常见问题</span></div>
<div class="blog_h3"><span class="graybg">AttributeError: 'WSGIRequest' object has no attribute 'REQUEST'</span></div>
<p>Django的request对象曾经有一个属性REQUEST，用来获得通过GET或者POST请求传递的请求参数，在1.9版本中此属性已经移除。</p>
<p>Graphite代码没有即时更新，存在不兼容的问题，修改一下即可：</p>
<pre class="crayon-plain-tag">def parseOptions(request):
   queryParams = request.GET # request.REQUEST已经被移除</pre>
<p>还有很多其它views.py存在同样的问题，最好搜索一下一并修改。如果觉得麻烦可以安装兼容版本的Django：</p>
<pre class="crayon-plain-tag">pip install django==1.8.14</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
</div><p>The post <a rel="nofollow" href="https://blog.gmem.cc/graphite-study-note">Graphite学习笔记</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.gmem.cc/graphite-study-note/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Shinken学习笔记</title>
		<link>https://blog.gmem.cc/shinken-study-note</link>
		<comments>https://blog.gmem.cc/shinken-study-note#comments</comments>
		<pubDate>Wed, 22 Jun 2016 01:29:03 +0000</pubDate>
		<dc:creator><![CDATA[Alex]]></dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Monitoring]]></category>
		<category><![CDATA[Shinken]]></category>

		<guid isPermaLink="false">https://blog.gmem.cc/?p=12060</guid>
		<description><![CDATA[<p>Shinken简介 Shinken是一个开源的IT监控框架，基于Python编写。Shinken从2009年开始发布，起初是作为一个简单的监控解决方案，由于越来越多的模块的加入，至2014年它被重新定位为“框架”。 Shinken的优势包括： 跨平台，它可以在Windows、Linux上部署和运行 独立性，不依赖于其它监控解决方案 可扩容，能够很好的支持不断扩张的、大规模的监控需求 特性列表 特性 说明 基于角色分离的守护程序 Shinken中的每个后端程序只做一种事情，这些后端程序有6类 强大的灵活性 大量的可拔插模块，让你能监控很多东西 从数据库导入配置 支持的数据库包括：GLPI、MySQL、MongoDB等 导出数据到数据库 支持的数据库包括：Graphite、InfluxDB、RRD、GLPI、CouchDB、Livestatus、MySQL、Oracle等 与WebUI集成 支持内置的WebUI，或者与Thruk、Adagios、Multisite、Nagvis、PNP4Nagios、NConf等集成 支持大量监控目标 数据库：MySQL、Oracle等关系型数据库；MongoDB等NoSQL；Memcached等缓存路由器/交换机：包括Cisco、Nortel、Procurve等公司的产品操作系统：Linux、Windows、Aix、HP-UX等网络协议：HTTP、SSH、LDAP、DNS、IMAP、FTP等应用程序：Weblogic、Exchange、AD、Tomcat等存储：IBM-DS、Safekit、Hacmp等 智能的SNMP轮询 <a class="read-more" href="https://blog.gmem.cc/shinken-study-note">[...]</a></p>
<p>The post <a rel="nofollow" href="https://blog.gmem.cc/shinken-study-note">Shinken学习笔记</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></description>
				<content:encoded><![CDATA[<div class="wri_content_clear_both"><div class="blog_h1"><span class="graybg">Shinken简介</span></div>
<p>Shinken是一个开源的<span style="background-color: #c0c0c0;">IT监控框架</span>，基于Python编写。Shinken从2009年开始发布，起初是作为一个简单的监控<span style="background-color: #c0c0c0;">解决方案</span>，由于越来越多的模块的加入，至2014年它被重新定位为“框架”。</p>
<p>Shinken的优势包括：</p>
<ol>
<li>跨平台，它可以在Windows、Linux上部署和运行</li>
<li>独立性，不依赖于其它监控解决方案</li>
<li>可扩容，能够很好的支持不断扩张的、大规模的监控需求</li>
</ol>
<div class="blog_h2"><span class="graybg">特性列表</span></div>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 25%; text-align: center;">特性</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>基于角色分离的守护程序</td>
<td>Shinken中的每个后端程序只做一种事情，这些后端程序有6类</td>
</tr>
<tr>
<td>强大的灵活性</td>
<td>大量的可拔插模块，让你能监控很多东西</td>
</tr>
<tr>
<td>从数据库导入配置</td>
<td>支持的数据库包括：GLPI、MySQL、MongoDB等</td>
</tr>
<tr>
<td>导出数据到数据库</td>
<td>支持的数据库包括：Graphite、InfluxDB、RRD、GLPI、CouchDB、Livestatus、MySQL、Oracle等</td>
</tr>
<tr>
<td>与WebUI集成</td>
<td>支持内置的WebUI，或者与Thruk、Adagios、Multisite、Nagvis、PNP4Nagios、NConf等集成</td>
</tr>
<tr>
<td>支持大量监控目标</td>
<td>数据库：MySQL、Oracle等关系型数据库；MongoDB等NoSQL；Memcached等缓存<br />路由器/交换机：包括Cisco、Nortel、Procurve等公司的产品<br />操作系统：Linux、Windows、Aix、HP-UX等<br />网络协议：HTTP、SSH、LDAP、DNS、IMAP、FTP等<br />应用程序：Weblogic、Exchange、AD、Tomcat等<br />存储：IBM-DS、Safekit、Hacmp等</td>
</tr>
<tr>
<td>智能的SNMP轮询</td>
<td>如果你需要监控大量的路由器、交换机等基础设施，可以使用SNMP Booster模块</td>
</tr>
<tr>
<td>可扩容性</td>
<td>只需要在其它服务器上安装守护程序，负载均衡就会自动完成</td>
</tr>
<tr>
<td>高可用性</td>
<td>守护程序可以有多个备用的</td>
</tr>
</tbody>
</table>
<div class="blog_h2"><span class="graybg">架构</span></div>
<div class="blog_h3"><a href="https://blog.gmem.cc/wp-content/uploads/2016/06/shinken-architecture.png"><img class="aligncenter wp-image-12067 size-large" src="https://blog.gmem.cc/wp-content/uploads/2016/06/shinken-architecture-1024x724.png" alt="shinken-architecture" width="710" height="501" /></a><span class="graybg">守护程序角色</span></div>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 15%; text-align: center;">角色</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>Arbiter</td>
<td>
<p>此类守护程序负责：</p>
<ol>
<li><span style="background-color: #c0c0c0;">读取配置</span>，拆分成N份（N=Scheduler的数量），然后<span style="background-color: #c0c0c0;">分发</span>给相应的其它守护程序</li>
<li>管理<span style="background-color: #c0c0c0;">高可用性</span>：管理其它守护进程的健康状况，如果某个守护程序宕机，它负责把<span style="background-color: #c0c0c0;">此守护程序管理的配置重新路由</span>给其它空闲的守护程序</li>
<li><span style="background-color: #c0c0c0;">接受用户输入</span>，并路由给合适的守护程序</li>
</ol>
<p>同时<span style="background-color: #c0c0c0;">只能有一个Arbiter处于活动状态</span>，其它只能Standby</p>
<p>和Arbiter相关的模块包括：<br />数据收集模块：NSCA、TSCA、Ws_arbiter<br />配置数据保存模块：MongoDB<br />状态保持模块：PickleRententionArbiter<br />配置数据导入模块：MySQLImport、GLPI<br />配置修改模块：vmware autolinking、IP_Tag</p>
</td>
</tr>
<tr>
<td>Scheduler</td>
<td>
<p>此类守护程序负责：</p>
<ol>
<li><span style="background-color: #c0c0c0;">分发检查</span>（Check）给Poller、<span style="background-color: #c0c0c0;">分发动作</span>（Action）给Reactionner。它<span style="background-color: #c0c0c0;">自己不会</span>执行检查或动作</li>
<li>处理检查结果队列（Check result queue）、<span style="background-color: #c0c0c0;">分析</span>结果，根据结果可能将动作请求纳入队列</li>
</ol>
<p>和Scheduler相关的模块包括：<br />用于状态保持的模块：pickle、nagios、memcache、redis、MongoDB</p>
</td>
</tr>
<tr>
<td>Poller</td>
<td>
<p>依据Scheduler的指令，启动检查插件（Check plugins），检查完毕后，Poller把结果返回给Scheduler</p>
<p>和Poller相关的模块包括：<br />数据获取模块：NRPE、CommandFile、SnmpBooster</p>
</td>
</tr>
<tr>
<td>Reactionner</td>
<td>
<p>发送通知、启动事件处理器（Event handler），集中处理和外部系统的通信</p>
<p>和Reactionner相关的模块包括：<br />外部通信模块：AndroidSMS</p>
</td>
</tr>
<tr>
<td>Broker</td>
<td>
<p>导出、管理来自Scheduler的数据，代理外部系统与Shinken的交互</p>
<p>和Broker相关的模块包括：<br />LiveStatus API模块——实时状态、状态保持、历史：SQLite（默认）、MongoDB<br />状态保持模块：Pickle、ToNdodb_Mysql、ToNdodb_Oracle<br />导出数据的模块：Graphite-Perfdata、NPCDMOD、raw_tcp、Syslog<br />WebUI相关模块：WebUI、GRAPHITE_UI、PNP_UI</p>
</td>
</tr>
<tr>
<td>Receiver</td>
<td>
<p>被动的接收检查数据，并作为分布式的命令缓冲</p>
<p>和Receiver相关的模块：<br />被动数据获取模块：NSCA、TSCA、Ws_arbiter</p>
</td>
</tr>
</tbody>
</table>
<div class="blog_h1"><span class="graybg">安装</span></div>
<div class="blog_h2"><span class="graybg">Linux</span></div>
<div class="blog_h3"><span class="graybg">通过PIP安装</span></div>
<pre class="crayon-plain-tag"># 如果机器上没有安装pip
apt-get install python-pip python-pycurl
# 添加shiken专用户
adduser shinken
# 安装shinken
pip install shinken</pre>
<div class="blog_h3"><span class="graybg">通过源码安装</span></div>
<p>使用这种方式，你可以方便的调试或者修改Shinken的源码：</p>
<pre class="crayon-plain-tag">adduser shinken
wget http://www.shinken-monitoring.org/pub/shinken-2.4.tar.gz
tar -xvzf shinken-2.4.tar.gz
cd shinken-2.4
python setup.py install</pre>
<div class="blog_h3"><span class="graybg">启动</span></div>
<p>在生产环境下可以设置Shinken为自启动：</p>
<pre class="crayon-plain-tag"># RedHat / CentOS
chkconfig shinken on
# Debian / Ubuntu
update-rc.d shinken defaults

# 启动
service shinken start</pre>
<p>你可以可以通过脚本启动：<pre class="crayon-plain-tag">./bin/launch_all.sh</pre>  </p>
<p>开发环境下，如果你需要修改Shinken源码，需使用第二种安装方式。然后注释掉shinken.cfg中用户、组信息，以当前用户的身份启动Shinken：</p>
<pre class="crayon-plain-tag">./bin/shinken-scheduler -c /etc/shinken/daemons/schedulerd.ini -d
./bin/shinken-poller -c /etc/shinken/daemons/pollerd.ini -d
./bin/shinken-broker -c /etc/shinken/daemons/brokerd.ini -d
./bin/shinken-reactionner -c /etc/shinken/daemons/reactionnerd.ini -d
./bin/shinken-arbiter -c /etc/shinken/shinken.cfg -d
./bin/shinken-receiver -c /etc/shinken/daemons/receiverd.ini -d</pre>
<div class="blog_h3"><span class="graybg">目录结构</span></div>
<p>安装后以及运行时，Shinken会使用下面的目录：</p>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 25%; text-align: center;">目录</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>/etc/shinken</td>
<td>存放Shinken配置文件</td>
</tr>
<tr>
<td>/var/lib/shinken</td>
<td>存放Shinken模块、保留文件（Retention files）</td>
</tr>
<tr>
<td>/var/log/shinken</td>
<td>存放日志文件</td>
</tr>
<tr>
<td>/var/run/shinken</td>
<td>存放PID</td>
</tr>
</tbody>
</table>
<div class="blog_h2"><span class="graybg">Windows</span></div>
<p>安装步骤参考Linux下基于源码的安装方式，不需要添加用户，解压可以手工进行。</p>
<p>Windows下所有目录都位于Shinken安装目录下，例如<pre class="crayon-plain-tag">/etc/shinken</pre> 对应<pre class="crayon-plain-tag">Windows下%SHINKEN_HOME%\etc</pre> 。</p>
<div class="blog_h1"><span class="graybg">启动和运行</span></div>
<div class="blog_h2"><span class="graybg">验证配置</span></div>
<p>每次修改配置后，你都应该在重启Shinken之前进行验证，因为配置存在问题会导致Shinken无法启动。</p>
<p>调用下面的命令执行验证：</p>
<pre class="crayon-plain-tag">/usr/bin/shinken-arbiter -v -c /etc/shinken/shinken.cfg </pre>
<p>如果配置存在错误，该命令会输出ERROR信息并指出问题所在位置。警告信息一般可以忽略。</p>
<div class="blog_h2"><span class="graybg">启动和停止</span></div>
<pre class="crayon-plain-tag"># 启动
/etc/rc.d/init.d/shinken start
# 重启
/etc/rc.d/init.d/shinken restart
# 停止
/etc/rc.d/init.d/shinken stop</pre>
<div class="blog_h1"><span class="graybg">基础知识</span></div>
<div class="blog_h2"><span class="graybg">shinken命令</span></div>
<p>Shinken提供了一个同名的命令，可以用于在shinken.io上检索、安装，上传<span style="background-color: #c0c0c0;">包（Pack，包含对象定义模板）</span>或者<span style="background-color: #c0c0c0;">模块（扩充Shinken功能的Python模块）</span>。初次使用该命令，需要初始化：</p>
<pre class="crayon-plain-tag"># 首次使用shinken命令时执行
shinken --init</pre>
<div class="blog_h3"><span class="graybg">常用选项</span></div>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 20%; text-align: center;">选项</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>--version</td>
<td>显示版本信息并退出</td>
</tr>
<tr>
<td>--proxy=PROXY</td>
<td>指定代理服务器，格式：<pre class="crayon-plain-tag">http://user:password@proxy-server:port</pre> </td>
</tr>
<tr>
<td>-A API_KEY</td>
<td>上传包时使用的API Key</td>
</tr>
<tr>
<td>-l, --list</td>
<td>列出子命令</td>
</tr>
<tr>
<td>--init</td>
<td>初始化并生成配置文件shinken.ini</td>
</tr>
<tr>
<td>-D</td>
<td>调试模式</td>
</tr>
<tr>
<td>-v</td>
<td>打印更多信息</td>
</tr>
<tr>
<td>-c INICONFIG</td>
<td>指定shinken.ini位置</td>
</tr>
</tbody>
</table>
<div class="blog_h3"><span class="graybg">常用子命令</span></div>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 20%; text-align: center;">子命令</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>desc</td>
<td>列出对象类型的属性</td>
</tr>
<tr>
<td>doc-compile</td>
<td>编译文档</td>
</tr>
<tr>
<td>doc-serve</td>
<td>发布在线文档</td>
</tr>
<tr>
<td>install</td>
<td>从shinken.io下载并安装包</td>
</tr>
<tr>
<td>inventory</td>
<td>列出本地安装的包</td>
</tr>
<tr>
<td>publish</td>
<td>发布包到shinken.io</td>
</tr>
<tr>
<td>search</td>
<td>在shinken.io搜索包</td>
</tr>
<tr>
<td>update</td>
<td>更新一个软件包</td>
</tr>
</tbody>
</table>
<div class="blog_h2"><span class="graybg">基本配置</span></div>
<p>在安装完毕后，你就获得一个基本的Shinken配置，可以直接启动之。</p>
<div class="blog_h3"><span class="graybg">守护程序的配置文件</span></div>
<p>/etc/shinken/daemons目录存放了*.ini文件，这些文件描述了<span style="background-color: #c0c0c0;">在本机需要运行的</span>守护程序。基本配置下Shinken单机运行，因而此目录下有5个文件（Arbiter的配置在主配置文件中）。分别定义Broker、Poller、Reactionner、Receiver、Scheduler这五个守护程序使用的端口、工作目录等重要信息。</p>
<p>需要注意的是，这些守护程序不一定要在单机上运行，你可以分散部署，只需要将它们作为对象引用到主配置文件中。</p>
<p>我们看一下配置文件的内容：</p>
<pre class="crayon-plain-tag">[daemon]

# 该程序启动后，立即修改工作目录为：
workdir = /var/run/shinken
logdir  = /var/log/shinken
# PID文件，有了它以后我们可以杀死该守护程序
pidfile=%(workdir)s/schedulerd.pid
# TCP监听端口，默认：
# scheduler: 7768
# poller: 7771
# reactionner: 7769
# broker: 7772
# arbiter: 7770
port=7768
# TCP监听地址
host=0.0.0.0
# 用于运行守护程序的用户，以及用户的组
user=shinken
group=shinken
# 如果设置为1，则你可以在root用户下运行此守护程序
idontcareaboutsecurity=0

# Set to 0 if you want to make this daemon NOT run
# 是否启用此守护程序，如果设置为0则不会运行
daemon_enabled=1


#-- SSL相关的配置 --
use_ssl=0
# WARNING : Use full paths for certs
#ca_cert=/etc/shinken/certs/ca.pem
#server_cert=/etc/shinken/certs/server.cert
#server_key=/etc/shinken/certs/server.key
hard_ssl_name_check=0
http_backend=auto
daemon_thread_pool_size=16

#-- 和该守护程序相关的本地日志配置 --
# Enabled by default to ease troubleshooting
use_local_log=1
local_log=%(logdir)s/schedulerd.log

# accepted log level values= DEBUG,INFO,WARNING,ERROR,CRITICAL
log_level=WARNING

# The path to the modules directory
modules_dir=/var/lib/shinken/modules</pre>
<div class="blog_h3"><span class="graybg">定义守护程序</span></div>
<p>守护程序作为Shinken架构中的<span style="background-color: #c0c0c0;">一种资源</span>，必须在主配置文件中进行定义，才能被使用。 </p>
<p>通常，<a href="#daemon-def-file">守护程序定义文件</a>依据类型的不同，存放在不同目录中，并且每个文件对应一个守护程序。该文件使用类似于对象定义的语法，描述此守护程序的名称、如何连接、是否Standby（Spare）。下面是一个Scheduler定义的例子：</p>
<pre class="crayon-plain-tag">define scheduler {
    # 守护程序的名称
    scheduler_name      scheduler-master
    # 如何连接到此守护程序
    address             localhost 
    port                7768
    # 是否备用
    spare               0
    # 权重，某些Scheduler可以管理更多的主机
    weight              1
    # PING超时
    timeout             3
    # 数据发送超时
    data_timeout        120 
    # 如果PING超时多少次，认为此节点挂掉
    max_check_attempts  3
    # 每60秒PING此节点
    check_interval      60
    # 此守护程序加载的模块
    modules
    # 所属的领域，用于多数据中心等大型场景
    realm   All
    skip_initial_broks  0
    use_ssl	          0
    hard_ssl_name_check   0
}</pre>
<p>注意，某些守护程序有特殊的配置选项，例如：</p>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 15%; text-align: center;">选项</td>
<td style="width: 15%; text-align: center;">用于</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td><span style="color: #404040;">host_name</span></td>
<td>Arbiter</td>
<td>Arbiter所在的机器的主机名，在高可用性场景下（两个或更多Arbiter）必须配置</td>
</tr>
<tr>
<td><span style="color: #404040;">poller_tags</span></td>
<td>Poller</td>
<td>该Poller管理的Poller tags</td>
</tr>
</tbody>
</table>
<div class="blog_h3"><span class="graybg">定义模块</span></div>
<p>所有守护程序都可以使用模块。对于Broker来说模块是必须的，它依赖模块来完成实际的工作。基本配置没有预定义任何模块。</p>
<p>模块具有公共的选项：</p>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 25%; text-align: center;">选项</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>module_name</td>
<td>模块的名称，用于被其它组件（例如守护程序）引用</td>
</tr>
<tr>
<td>module_type</td>
<td>模块的类型，由模块本身提供的固定值</td>
</tr>
</tbody>
</table>
<p>每个模块具有自己的其它特殊配置项，需要查看模块的文档。</p>
<p>这里，我们定义一个模块，为基本配置增加日志记录的功能：</p>
<pre class="crayon-plain-tag">define module{
     module_name      simple-log
     module_type      simple-log
     path             /var/log/shinken/shinken.log
}</pre>
<p>然后修改默认的Broker：</p>
<pre class="crayon-plain-tag">modules            simple-log</pre>
<p>默认情况下simple-log<span style="background-color: #c0c0c0;">模块是没有安装的</span>，因此你会在/var/log/shinken/brokerd.log中发现警告信息：The module type simple-log for simple-log was not found in modules。执行下面的命令来安装模块：</p>
<pre class="crayon-plain-tag"># 到shinken.io搜索包
shinken search log
# 安装模块到/var/lib/shinken/modules/目录下
shinken install simple-log</pre>
<p>重启Shinken，你会发现所有守护程序的日志被收集到 /var/log/shinken/shinken.log文件中了。</p>
<div class="blog_h2"><span class="graybg">监控插件</span></div>
<p>Shinken包含一系列内部模块，这些模块可以被多种守护程序加载，参与到数据获取中去。这些模块包括NPRE、SNMP等。</p>
<p>Shinken同时<span style="background-color: #c0c0c0;">依赖于外部程序——检查插件（Check plugins）</span>来监控更多种类的设备、应用、以及网络服务。</p>
<p>插件可以是编译好的可执行文件或者脚本，它们可以被调用，以便检查主机/服务的状态。Shinken使用插件的调用返回值来确定<span style="background-color: #c0c0c0;">主机、服务的当前状态</span>，以及被监控<span style="background-color: #c0c0c0;">服务的性能数据</span>。</p>
<p>插件作为监控逻辑组件和被监控主机/服务之间的<span style="background-color: #c0c0c0;">抽象层</span>。具有一定的接口规范，你可以编写自己的插件来监控任何东西。</p>
<div class="blog_h3"><span class="graybg">有哪些插件</span></div>
<p>Shinken插件有很多，支持的监控协议包括：WMI, SNMP, SSH, NRPE, TCP, UDP, ICMP, OPC, LDAP 等。</p>
<p>支持的监控对象包括各种OS、服务器和网络硬件、各种网络协议、各种性能数据、应用程序和数据库。</p>
<div class="blog_h3"><span class="graybg">获取插件</span></div>
<p>插件没有和Shinken运行时一同分发，需要单独获取。可以从：</p>
<ol>
<li><a href="https://www.monitoring-plugins.org/">Monitoring Plugins Project</a></li>
<li><a href="http://www.nagios.org/download/">Nagios Downloads Page</a></li>
<li><a href="http://www.nagiosexchange.org/">NagiosExchange.org</a></li>
</ol>
<p>等地方获取插件。很多插件都提供帮助，你应该通过阅读帮助来了解如何使用之：<pre class="crayon-plain-tag">./check_http --help</pre> </p>
<div class="blog_h2"><span class="graybg">理解并使用宏</span></div>
<p>Shinken的灵活性依赖于宏机制，你可以<span style="background-color: #c0c0c0;">在命令中使用宏</span>。通过宏你可以引用主机、服务等信息。</p>
<p>Shinken宏使用<pre class="crayon-plain-tag">$</pre> 作为其起始、结束标记，如果要在命令中使用$字符必须用<pre class="crayon-plain-tag">$$</pre> 代替。</p>
<div class="blog_h3"><span class="graybg">宏替换</span></div>
<p>在执行命令前，Shinken会替换命令定义中所有宏为实际值，这些值由上下文决定。宏替换发生在任何命令上，包括主机/服务检查、通知、事件处理器等。</p>
<div class="blog_h3"><span class="graybg">参数宏</span></div>
<p>你可以使用<pre class="crayon-plain-tag">$ARGn$</pre> 来访问传递给命令的参数：</p>
<pre class="crayon-plain-tag"># 定义命令
define command{
  command_name    check_ping
  # ARG1表示第一个入参
  command_line    /var/lib/shinken/libexec/check_ping -H $HOSTADDRESS$ -w $ARG1$ -c $ARG2$
}</pre>
<p>调用命令时，以<pre class="crayon-plain-tag">!</pre> 开头向命令传递参数：</p>
<pre class="crayon-plain-tag">define service{
  host_name    linux
  # 调用命令。给check_ping命令传递了两个参数，每个参数以叹号开始
  # 200.0,80%
  # 400.0,40%
  check_command    check_ping!200.0,80%!400.0,40%
}</pre>
<p>如果调用命令需要传递叹号（!）本身，可以使用反斜杠转义。 </p>
<div class="blog_h3"><span class="graybg">On-Demand宏</span></div>
<p>通常，当你使用主机/服务宏时，这些宏指向当前命令所针对的主机/服务。如果你想引用其它主机/服务时，可以使用按需宏机制。</p>
<p>按需宏和普通宏类似，只是它后缀一个用于识别主机/服务的标识符：</p>
<pre class="crayon-plain-tag"># 语法格式。把HOSTMACRONAME、SERVICEMACRONAME替换成真实的宏名称，:后面替换成真实的属性值即可
$HOSTMACRONAME:host_name$
$SERVICEMACRONAME:host_name:service_description$

# 举例
$HOSTDOWNTIME:myhost$   #myhosq的宕机时间
$SERVICESTATEID:server:database$  #server的database服务的状态ID
$CONTACTEMAIL:john$   #john的电子邮件</pre>
<div class="blog_h3"><span class="graybg">On-Demand组宏</span></div>
<p>你还可以使用宏来获得一个组中的全部联系人、主机、服务的属性，使用特定分隔符分隔多个值：</p>
<pre class="crayon-plain-tag">#语法格式。HOSTMACRONAME等替换成真实的宏名称，*group_name替换为真实的组名称，delimiter替换为分隔符即可
$HOSTMACRONAME:hostgroup_name:delimiter$
$SERVICEMACRONAME:servicegroup_name:delimiter$
$CONTACTMACRONAME:contactgroup_name:delimiter$</pre>
<div class="blog_h3"><span class="graybg">定制变量宏</span></div>
<p>你在主机、服务、联系人等的定义中声明的定制对象变量（custom object variables） 均可以作为宏使用：</p>
<pre class="crayon-plain-tag">#语法格式。
$_HOSTvarname$
$_SERVICEvarname$
$_CONTACTvarname$

#举例：
define host{
  ...
  # 定制变量必须以_开头
  _MACADDRESS    00:01:02:03:04:05
  ...
}
# 你可以使用 $_HOSTMACADDRESS$ 来访问MAC地址这一定制变量</pre>
<div class="blog_h3"><span class="graybg">作为环境变量</span></div>
<p>大部分宏被导出为环境变量，脚本或者命令可以很容易的引用之。<pre class="crayon-plain-tag">$USERn$</pre> 和On-Demand宏不可通过环境变量访问。 </p>
<div class="blog_h3"><span class="graybg">标准宏列表</span></div>
<p>参考<a href="https://shinken.readthedocs.io/en/latest/05_thebasics/macrolist.html">官方文档</a>。</p>
<div class="blog_h2"><span class="graybg">主机检查</span></div>
<p>以下时机Shinken的守护程序对主机执行检查：</p>
<ol>
<li>根据主机的<span style="color: #404040;">check_interval、retry_interval选项</span>周期性、定时检查。如果check_interval设置为0则不进行周期性检查</li>
<li>当主机下某个服务的状态改变，按需检查</li>
<li>作为主机可到达性逻辑的一部分，按需检查。这种情况下，主机是路由器等网络设备</li>
<li>在进行预测性主机依赖性检查（predictive host dependency checks）时，按需进行</li>
</ol>
<p>主机检查是<span style="background-color: #c0c0c0;">并行</span>执行的。</p>
<p><span style="background-color: #c0c0c0;">按需检查的性能</span>可以通过<span style="background-color: #c0c0c0;">已缓存的主机检查</span>（Cached Host Checks）极大的提高。Shinken可以放弃检查执行，而使用最近的检查结果。</p>
<p>通过定义主机执行依赖（host execution dependencies），你可以<span style="background-color: #c0c0c0;">基于其它一个或多个主机的状态，禁止某一主机的检查</span>。</p>
<div class="blog_h3"><span class="graybg">主机状态</span></div>
<p>被检查的主机可以处于三种状态之一：UP、DOWN、UNREACHABLE。</p>
<p>主机检查由插件进行，插件的返回状态和主机状态映射如下表。注意，依据插件结果初步判定为DOWN时，需要依赖于父主机状态，来确定主机的真实（最终）状态：</p>
<table class=" fixed-word-wrap full-width">
<thead>
<tr>
<td style="width: 15%; text-align: center;">插件结果</td>
<td style="width: 20%; text-align: center;">主机状态（初步）</td>
<td style="text-align: center;">父主机状态</td>
<td style="text-align: center;">主机状态（最终）</td>
</tr>
</thead>
<tbody>
<tr>
<td>OK</td>
<td>UP</td>
<td> </td>
<td>UP</td>
</tr>
<tr>
<td>WARNING</td>
<td>DOWN*</td>
<td colspan="2" rowspan="3">
<p>至少一个父主机UP，则最终状态为DOWN</p>
<p>所有父主机都DOWN/UNREACHABLE，则最终状态为UNREACHABLE</p>
</td>
</tr>
<tr>
<td>UNKNOWN</td>
<td>DOWN</td>
</tr>
<tr>
<td>CRITICAL</td>
<td>DOWN</td>
</tr>
</tbody>
</table>
<div class="blog_h3"><span class="graybg">状态变更</span></div>
<p>Shinken可能发现主机状态在<span style="color: #404040;">UP/DOWN/UNREACHABLE之间变化，并采取一定的操作。</span></p>
<p>状态变革会导致不同的状态类型（State types）：<span style="color: #404040;">HARD/SOFT，可能相应的触发事件处理器或者通知。</span></p>
<p>当主机状态频繁变化时，称为动荡（<span style="color: #404040;">flapping</span>），动荡的一个例子是，主机由于某种原因反复的重启（例如系统更新导致）。Shinken可以在检测到动荡后暂停通知发送，直到主机状态稳定下来。 </p>
<div class="blog_h2"><span class="graybg">服务检查</span></div>
<p>以下时机Shinken的守护程序对服务执行检查：</p>
<ol>
<li>根据服务的<span style="color: #404040;">check_interval、retry_interval选项</span>周期性、定时检查</li>
<li>在进行预测性服务依赖性检查（predictive service dependency checks）时，按需进行</li>
</ol>
<p>与主机检查一样：</p>
<ol>
<li>缓存可以很大的提高On-demand服务检查的性能</li>
<li>检查是并行执行的</li>
<li>通过定义服务执行依赖（service execution dependencies），你可以基于其它一个或多个服务的状态，禁止某一服务的检查</li>
</ol>
<div class="blog_h3"><span class="graybg">服务状态</span></div>
<p>被检查的服务可以处于几种状态之一：OK、WARNING、UNKNOWN、CRITICAL。</p>
<p>服务检查由插件执行，插件的返回状态直接对应到上面几个服务状态。</p>
<div class="blog_h3"><span class="graybg">状态变更</span></div>
<p>服务的状态变更、动荡的处理和主机类似。</p>
<div class="blog_h2"><span class="graybg">主动检查</span></div>
<p>主动检查是Shinken<span style="background-color: #c0c0c0;">主要使用的检查方式</span>。主动检查由Shinken发起，依据计划周期性的执行。具体步骤如下：</p>
<ol>
<li>周期性、On-demand触发检查</li>
<li>守护程序调用插件，并传递必要信息</li>
<li>插件执行实际的坚持并报告结果给守护程序</li>
<li>守护程序处理结果，执行适当的操作，例如发送通知、执行事件处理器</li>
</ol>
<div class="blog_h2"><span class="graybg">主动数据获取模块</span></div>
<p>集成的数据获取模块，是可以被守护程序启动的组件。这些组件可以高性能的获取数据，效率比周期性的调用插件脚本高。</p>
<p>SNMP数据获取模块：SnmpBooster</p>
<p>NRPE数据获取模块：NRPE</p>
<p>NRPE是一种通信协议，它和安装在远程主机上的代理（Agent）进行交互。</p>
<div class="blog_h2"><span class="graybg">被动检查</span></div>
<p>Shinken也支持被动的得到对象的状态。被动检查由外部程序发起，并将检查结果提交给Shinken。</p>
<p>对于天生异步的、不能通过轮询（Polling）很好的检查的服务，被动检查很适用。适合被动检查的例子包括：</p>
<ol>
<li>SNMP陷阱、安全报警。你永远不知道一定时间内有多少陷阱、报警</li>
<li>安装了代理（Agent）的主机上的聚合检查，这种检查的执行间隔会相当低</li>
<li>直接从英语程序中提交检查结果，不依赖于中介日志文件（syslog、event log等）</li>
</ol>
<div class="blog_h3"><span class="graybg">启用主动检查</span></div>
<p>在主配置文件中设置accept_passive_service_checks为1。对于不需要主动检查的主机、服务，设置passive_checks_enabled为0。</p>
<div class="blog_h3"><span class="graybg">提交服务检查结果</span></div>
<p>外部程序可以向Shinken的外部命令管道（external command pipe）写入一条PROCESS_SERVICE_CHECK_RESULT外部命令，以提交检查结果。该命令的格式为：</p>
<pre class="crayon-plain-tag"># <span style="color: #404040;">timestamp，格式为time_t即1970到现在的秒数。执行服务检查的时间点</span>
# <span style="color: #404040;">host_name，服务所属主机的短名</span>
# <span style="color: #404040;">svc_description，服务定义中的服务描述</span>
# <span style="color: #404040;">return_code，检查结果，0=OK, 1=WARNING, 2=CRITICAL, 3=UNKNOWN</span>
# <span style="color: #404040;">plugin_output，插件的文本输出</span>
[timestamp] PROCESS_SERVICE_CHECK_RESULT;configobjects/host_name;svc_description;return_code;plugin_output</pre>
<p>被检查的服务必须在Shinken中预先定义，否则提交的检查结果自动丢弃。</p>
<div class="blog_h3"><span class="graybg">提交主机检查结果</span></div>
<p>外部程序可以向Shinken的外部命令管道（external command pipe）写入一条<span style="color: #404040;">PROCESS_HOST_CHECK_RESULT</span>外部命令，以提交检查结果。该命令的格式为：</p>
<pre class="crayon-plain-tag"># host_status，主机状态 0=UP, 1=DOWN, 2=UNREACHABLE
[timestamp] PROCESS_HOST_CHECK_RESULT;configobjects/host_name;configobjects/host_status;plugin_output</pre>
<p>与主动检查不同，Shinken不会把结果作为初步结果，进而根据父主机状态判断最终结果。你提交的必须就是主机的实际状态。 </p>
<div class="blog_h2"><span class="graybg">状态类型</span></div>
<p>被监控主机/服务的当前状态（Current state）由两个字段决定：</p>
<ol>
<li>主机或服务的状态（status，先前所有提及的状态，都是这个单词），即OK, WARNING, UP, DOWN...</li>
<li>主机或服务所处的状态类型（State type）</li>
</ol>
<p>状态类型有两种：软状态（SOFT）、硬状态（HARD）。状态类型<span style="background-color: #c0c0c0;">非常重要</span>，它们用于决定何时执行事件处理器，何时发送最初的通知。</p>
<div class="blog_h3"><span class="graybg">重新检查</span></div>
<p>为了防止因为临时故障而错误的报警，Shinken允许配置主机/服务的max_check_attempts。最有在最大尝试次数到达后，才会认为是真正出现问题。</p>
<p>重新检查与状态类型密切相关</p>
<div class="blog_h3"><span class="graybg">软状态</span></div>
<p>以下情况下，服务/主机处于软状态：</p>
<ol>
<li>当服务/主机从OK/UP变为non-OK/non-UP状态后，到达max_check_attempts之前。这种情况称为软错误</li>
<li>当服务/主机从软错误中恢复时。这种情况称为软恢复</li>
</ol>
<p>当对象进入软状态时：</p>
<ol>
<li>日志记录SOFT状态，仅当你在主配置文件启用log_service_retries或log_host_retries时</li>
<li>调用事件处理器来处理SOFT状态。这是软状态下重要的行为，你可以<span style="background-color: #c0c0c0;">在到达HARD状态前积极的修复</span>问题。事件处理器执行时， $HOSTSTATETYPE$、 $SERVICESTATETYPE$宏的值为SOFT提示当前处于软状态</li>
</ol>
<div class="blog_h3"><span class="graybg">硬状态</span></div>
<p>以下情况下，服务/主机处于硬状态：</p>
<ol>
<li>服务/主机从OK/UP变为non-OK/non-UP状态后，到达max_check_attempts之后仍然没有恢复。这种情况称为硬错误</li>
<li>当服务/主机从硬错误转换到其它错误状态时，例如WARNING、CRITICAL</li>
<li>当服务的检查结果是一个non-OK状态且它所属主机为DOWN或UNREACHABLE状态</li>
<li>当服务/主机从硬错误状态恢复。这种情况称为硬恢复</li>
<li>当被动检查结果送达，默认总是认为是硬状态。除非启用passive_host_checks_are_soft选项</li>
</ol>
<p>当对象进入硬状态时：</p>
<ol>
<li>日志记录HARD状态</li>
<li>调用事件处理器来处理HARD状态</li>
<li>通知联系人，告知问题或者恢复。事件处理器执行时， $HOSTSTATETYPE$、 $SERVICESTATETYPE$宏的值为HARD提示当前处于硬状态</li>
</ol>
<div class="blog_h2"><span class="graybg">网络依赖</span></div>
<p>我们常说“外网挂了”，外网真的会挂吗？几乎不可能，问题肯定出现在你的机器到Internet的链路上。链路上的任何一个路由器/交换机出现故障，你都会无法上网。</p>
<p>在Shinken的监控业务中也是这样，守护程序所在机器到目标主机之间的链路上任何一个节点出现故障，目标主机都会处于non-UP状态。Shinken有能力区分这个non-Up是DOWN还是UNREACHABLE，前提是你正确的配置网络依赖。</p>
<p>你必须站在Shinken守护程序的角度来看问题，守护程序需要经过哪些主机（网络设备）才能到到目标主机？你需要把这些中介的设备配置为目标主机的祖先主机，例如：</p>
<pre class="crayon-plain-tag"># 父子关系的配置必须真实的反映网络拓扑
define host{
  host_name    Switch1
  parents    Shinken  #声明自己的父主机，父主机总是离Shinken守护程序更近（跳数少）
}
define host{
  host_name    Web
  parents    Switch1
}
define host{
  host_name    FTP
  parents    Switch1
}
define host{
  host_name    Router1
  parents    Switch1
}
define host{
  host_name    somewebsite.com
  parents    Router1
}</pre>
<p>类似上面的配置，形成从守护程序到目标主机的单向图，Shinken依据此图判断目标主机是不可达，还是宕机。 </p>
<div class="blog_h3"><span class="graybg">多个父主机</span></div>
<p>某些情况下你可能有多重链路可以到达目标主机，此时应该为目标主机（或者链路上的中介节点）配置多个父主机。</p>
<p>只有全部父主机不可达、宕机，子主机才会被判定为不可达。</p>
<div class="blog_h3"><span class="graybg">不可达与通知</span></div>
<p>Shinken只会针对问题的根源（Root problems）发送通知，这避免了发送大量的通知给联系人。只有主机状态是DOWN时通知才会发送，主机是UNREACHABLE时不会发送，但是它的某个祖先主机的DOWN通知可能被发送。</p>
<p>同样的，DOWN/UNREACHABLE主机上服务的通知也不会发送，它们不是问题的根源所在。</p>
<div class="blog_h2"><span class="graybg">逻辑依赖</span></div>
<p>服务和主机（逻辑）依赖是Shinken的高级特性。允许你基于其它主机/服务的状态，来控制目标主机/服务的行为。</p>
<p>以服务依赖为例，一个Web服务常常会依赖于一个数据库服务。如果数据库服务宕机了，你向联系人通知说Web服务挂了是没有意义的。你应该正确配置服务之间的依赖关系，以便Shinken能够报告问题的根源。</p>
<p>关于服务依赖，你需要知道：</p>
<ol>
<li>一个服务可以依赖于1-N个其它服务</li>
<li>一个服务可以依赖于其它主机上的服务</li>
<li>通过服务依赖配置，你可以在服务的某些状态下，抑制检查的执行、通知的发送</li>
<li>依赖关系可以仅在特定时间段内启用</li>
</ol>
<div class="blog_h3"><span class="graybg">服务依赖示例</span></div>
<pre class="crayon-plain-tag"># 位于srv-web上的service服务
define service{
  host_name              srv-web
  service_description    Http
  # 依赖位于srv-db上的mysql服务
  service_dependencies   srv-db,mysql
}</pre>
<div class="blog_h3"><span class="graybg">依赖层次</span></div>
<p>依赖是可以继承（inherited，应该理解为传递性依赖）。以上面的例子讲，假设mysql服务依赖srv-dns,dns，那么http出现问题时会检查mysql，进一步会检查srv-dns以确认问题根源。</p>
<div class="blog_h3"><span class="graybg">结合网络依赖</span></div>
<p>网络依赖同样会影响问题根源的判断，如果http出现问题的同时发现srv-db宕机，那么后者会被看作问题的根源，前者只作为后者的impact。</p>
<div class="blog_h1"><span class="graybg">高级主题</span></div>
<div class="blog_h2"><span class="graybg">性能数据</span></div>
<p>Shinken允许在返回状态数据的同时，附带记录<span style="background-color: #c0c0c0;">可选的性能数据</span>。你可以把性能数据返回给外部程序进行处理。</p>
<div class="blog_h3"><span class="graybg">性能数据的类型</span></div>
<p>性能数据分为两个类别：</p>
<table class=" full-width fixed-word-wrap">
<tbody>
<tr>
<td style="width: 15%;"><strong>检查性能数据</strong></td>
<td>
<p>与主机、服务检查的执行过程本身相关的性能数据，例如检查的：</p>
<ol>
<li>延迟时间，即实际发起检查与计划检查之间的延迟，相关宏 $HOSTLATENCY$、$SERVICELATENCY$ </li>
<li>消耗时间，即检查执行开始到结束的时间，相关宏$HOSTEXECUTIONTIME$、 $SERVICEEXECUTIONTIME$</li>
</ol>
</td>
</tr>
<tr>
<td><strong>插件性能数据</strong></td>
<td>
<p>与特定插件相关，可能包括丢包率、磁盘剩余空间、处理器负载、当前登陆用户数量……等等插件在执行时获取的任何度量数据</p>
<p>插件性能数据相关的宏有$HOSTPERFDATA$ 、$SERVICEPERFDATA$，不是所有插件都支持性能数据</p>
</td>
</tr>
</tbody>
</table>
<div class="blog_h3"><span class="graybg">插件性能数据</span></div>
<p>Shinken插件至少会返回一行<span style="background-color: #c0c0c0;">人类可读</span>的文本，用来描述某种类型的<span style="background-color: #c0c0c0;">可度量数据</span>，例如check_ping插件返回的文本可以如下：</p>
<pre class="crayon-plain-tag">PING ok - Packet loss = 0%, RTA = 0.80 ms</pre>
<p>类似这样的输出，可以通过<pre class="crayon-plain-tag">$HOSTOUTPUT$</pre> 或者<pre class="crayon-plain-tag">$SERVICEOUTPUT$</pre> 宏来获取。 </p>
<p>可选的，插件还可以返回性能数据，以管道符号<pre class="crayon-plain-tag">|</pre> 和上述可读数据分隔：</p>
<pre class="crayon-plain-tag">PING ok - Packet loss = 0%, RTA = 0.80 ms | percent_packet_loss=0, rta=0.80</pre>
<p>输出中的性能数据部分，可以通过 <pre class="crayon-plain-tag">$HOSTPERFDATA$ </pre> 或者<pre class="crayon-plain-tag">$SERVICEPERFDATA$</pre> 宏来获取。</p>
<p>Shinken守护程序不直接处理性能数据，因此它也不关心其格式。</p>
<div class="blog_h3"><span class="graybg">处理性能数据</span></div>
<p>如果你需要处理性能数据，则需要启用process_performance_data选项，并配置Shinken，让性能数据写入到文件，或者执行命令。</p>
<p>选项host_perfdata_command、service_perfdata_command用于指定<span style="background-color: #c0c0c0;">处理性能数据的命令</span>。下面是命令的例子：</p>
<pre class="crayon-plain-tag">define command{
  command_name    store-service-perfdata
  command_line    /bin/echo -e "$LASTSERVICECHECK$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICESTATE$\t$SERVICEATTEMPT$\t
                                $SERVICESTATETYPE$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t
                                $SERVICEPERFDATA$" &gt;&gt; /var/lib/shinken/service-perfdata.dat
}</pre>
<p>调用命令的方式可能会导致较高的CPU负载，特别是需要处理大量主机/服务时，最好先写入文件，然后由外部程序处理。使用host_perfdata_file、service_perfdata_file选项你可以指定<span style="background-color: #c0c0c0;">写入到什么文件</span>；而host_perfdata_file_template、service_perfdata_file_template 选项用于指定<span style="background-color: #c0c0c0;">输出的模板</span>。</p>
<div class="blog_h1"><span class="graybg">配置详解</span></div>
<p>在让Shinken真正能工作之前，你需要配置若干个文件。在目录<pre class="crayon-plain-tag">/etc/shinken/</pre> 下有很多样例配置文件可供参考。</p>
<p>编辑任何配置文件时，都要记住：</p>
<ol>
<li>#开头的行是注释，不进行处理</li>
<li>变量名大小写敏感</li>
</ol>
<div class="blog_h2"><span class="graybg">简介</span></div>
<p>从2.0开始Shinken引入新的配置文件布局，基本的配置文件现在被分割到多个小的文件中。新的布局更好管理，例如一个文件对应一个对象的配置。</p>
<p>配置文件可以分为以下几类：</p>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 20%; text-align: center;">配置文件类别</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>主配置文件</td>
<td>即<pre class="crayon-plain-tag">shinken.cfg</pre> 文件，它是整个配置的入口点，它会作为命令行参数传递给Arbiter</td>
</tr>
<tr>
<td><a id="daemon-def-file"></a>守护程序定义文件</td>
<td>定义守护程序，依据类型的不同存放在不同的目录中，例如poller目录存放的是Poller守护程序<br />目录中每个文件对应一个守护程序实例</td>
</tr>
<tr>
<td>模块定义文件</td>
<td>位于modules目录中，每个模块具有自己的配置文件<br />由于模块由守护程序加载，因而守护程序定义文件会通过<pre class="crayon-plain-tag">module</pre> 指令引用这些模块定义文件</td>
</tr>
<tr>
<td>资源文件</td>
<td>存储用户定义的宏，主要用于存放敏感信息，例如密码<br />在主配置文件中需要使用<pre class="crayon-plain-tag">resource_file</pre> 指令引用资源文件</td>
</tr>
<tr>
<td>对象定义文件</td>
<td>定义各种对象，例如主机、服务、主机组、联系人、联系人组，等等<br />你可以在主配置文件中多次使用<pre class="crayon-plain-tag">cfg_file</pre> 或<pre class="crayon-plain-tag">cfg_dir</pre> 指令，来引用对象定义</td>
</tr>
</tbody>
</table>
<div class="blog_h2"><span class="graybg">主配置文件配置项</span></div>
<table class=" fixed-word-wrap full-width">
<thead>
<tr>
<td style="width: 35%; text-align: center;">配置项</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>cfg_dir</td>
<td rowspan="2">这两个属于声明（statements）而非参数（parameters）<br />Arbiter会这些配置文件，或者目录中的<span style="background-color: #c0c0c0;">.cfg</span>文件。对于目录，Arbiter会<span style="background-color: #c0c0c0;">递归</span>的读取，这些被读取的文件中如果包含这两条声明，会被忽略</td>
</tr>
<tr>
<td>cfg_file</td>
</tr>
<tr>
<td>retention_update_interval</td>
<td>自动的状态保持（State Retention）更新间隔，单位分钟，默认60<br />该参数指示Scheduler自动保存Retention数据的间隔，如果设置为0则不会定期保存，但是Shinken重启或关闭时仍然会保存</td>
</tr>
<tr>
<td>max_service_check_spread</td>
<td rowspan="2">Shinken启动后，最长多少分钟内服务、主机被检查，默认30<br />该参数用于确保主机、服务状态在一定时间内被检查</td>
</tr>
<tr>
<td>max_host_check_spread</td>
</tr>
<tr>
<td>service_check_timeout</td>
<td rowspan="2">服务检查最大消耗时间（秒），如果超时Shinken会杀死Check并返回一个CRITICAL状态并记录超时错误日志。该配置作为终止不正常运作的插件的最后手段。默认值：<br />
<pre class="crayon-plain-tag">service_check_timeout=60
host_check_timeout=30 </pre>
</td>
</tr>
<tr>
<td>host_check_timeout</td>
</tr>
<tr>
<td>timeout_exit_status</td>
<td>超时的退出状态，可选值0、1、2、3，默认2<br />当超时时由Shinken自动设置</td>
</tr>
<tr>
<td>flap_history</td>
<td>对象状态的历史数值的保持数量，这些历史值用于判断对象处于动荡——状态频繁变化——的状态。默认20</td>
</tr>
<tr>
<td>max_plugins_output_length</td>
<td>负责检查的插件（Checks plugin）输出的最大字节数，默认8192</td>
</tr>
<tr>
<td>enable_problem_impacts_states_change</td>
<td>
<p>布尔值0/1默认0，当一个主机/服务受一个根源性问题（例如服务所属的主机、主机的parent宕机）影响时，是否改变其状态</p>
<p>如果启用，服务的状态会变成UNKNOWN而主机的状态会变成<span style="color: #404040;">UNREACHABLE，直到下一轮检查</span></p>
</td>
</tr>
<tr>
<td>disable_old_nagios_parameters_whining </td>
<td>布尔值0/1默认0，如果启用，在检查配置时所有通知、警告消息禁用</td>
</tr>
<tr>
<td>use_timezone</td>
<td>覆盖时区设置</td>
</tr>
<tr>
<td>enable_environment_macros</td>
<td>布尔值0/1默认1，是否将所有标准宏作为环境变量，暴露给检查、通知、事件处理器</td>
</tr>
<tr>
<td>log_initial_states </td>
<td>布尔值0/1默认1，是否强制记录所有主机/服务的初始状态，即使它们是OK</td>
</tr>
<tr>
<td>no_event_handlers_during_downtimes</td>
<td>布尔值0/1默认0，Shinken是否在主机/服务处于计划内宕机时间内，仍然运行事件处理器</td>
</tr>
<tr>
<td style="text-align: center;" colspan="2"><strong>Arbiter默认配置<br /></strong><em>适用于所有Arbiter</em></td>
</tr>
<tr>
<td><em>workdir</em></td>
<td>守护程序的工作目录，默认/var/run/shinken/。对于Arbiter默认值为lock_file所在目录</td>
</tr>
<tr>
<td>lock_file</td>
<td>Arbiter作为后台程序（-d）运行时存放PID的文件</td>
</tr>
<tr>
<td>local_log</td>
<td>守护程序日志文件位置，默认/var/log/shinken/arbiterd.log</td>
</tr>
<tr>
<td>log_level</td>
<td>日志级别，可选：DEBUG,INFO,WARNING,ERROR,CRITICAL，默认WARNING</td>
</tr>
<tr>
<td>shinken_user</td>
<td>Arbiter进程（主进程）的有效（Effective）用户</td>
</tr>
<tr>
<td>shinken_group</td>
<td>Arbiter进程的有效组</td>
</tr>
<tr>
<td>modules_dir</td>
<td>模块存放的目录，默认/var/lib/shinken/modules</td>
</tr>
<tr>
<td>daemon_enabled</td>
<td>布尔值0/1默认1，设置为0则Arbiter不会运行</td>
</tr>
<tr>
<td>use_ssl</td>
<td>布尔值0/1默认0，是否使用SSL，如果启用，则其它守护程序也必须启用</td>
</tr>
<tr>
<td>ca_cert</td>
<td>CA证书</td>
</tr>
<tr>
<td>server_cert</td>
<td>服务器证书</td>
</tr>
<tr>
<td>server_key</td>
<td>服务器密钥</td>
</tr>
<tr>
<td>hard_ssl_name_check</td>
<td>布尔值0/1默认0，启用SSL名称检查</td>
</tr>
<tr>
<td>http_backend</td>
<td>使用的HTTP后端组件，可选：auto, cherrypy, swsgiref</td>
</tr>
<tr>
<td style="text-align: center;" colspan="2"><strong>主配置文件进阶配置项</strong></td>
</tr>
<tr>
<td>perfdata_timeout</td>
<td>主机/服务性能数据处理器命令（performance data processor command ）的处理超时<br />默认5秒，如果超时，处理器被终结并在日志中记录警告</td>
</tr>
<tr>
<td>process_performance_data</td>
<td>是否处理主机/服务检查的性能数据<br />如果你希望使用PNP、NagiosGrapher、Graphite等工具，需要设置为1</td>
</tr>
<tr>
<td>host_perfdata_command</td>
<td rowspan="2">主机/服务的性能数据处理命令<br />每次主机/服务检查后，都会调用这些命令处理性能数据</td>
</tr>
<tr>
<td>service_perfdata_command</td>
</tr>
<tr>
<td>host_perfdata_file</td>
<td rowspan="2">允许你指定一个存储性能数据的文件，供外部程序后续处理</td>
</tr>
<tr>
<td>service_perfdata_file</td>
</tr>
<tr>
<td>host_perfdata_file_template</td>
<td rowspan="2">性能数据文件的格式模板</td>
</tr>
<tr>
<td>service_perfdata_file_template</td>
</tr>
<tr>
<td>host_perfdata_file_mode</td>
<td rowspan="2">性能数据存储文件的操作模式：<br />a 附加模式（默认）；w写模式；p非阻塞的读写模式，写入管道时使用</td>
</tr>
<tr>
<td>service_perfdata_file_mode</td>
</tr>
<tr>
<td>cached_host_check_horizon</td>
<td rowspan="2">多久（秒）以内的历史检查结果被认为是“当前的”<br />默认15秒，过大的值会导致不精确的结果，但是大的值会提高性能</td>
</tr>
<tr>
<td>cached_service_check_horizon</td>
</tr>
<tr>
<td>use_large_installation_tweaks</td>
<td>设置为1，可以在大规模环境下提高性能，但是会丢失一些特性</td>
</tr>
<tr>
<td>enable_flap_detection</td>
<td>是否启用状态动荡检测，默认0</td>
</tr>
<tr>
<td>low_service_flap_threshold</td>
<td rowspan="4">单位百分比，下限默认25，上限默认50<br />用于设定检测状态动荡的上下限阈值</td>
</tr>
<tr>
<td>low_host_flap_threshold</td>
</tr>
<tr>
<td>high_service_flap_threshold</td>
</tr>
<tr>
<td>high_host_flap_threshold</td>
</tr>
<tr>
<td>event_handler_timeout</td>
<td>事件处理器的执行超时时间，默认30秒</td>
</tr>
<tr>
<td>notification_timeout</td>
<td>通知的发送超时时间，默认30秒</td>
</tr>
<tr>
<td>ocsp_timeout</td>
<td>ocsp执行的超时时间，默认15秒</td>
</tr>
<tr>
<td>ochp_timeout</td>
<td>ochp执行的超时时间，默认15秒</td>
</tr>
<tr>
<td>check_service_freshness</td>
<td rowspan="2">是否允许Shinken检测<span style="background-color: #c0c0c0;">被动检查</span>的“新鲜度”，用于确认是否被动检查被定期的发送给Shinken</td>
</tr>
<tr>
<td>check_host_freshness</td>
</tr>
<tr>
<td>service_freshness_check_interval</td>
<td rowspan="2">新鲜度检查的时间间隔，默认60秒</td>
</tr>
<tr>
<td>host_freshness_check_interval</td>
</tr>
<tr>
<td>human_timestamp_log</td>
<td>日志中的时间戳，是否保存为人类可读的方式<br />默认0，保存为unixtime格式</td>
</tr>
<tr>
<td>date_format</td>
<td>日期格式，可选值：iso8601、strict-iso8601、us、euro</td>
</tr>
<tr>
<td>resource_file</td>
<td>指定资源文件的位置</td>
</tr>
<tr>
<td>triggers_dir</td>
<td>指定触发器的位置，会递归的寻找*.trig文件</td>
</tr>
<tr>
<td>idontcareaboutsecurity</td>
<td>是否允许以root身份运行守护程序，默认否</td>
</tr>
<tr>
<td>enable_notifications</td>
<td>是否启用通知机制，默认1</td>
</tr>
<tr>
<td>check_external_commands</td>
<td>指示Shinken是否检查外部命令文件（ External Command File ），以发现需要被Arbiter执行的命令</td>
</tr>
<tr>
<td>command_file</td>
<td>外部命令文件（命名管道）的路径</td>
</tr>
<tr>
<td>execute_service_checks</td>
<td rowspan="2">是否执行主机/服务状态主动检查，默认1</td>
</tr>
<tr>
<td>execute_host_checks</td>
</tr>
<tr>
<td>accept_passive_service_checks</td>
<td rowspan="2">是否接收主机/服务状态被动检查结果，默认1</td>
</tr>
<tr>
<td>accept_passive_host_checks</td>
</tr>
<tr>
<td>enable_event_handlers</td>
<td>是否启用事件处理器</td>
</tr>
<tr>
<td>use_syslog</td>
<td>是否记录系统日志，仅Linux</td>
</tr>
<tr>
<td>log_notifications</td>
<td>是否记录通知发送情况，默认1</td>
</tr>
<tr>
<td>log_event_handlers</td>
<td>是否记录事件处理器执行情况，默认1</td>
</tr>
<tr>
<td>log_external_commands</td>
<td>是否记录外部命令执行情况，默认1</td>
</tr>
<tr>
<td>interval_length</td>
<td>
<p>单位时间间隔（interval）的长度，默认60秒<br />很多其它配置项间接受到该配置项的影响</p>
<p>注意，Shinken<span style="background-color: #c0c0c0;">并没有被设计为硬实时监控</span>系统，因此把这个参数设置为5或者更低的值不是好主意</p>
</td>
</tr>
</tbody>
</table>
<div class="blog_h2"><span class="graybg">对象继承</span></div>
<p>在进行对象定义的时候，你可以使用对象继承机制，降低配置文件字段的冗余。</p>
<div class="blog_h3"><span class="graybg">基础知识</span></div>
<p>所有对象都可以使用以下三个和继承、递归相关的变量：</p>
<pre class="crayon-plain-tag">define someobjecttype{
       object-specific variables ...
       # 对象的名称，可以被其它对象引用，对于同一类型的对象，其名称必须唯一
       name            template_name
       # 你想从中继承属性/变量的“模板对象”
       use             name_of_template_to_use
       # 是否向Shinken注册此定义，如果该定义纯粹是作为模板使用的不完全定义，应该设置为0
       # 默认1，表示注册，该字段不会被继承
       register        [0/1]
}</pre>
<div class="blog_h3"><span class="graybg">本地变量vs继承的变量</span></div>
<p>有一点很重要，对象在<span style="background-color: #c0c0c0;">本地自己定义的变量</span>，总是比继承自模板的<span style="background-color: #c0c0c0;">优先级高</span>。也就是说，对象定义可以覆盖继承得到的值。</p>
<div class="blog_h3"><span class="graybg">继承层次</span></div>
<p>Shinken不限制对象继承的深度，上述的覆盖行为从祖代向子代逐步进行。</p>
<div class="blog_h3"><span class="graybg">定制变量的继承</span></div>
<p>你在主机/服务/联系人中声明的自定义变量（_开头的），可以和普通变量一样被继承。</p>
<div class="blog_h3"><span class="graybg">阻止字符串继承</span></div>
<p>对于字符串类型的变量，你可以将其设置为null，防止从模板继承值：<pre class="crayon-plain-tag">event_handler null</pre> </p>
<div class="blog_h3"><span class="graybg">追加而不覆盖</span></div>
<p>默认的，你在对象里声明一个变量，会覆盖模板中的同名变量。</p>
<p>对于标准变量（非自定义）的<span style="background-color: #c0c0c0;">字符串变量</span>，Shinken支持所谓加性继承（additive inheritance），即把对象声明的值附加到继承值的后面。</p>
<p>要启用加性继承，只需要在声明值的时候<span style="background-color: #c0c0c0;">前缀+号</span>：</p>
<pre class="crayon-plain-tag"># 模板
hostgroups              all-servers

# use模板的对象
hostgroups             +linux-servers,web-servers
# 实际相当于
hostgroups             all-servers,linux-servers,web-servers</pre>
<div class="blog_h3"><span class="graybg">隐含继承</span></div>
<p>通常情况下，你要么继承，要么声明一个变量值，但是由几个例外情况。在这些情况下，Shinken会从相关对象继承值：</p>
<table class=" fixed-word-wrap full-width">
<thead>
<tr>
<td style="text-align: center;">对象类型</td>
<td style="text-align: center;">变量</td>
<td style="text-align: center;">隐含继承源</td>
</tr>
</thead>
<tbody>
<tr>
<td>Services</td>
<td>contact_groups</td>
<td>关联的host定义</td>
</tr>
<tr>
<td>Host Escalations</td>
<td>contact_groups</td>
<td>关联的host定义</td>
</tr>
<tr>
<td>Service Escalations</td>
<td>contact_groups</td>
<td>关联的service定义</td>
</tr>
</tbody>
</table>
<div class="blog_h3"><span class="graybg">多重继承</span></div>
<p> 一个对象可以同时继承多个模板，例如：</p>
<pre class="crayon-plain-tag">define host{
       name                    generic-host
       active_checks_enabled   1
       check_interval          10
       register                0
}
define host{
       name                    development-server
       check_interval          15
       notification_options    d,u,r
       register                0
}
define host{
       use                    generic-host,development-server
       host_name              devweb
}</pre>
<p>对象devweb的实际定义相当于：</p>
<pre class="crayon-plain-tag">define host{
       host_name               devweb1
       active_checks_enabled   1
       check_interval          10
       notification_options    d,u,r
}</pre>
<p>可以看到，声明在<span style="background-color: #c0c0c0;">use列表前面的模板，具有更高的优先级</span>。 </p>
<div class="blog_h3"><span class="graybg">继承覆盖（Inheritance overriding）</span></div>
<p>上面提到过，通过隐含继承，可以让Service自动从Host继承特定变量。对于不支持隐含继承的变量，你可以在主机中使用指令：</p>
<pre class="crayon-plain-tag"># 对于属于该主机的xxx服务，设置其yyy为zzz
service_overrides xxx,yyy zzz
# 支持多行值
service_overrides xxx,yyy zzz
                  aaa,bbb ccc

# 举例
define host {
       host_name               web-back-01
       hostgroups              web
       service_overrides       HTTP,notification_options c,r
}</pre>
<p>这样可以避免从Pack中继承不匹配实际需求的值。</p>
<p>注意：service_overrides属性可以从模板继承。</p>
<div class="blog_h3"><span class="graybg">继承排除（Inheritance exclusions）</span></div>
<p>你可以使用service_excludes指令，从Pack中排除继承得来的服务定义：</p>
<pre class="crayon-plain-tag">define host {
       use                     web-front
       host_name               web-back-01
       service_excludes        mgr
}</pre>
<div class="blog_h2"><span class="graybg">对象定义文件配置项</span></div>
<p>通过多次使用cfg_file、cfg_dir指令，你可以编写多个对象定义文件。安装好Shinken后，/etc/shinken/目录中有很多样例对象定义文件，这些文件存放在各自的目录中。</p>
<div class="blog_h3"><span class="graybg">对象分类</span></div>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 30%; text-align: center;">对象类别</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>主机（Hosts）</td>
<td>
<p>主机是监控逻辑中的中心对象之一。主机包括以下重要特征：</p>
<ol>
<li>主机常常是网络中的一个物理设备，例如服务器、工作站、路由器、交换机、打印机等</li>
<li>主机拥有某种形式的地址，例如IP、MAC</li>
<li>主机拥有1-N个与之关联的服务</li>
<li>主机可以和其它主机具有父子关系，这呈现了真实世界的网络结构，用于网络可到达性检查</li>
</ol>
</td>
</tr>
<tr>
<td>主机组（Host Groups）</td>
<td>
<p>将一系列主机分组，可以：</p>
<ol>
<li>在WebUI中查看一组相关主机的状态</li>
<li>简化配置</li>
</ol>
</td>
</tr>
<tr>
<td>服务（Services）</td>
<td>
<p>服务是监控逻辑中的中心对象之一。它附属于主机，可以是：</p>
<ol>
<li>主机的某个属性值：CPU负载、磁盘用量、启动时间等</li>
<li>主机提供的某种服务：HTTP、POP3、FTP、SSH等</li>
<li>其它与主机关联的东西，例如DNS记录</li>
</ol>
</td>
</tr>
<tr>
<td>服务组（Service Groups）</td>
<td>
<p>将一系列服务分组，可以：</p>
<ol>
<li>在WebUI中查看一组相关服务的状态</li>
<li>简化配置</li>
</ol>
</td>
</tr>
<tr>
<td>联系人（Contacts）</td>
<td>
<p>联系人是指在通知处理中牵涉进来的人员的信息：</p>
<ol>
<li>联系人可以包含1-N种通知方法，例如电话、邮件、即时消息</li>
<li>联系人接收他们负责的主机、服务的通知信息</li>
</ol>
</td>
</tr>
<tr>
<td>联系人组（Contact Groups）</td>
<td>联系人的分组，用于简化通知的配置，例如当特定主机、服务发生故障时通知若干个联系人</td>
</tr>
<tr>
<td>命令（Commands）</td>
<td>
<p>命令用于告知Shinken需要执行什么程序、脚本以便：</p>
<ol>
<li>执行主机、服务检查</li>
<li>发送通知</li>
<li>执行事件处理器</li>
</ol>
<p>等等</p>
</td>
</tr>
<tr>
<td>时间段（Time Periods）</td>
<td>
<p>时间段用于控制：</p>
<ol>
<li>何时主机、服务可以被监控</li>
<li>何时联系人可以被通知</li>
</ol>
</td>
</tr>
</tbody>
</table>
<div class="blog_h3"><span class="graybg">主机定义</span></div>
<p>定义格式： </p>
<pre class="crayon-plain-tag"># 语法
define host {
    optionname   optionvalue
}

# 示例
define host{
    host_name                      bogus-router
    alias                          Bogus Router #1
    address                        192.168.1.254
    parents                        server-backbone
    check_command                  check-host-alive
    check_interval                 5
    retry_interval                 1
    max_check_attempts             5
    check_period                   24x7
    process_perf_data              0
    retain_nonstatus_information   0
    contact_groups                 router-admins
    notification_interval          30
    notification_period            24x7
    notification_options           d,u,r
    realm                          Europe
    poller_tag                     DMZ
    icon_set                       server
}</pre>
<p>选项列表：</p>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 25%; text-align: center;">选项</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td><strong>host_name</strong></td>
<td>用于识别主机的<span style="background-color: #c0c0c0;">短名称</span>，在主机组、服务中引用的就是该名称<br />对应宏<span style="color: #404040;">$HOSTNAME$</span></td>
</tr>
<tr>
<td>alias</td>
<td>用于识别主机的长名称<br />对应宏<span style="color: #404040;">$HOSTALIAS$</span></td>
</tr>
<tr>
<td>display_name</td>
<td>在WebUI中的显示名称，默认为host_name</td>
</tr>
<tr>
<td><strong>address</strong></td>
<td>主机的通信地址，一般是IP<br />对应宏<span style="color: #404040;"> $HOSTADDRESS$</span></td>
</tr>
<tr>
<td>parents</td>
<td>逗号分隔的父主机的短名称，父主机常常是路由器、交换机、防火墙等位于监控服务器与目标主机之间的网络设备<br />位于同一网段的目标主机不需要设置该字段</td>
</tr>
<tr>
<td>hostgroups</td>
<td>逗号分隔的、所属的主机组的短名称</td>
</tr>
<tr>
<td>check_command</td>
<td>用于检查主机开/关状态的命令的短名称，典型情况下命令使用PING来确定主机是否连通，命令必须返回状态码0来表示主机OK，否则Shinken一律认为主机宕机</td>
</tr>
<tr>
<td>initial_state</td>
<td>主机的初始状态，默认的，Shinken认为主机是开启的，可选值：<br /><span style="background-color: #c0c0c0;">o 正常；d 宕机；u不可达</span></td>
</tr>
<tr>
<td><strong>max_check_attempts</strong></td>
<td>如果返回状态不是OK，Shinken会重试对主机的检查的最大次数</td>
</tr>
<tr>
<td>check_interval</td>
<td>周期性的对主机进行检查，检查的间隔<br />除非你修改 interval_length的默认值60，否则单位为分钟</td>
</tr>
<tr>
<td>retry_interval</td>
<td>在到达max_check_attempts前，重新检查的执行间隔<br />除非你修改 interval_length的默认值60，否则单位为分钟</td>
</tr>
<tr>
<td>active_checks_enabled</td>
<td>布尔值0/1，是否启用主动的状态检查</td>
</tr>
<tr>
<td>passive_checks_enabled</td>
<td>布尔值0/1，是否启用被动的状态检查</td>
</tr>
<tr>
<td>check_period</td>
<td>引用时间段的短名，指示何时允许执行主动状态检查</td>
</tr>
<tr>
<td>obsess_over_host</td>
<td> </td>
</tr>
<tr>
<td>check_freshness</td>
<td>布尔值0/1，指示是否对该主机启用freshness checks</td>
</tr>
<tr>
<td>freshness_threshold</td>
<td>指定freshness的阈值（单位秒），如果设置为0则Shinken自动确定阈值</td>
</tr>
<tr>
<td>event_handler</td>
<td>引用一个命令的短名，当主机状态变化时，该命令被作为事件处理器执行 </td>
</tr>
<tr>
<td>event_handler_enabled</td>
<td>布尔值0/1，是否启用事件处理器 </td>
</tr>
<tr>
<td>low_flap_threshold</td>
<td rowspan="2">在状态动荡检测时，指定高、低状态变化阈值</td>
</tr>
<tr>
<td>high_flap_threshold</td>
</tr>
<tr>
<td>flap_detection_enabled</td>
<td>布尔值0/1，是否启状态动荡检测 </td>
</tr>
<tr>
<td>flap_detection_options</td>
<td>状态动荡检测逻辑使用哪些状态，o、d、u的组合，逗号分隔</td>
</tr>
<tr>
<td>process_perf_data</td>
<td>是否对该主机启用性能数据处理</td>
</tr>
<tr>
<td>retain_status_information</td>
<td>是否在Shinken重启后，仍然保持（retain）该主机的状态</td>
</tr>
<tr>
<td>retain_nonstatus_information</td>
<td>是否在Shinken重启后，仍然保持（retain）该主机的非状态信息</td>
</tr>
<tr>
<td><strong>contacts</strong></td>
<td>逗号分隔的联系人短名称 </td>
</tr>
<tr>
<td><strong>contact_groups </strong></td>
<td>逗号分隔的联系人组短名称</td>
</tr>
<tr>
<td><strong>notification_interval</strong></td>
<td>如果主机状态持续在d、u，则在重复通知联系人前需要等待的时间<br />除非你修改interval_length的默认值60，否则单位为分钟</td>
</tr>
<tr>
<td>first_notification_delay</td>
<td>第一次发送通知的延迟时间，如果在此期间主机状态变为o则不会发送通知<br />除非你修改interval_length的默认值60，否则单位为分钟</td>
</tr>
<tr>
<td>notification_period</td>
<td>引用时间段的短名，指示何时允许发送通知</td>
</tr>
<tr>
<td>notification_options</td>
<td>哪些主机状态会导致通知的发送，逗号分隔：<br />d宕机；u不可达；r恢复正常；f开始或结束状态动荡；s计划内的启动和停机<br />如果设置为n，则不会发送任何关于该主机的通知</td>
</tr>
<tr>
<td>notifications_enabled</td>
<td>是否启用针对该主机的状态通知</td>
</tr>
<tr>
<td>stalking_options</td>
<td>启用对该主机哪些状态的跟踪，逗号分隔的o、d、u </td>
</tr>
<tr>
<td>notes</td>
<td>主机的备注字段</td>
</tr>
<tr>
<td>notes_url</td>
<td>主机的备注URL</td>
</tr>
<tr>
<td>action_url</td>
<td>可以提供针对主机的额外操作的URL </td>
</tr>
<tr>
<td>icon_image</td>
<td>主机的图标</td>
</tr>
<tr>
<td>icon_image_alt</td>
<td>图标不可用时显示的文字</td>
</tr>
<tr>
<td>vrml_image</td>
<td>与statuswrl CGI相关 </td>
</tr>
<tr>
<td>statusmap_image</td>
<td>与statusmap相关</td>
</tr>
<tr>
<td>2d_coords</td>
<td>在statusmap CGI中绘制主机时，主机的二维坐标</td>
</tr>
<tr>
<td>3d_coords</td>
<td>在statuswrl CGI中绘制主机时，主机的三维坐标</td>
</tr>
<tr>
<td>realm</td>
<td>定义主机归属的领域，主机将被领域的一个Scheduler管理</td>
</tr>
<tr>
<td>poller_tag</td>
<td>定义主机的poller_tag，该主机上的任何检查，只能被poller_tags包含该poller_tag的Poller执行</td>
</tr>
<tr>
<td>reactionner_tag</td>
<td>与上面类似，指定哪些Reactionner才能处理来自该主机的通知</td>
</tr>
<tr>
<td>business_impact</td>
<td>指示该主机的重要性，0-5之间，默认2，数字越大越重要</td>
</tr>
<tr>
<td>resultmodulations</td>
<td>与resultmodulations对象连接，从而应用modulation到主机 </td>
</tr>
<tr>
<td>escalations</td>
<td>与escalations对象连接，从而应用escalations规则到主机</td>
</tr>
<tr>
<td>business_impact_modulations</td>
<td>与business_impact_modulations对象连接 </td>
</tr>
<tr>
<td>icon_set</td>
<td>设置在Shinken Web UI中的图标，可用值：database, disk, network_service, server</td>
</tr>
<tr>
<td>maintenance_period</td>
<td>指定一个周期性的维护时间</td>
</tr>
<tr>
<td>service_overrides</td>
<td>
<p>用于覆盖属于该主机的服务的选项，在使用继承（inherited，例如从一个pack中）来的服务时很有用，它允许你为服务提供不一样的值</p>
<p>举例：HTTP服务（继承自http pack）用于生产环境时可能需要24x7启用通知，而演示环境可能仅需要工作时间启用通知。这时你可以覆盖：</p>
<pre class="crayon-plain-tag">service_overrides      HTTP,notification_period workhours</pre>
<p>你可以指定多个覆盖项，但是每个项应当占据独立的一行 </p>
</td>
</tr>
<tr>
<td>service_excludes</td>
<td>从主机中排除服务，逗号分隔。服务可能来自从一个pack中继承，或者附加到当前主机所属的组上</td>
</tr>
<tr>
<td>service_includes</td>
<td>和上面的功能类似，但是指出该主机仅<span style="background-color: #c0c0c0;">仅包含</span>的服务 </td>
</tr>
<tr>
<td>labels</td>
<td>任意逗号分隔的多个标签</td>
</tr>
<tr>
<td>business_rule_output_template</td>
<td>商业规则的输出模板</td>
</tr>
<tr>
<td>business_rule_smart_notifications</td>
<td>用于启用智能化的针对商业规则的通知，可以用于在底层问题被确认后，停止继续发送通知 </td>
</tr>
<tr>
<td>business_rule_downtime_as_ack</td>
<td> </td>
</tr>
<tr>
<td>business_rule_host_notification_options</td>
<td> </td>
</tr>
<tr>
<td>business_rule_service_notification_options</td>
<td> </td>
</tr>
<tr>
<td>snapshot_enabled</td>
<td>是否启用针对该主机的快照 </td>
</tr>
<tr>
<td>snapshot_command</td>
<td>执行快照时启动的命令</td>
</tr>
<tr>
<td>snapshot_period</td>
<td>允许快照调用的时间段 </td>
</tr>
<tr>
<td>snapshot_criteria</td>
<td>启用快照的状态列表（通常都是坏的状态），逗号分隔 </td>
</tr>
<tr>
<td>snapshot_interval</td>
<td>两次快照执行的最小间隔<br />除非你修改interval_length的默认值60，否则单位为分钟</td>
</tr>
<tr>
<td>trigger_name</td>
<td>主动/被动检查结果得到后，执行的触发器，触发器文件trigger_name.trig必须被预先保存在触发器目录或者子目录中</td>
</tr>
<tr>
<td>trigger_broker_raise_enabled</td>
<td> </td>
</tr>
</tbody>
</table>
<div class="blog_h3"><span class="graybg">主机组定义</span></div>
<table class=" fixed-word-wrap full-width">
<thead>
<tr>
<td style="width: 25%; text-align: center;">选项</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td><strong>hostgroup_name</strong></td>
<td>用于识别主机组的短名称</td>
</tr>
<tr>
<td><strong>alias</strong></td>
<td>一个较长的别名</td>
</tr>
<tr>
<td>members</td>
<td>归属为该组的主机成员，亦可在主机定义的hostgroups配置项声明归属关系</td>
</tr>
<tr>
<td>hostgroup_members</td>
<td>把其它组的成员加入到本组</td>
</tr>
<tr>
<td>realm</td>
<td>该组的所有成员属于的领域</td>
</tr>
</tbody>
</table>
<div class="blog_h3"><span class="graybg">服务定义</span></div>
<table class=" fixed-word-wrap full-width">
<thead>
<tr>
<td style="width: 25%; text-align: center;">选项</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td><strong>host_name</strong></td>
<td>该服务在哪个主机上运行（属于哪个主机），指定主机的短名</td>
</tr>
<tr>
<td>hostgroup_name</td>
<td>让目标组的所有主机都具有该服务，支持逻辑操作符：<span style="background-color: #c0c0c0;">&amp;逻辑与；|逻辑或（亦可用逗号,）；!逻辑非</span>、支持<span style="background-color: #c0c0c0;">括号限定优先级</span>。举例：<br />
<pre class="crayon-plain-tag">hostgroup_name=(linux|windows)&amp;!qualification,routers</pre>
</td>
</tr>
<tr>
<td><strong>service_description</strong></td>
<td>服务的描述，一个主机下，不得有两个服务具有相同的描述</td>
</tr>
<tr>
<td>display_name</td>
<td>在UI中显示的名称</td>
</tr>
<tr>
<td>servicegroups</td>
<td>所属的服务组的短名，逗号分隔</td>
</tr>
<tr>
<td>is_volatile</td>
<td>声明服务是否“易变的”，默认否</td>
</tr>
<tr>
<td>duplicate_foreach</td>
<td>用于基于一个服务定义，生成多个类似的服务</td>
</tr>
<tr>
<td><strong>check_command</strong></td>
<td>
<p>指定用于检查该服务状态的命令的短名称，主配置文件选项service_check_timeout限制了命令执行的最大时间</p>
<p>由一个内部定义的、特殊用途的命令<pre class="crayon-plain-tag">bp_rule</pre> ，该命令不需要定义。该命令不是执行一个特定的插件，而是<span style="background-color: #c0c0c0;">依据其它服务的状态</span>来执行一个逻辑操作，例如：</p>
<pre class="crayon-plain-tag"># 支持逻辑操作符
# 如果websrv1的apache服务或者websrv2的apache服务OK，并且dbsrv1上的oracle数据库OK
# 那么当前服务的状态判断为OK
bp_rule(websrv1,apache | websrv2,apache) &amp; dbsrv1,oracle</pre>
</td>
</tr>
<tr>
<td><strong>initial_state</strong></td>
<td>
<p>默认的，Shinken认为所有服务的状态是正常（OK），你可以覆盖默认状态：<br /><span style="background-color: #c0c0c0;">o正常；w警告；u未知；c关键（错误）</span>
</td>
</tr>
<tr>
<td><strong>max_check_attempts</strong></td>
<td rowspan="36">参考主机配置同名配置项 </td>
</tr>
<tr>
<td><strong>check_interval</strong></td>
</tr>
<tr>
<td><strong>retry_interval</strong></td>
</tr>
<tr>
<td>active_checks_enabled</td>
</tr>
<tr>
<td>passive_checks_enabled</td>
</tr>
<tr>
<td><strong>check_period</strong></td>
</tr>
<tr>
<td>obsess_over_service</td>
</tr>
<tr>
<td>check_freshness</td>
</tr>
<tr>
<td>freshness_threshold</td>
</tr>
<tr>
<td>event_handler</td>
</tr>
<tr>
<td>event_handler_enabled</td>
</tr>
<tr>
<td>low_flap_threshold</td>
</tr>
<tr>
<td>high_flap_threshold</td>
</tr>
<tr>
<td>flap_detection_enabled</td>
</tr>
<tr>
<td>flap_detection_options</td>
</tr>
<tr>
<td>process_perf_data</td>
</tr>
<tr>
<td>retain_status_information</td>
</tr>
<tr>
<td>retain_nonstatus_information</td>
</tr>
<tr>
<td><strong>notification_interval</strong></td>
</tr>
<tr>
<td>notification_interval</td>
</tr>
<tr>
<td>notification_period</td>
</tr>
<tr>
<td>notification_options</td>
</tr>
<tr>
<td>notifications_enabled</td>
</tr>
<tr>
<td><strong>contacts</strong></td>
</tr>
<tr>
<td><strong>contact_groups</strong></td>
</tr>
<tr>
<td>stalking_options</td>
</tr>
<tr>
<td>notes</td>
</tr>
<tr>
<td>notes_url</td>
</tr>
<tr>
<td>action_url</td>
</tr>
<tr>
<td>icon_image</td>
</tr>
<tr>
<td>icon_image_alt</td>
</tr>
<tr>
<td>poller_tag</td>
</tr>
<tr>
<td>reactionner_tag</td>
</tr>
<tr>
<td>business_impact</td>
</tr>
<tr>
<td>icon_set</td>
</tr>
<tr>
<td>maintenance_period</td>
</tr>
<tr>
<td>service_dependencies</td>
<td>
<p>定义该服务依赖的其它服务，在通知时有用，为了避免通知泛滥，Shinken只会将Root问题通知给联系人，此配置项用于发现问题的根</p>
<p>值格式：<pre class="crayon-plain-tag">host,service_description,host,service_description</pre> ，其中主机可以<span style="background-color: #c0c0c0;">忽略，表示依赖于当前主机</span>下的服务</p>
</td>
</tr>
<tr>
<td>host_dependency_enabled</td>
<td>可以移除服务和它的主机之间的依赖关系，对于需要依据其自身而不是所属主机进行通知的volatile服务有用</td>
</tr>
<tr>
<td>labels</td>
<td rowspan="13">参考主机配置同名配置项 </p>
<p>&nbsp;</p>
</td>
</tr>
<tr>
<td>business_rule_output_template</td>
</tr>
<tr>
<td>business_rule_smart_notifications</td>
</tr>
<tr>
<td>business_rule_downtime_as_ack</td>
</tr>
<tr>
<td>business_rule_host_notification_options</td>
</tr>
<tr>
<td>business_rule_service_notification_options</td>
</tr>
<tr>
<td>snapshot_enabled</td>
</tr>
<tr>
<td>snapshot_command</td>
</tr>
<tr>
<td>snapshot_period</td>
</tr>
<tr>
<td>snapshot_criteria</td>
</tr>
<tr>
<td>snapshot_interval</td>
</tr>
<tr>
<td>trigger_name</td>
</tr>
<tr>
<td>trigger_broker_raise_enabled</td>
</tr>
</tbody>
</table>
<div class="blog_h1"><span class="graybg">集成</span></div>
<div class="blog_h2"><span class="graybg">如何查看数据</span></div>
<p>通过Shinken支持的接口，管理员可以直观的看到监控数据，例如主机/服务的状态。</p>
<p>Shinken自带一个WebUI，你也可以使用其它开源/商业的Web前端，这些前端使用<span style="background-color: #c0c0c0;">LiveStatus API</span>或者S<span style="background-color: #c0c0c0;">QL backend</span>。LiveStatus具有很好的实时性、可扩容性和灵活性。</p>
<div class="blog_h2"><span class="graybg">基于内存直接访问的UI</span></div>
<div class="blog_h3"><span class="graybg">使用Shinken WebUI</span></div>
<p>安装必要的模块：</p>
<pre class="crayon-plain-tag"># Web UI
shinken install webui
# 身份验证机制
shinken install auth-cfg-password
# 用户配置存储
shinken install sqlitedb</pre>
<p>修改模块定义（安装WebUI模块后，<span style="background-color: #c0c0c0;">此定义会自动生成</span>）：</p>
<pre class="crayon-plain-tag">define module {
    module_name         webui
    module_type         webui
    host                0.0.0.0     # 监听所有网络接口
    port                7767
    auth_secret         CHANGEME    # 修改，防止Cookie伪造
    allow_html_output   1           # 是否允许插件输出HTML特殊字符
    max_output_length   1024        # 插件输出的最大长度
    manage_acl          1           # Use contacts ACL. 0 allow actions for all.
    play_sound          0           # 出现新的未确认问题时播放声音
    login_text          Welcome on Shinken WebUI   # 登陆表单提示信息
    modules             auth-cfg-password SQLitedb # 使用Shinken联系人进行身份验证，使用SQLitedb存储用户设置
}</pre>
<p>修改用于登陆的联系人：</p>
<pre class="crayon-plain-tag"># 基本配置已经包含此联系人
define contact{
    use             generic-contact
    contact_name    admin
    email           shinken@localhost
    # 修改密码
    password        admin             
    is_admin        1
    expert          1
}</pre>
<p>然后，需要让代理加载此模块定义：</p>
<pre class="crayon-plain-tag">define broker {
    ...
    modules   webui
}</pre>
<p>现在你可以访问 http://ip:7767/user/login并登陆了。</p>
<p><span class="graybg"><span style="font-weight: bold;">使用Shinken WebUI2</span> </span></p>
<p>新版本的WebUI，内部集成了身份验证、存储、日志模块，简化了安装和配置。</p>
<p>安装模块：</p>
<pre class="crayon-plain-tag">pip install bottle
shinken install webui2</pre>
<p>完毕后修改代理定义，把webui模块改为webui2，重启Shinken即可。</p>
<div class="blog_h2"><span class="graybg">基于网络访问（Livestatus）的UI</span></div>
<p>基于Livestatus的前端包括：</p>
<ol>
<li>Thruk，适用于中小规模的场景</li>
<li>Multisite，适用于最大规模的可扩容性需求</li>
<li>Nagvis，用于图形化的展示，可以显示网络拓扑图，并标注每个主机的状态</li>
</ol>
<div class="blog_h3"><span class="graybg">启用Livestatus模块</span></div>
<p>获得livestatus模块定义：</p>
<pre class="crayon-plain-tag"># 使用SQLite存储历史日志
shinken install logstore-sqlite
# 获得livestatus模块定义
shinken install livestatus</pre>
<p>在代理定义中加载livestatus模块</p>
<pre class="crayon-plain-tag">define broker {
    modules   webui2,livestatus
} </pre>
<div class="blog_h2"><span class="graybg">使用Thruk作为Shinken前端</span></div>
<div class="blog_h3"><span class="graybg">安装Thruk</span></div>
<p>禁用SELinux： </p>
<pre class="crayon-plain-tag">SELINUX=disabled</pre>
<p>安装必要的软件：</p>
<pre class="crayon-plain-tag">yum install httpd
yum install mod_fcgid

wget http://download.thruk.org/pkg/v2.08/rhel7/x86_64/libthruk-2.08-1.rhel7.x86_64.rpm
rpm -ivh ./libthruk-2.08-1.rhel7.x86_64.rpm
wget http://download.thruk.org/pkg/v2.08/rhel7/x86_64/thruk-base-2.08-1.rhel7.x86_64.rpm
rpm -ivh ./thruk-base-2.08-1.rhel7.x86_64.rpm 
wget http://download.thruk.org/pkg/v2.08/rhel7/x86_64/thruk-plugin-reporting-2.08-1.rhel7.x86_64.rpm
rpm -ivh ./thruk-plugin-reporting-2.08-1.rhel7.x86_64.rpm
wget http://download.thruk.org/pkg/v2.08/rhel7/x86_64/thruk-2.08-1.rhel7.x86_64.rpm
rpm -ivh ./thruk-2.08-1.rhel7.x86_64.rpm 

chkconfig httpd on
service httpd start</pre>
<p>上述步骤完毕后，你可以通过<span style="background-color: #c0c0c0;">http://ip/thruk/</span>来访问Thruk了，默认登陆用户名密码是thrukadmin/thrukadmin。</p>
<div class="blog_h3"><span class="graybg">将Shinken配置为Thruk的后端</span></div>
<pre class="crayon-plain-tag">enable_shinken_features = 1
&lt;Component Thruk::Backend&gt;
    &lt;peer&gt;
        name   = External Shinken
        type   = livestatus
        &lt;options&gt;
            peer    = 127.0.0.1:50000
        &lt;/options&gt;
    &lt;/peer&gt;
&lt;/Component&gt;</pre>
<p>注意livestatus的IP和端口要和livestatus的模块定义匹配。</p>
<div class="blog_h3"><span class="graybg">连通性测试</span></div>
<p>完成配置后，重启Shinken，然后登陆到Thruk。在左侧菜单点击Config Tool，右上角Configuration Type选择Backends，点击Test测试。参考下图：<img class="aligncenter size-full wp-image-12150" src="https://blog.gmem.cc/wp-content/uploads/2016/06/Selection_001.png" alt="Selection_001" width="361" height="253" /></p>
<p>注意：从启动Shinken到livestatus可用，可能需要几分钟时间。</p>
<div class="blog_h1"><span class="graybg">如何监控...</span></div>
<div class="blog_h2"><span class="graybg">Windows设备</span></div>
<p>你可以使用预定义的模板来监控Windows设备，并获得内存用量、CPU负载、磁盘用量、系统服务状态、进程、系统事件日志等方面的信息。</p>
<div class="blog_h3"><span class="graybg">监控方式</span></div>
<p>有两种方法监控Windows设备：</p>
<ol>
<li>基于代理的方式：在目标设备上安装NSClient++</li>
<li>无代理的方式：通过WMI协议直接通过网络轮询Windows状态</li>
</ol>
<div class="blog_h3"><span class="graybg">基于WMI的监控</span></div>
<p>前提条件：你需要一个合法的Windows本地/域账号，用于执行WMI查询。</p>
<p>安装windows包：<pre class="crayon-plain-tag">shinken install windiws</pre> </p>
<p>安装必要的Perl模块：</p>
<pre class="crayon-plain-tag">yum -y install perl-Number-Format 
yum -y install perl-Config-IniFiles 
yum -y install -y perl-DateTime  </pre>
<p>修改主机配置：</p>
<pre class="crayon-plain-tag">define host{
   # 继承windows模板
   use                     windows  
   _DOMAIN                 $DOMAIN$
   _DOMAINUSERSHORT        logonuser
   _DOMAINPASSWORD         passwd
}</pre>
<div class="blog_h2"><span class="graybg">Linux设备</span></div>
<p>与Windows设备的监控类似，你也可以监控Linux的内存用量、CPU负载、磁盘用量、进程等方面的信息。</p>
<div class="blog_h3"><span class="graybg">监控方式</span></div>
<p>你可以通过多种方式来监控Linux：</p>
<ol>
<li>通过SNMP代理</li>
<li>基于一个本地的代理，可以高频率获取数据，支持主动、被动通信方式</li>
<li>基于SSH的方式，只适用于非频繁的检测，可扩容性差</li>
</ol>
<div class="blog_h3"><span class="graybg">基于SNMP的监控</span></div>
<p>首先，你需要在<span style="background-color: #c0c0c0;">目标设备上</span>安装SNMP守护程序：</p>
<pre class="crayon-plain-tag"># CentOS 7
yum install net-snmp net-snmp-devel net-snmp-libs net-snmp-utils
systemctl enable snmpd
systemctl start  snmpd

# Debian/Ubuntu
apt-get install snmpd
sudo update-rc.d snmpd defaults
service snmpd start</pre>
<p>修改snmpd的配置文件：</p>
<pre class="crayon-plain-tag"># Ubuntu 14.04
# 注释掉 agentAddress  udp:127.0.0.1:161，添加
agentAddress udp:161,udp6:[::1]:161
# 将 rocommunity public  default    -V systemonly 改为
rocommunity public

# CentOS 7
# 把默认的两行view systemview去掉，改为：
view systemview included .1.3.6.1

# 最好更改团体名（下面的public），以避免安全问题
# CentOS 7
com2sec notConfigUser  default       public
# Ubuntu 14.04
rocommunity public  default    -V systemonly</pre>
<p>然后，你需要在监控服务器上执行以下操作：</p>
<ol>
<li>安装Perl的SNMP支持：<pre class="crayon-plain-tag">yum -y install perl-Net-SNMP</pre> </li>
<li>安装相关Shinken包：<pre class="crayon-plain-tag">shinken install linux-snmp</pre> </li>
<li>修改主机配置：<br />
<pre class="crayon-plain-tag">define host{
    # 继承linux-snmp模板
    use                 linux-snmp
    # 指定团体名，默认是读取宏$SNMPCOMMUNITYREAD$的值，你可以在资源中定义该宏
    _SNMPCOMMUNITY      public
    # 监控哪个网络接口的使用情况
    _NET_IFACES         eth0
}</pre>
</li>
</ol>
<p>完毕后，重启Shinken即可。</p>
<div class="blog_h2"><span class="graybg">路由器和交换机</span></div>
<p>某些廉价的交换机、集线器没有IP地址，因而无法监控。相反的，一些高档网络设备则提供SNMP查询功能。</p>
<p>Shinken支持监控：</p>
<ol>
<li>丢包率、延迟</li>
<li>SNMP状态信息，需要交换机支持SNMP</li>
<li>带宽/通信速率，需要安装MRTG，需要交换机支持SNMP</li>
</ol>
<div class="blog_h3"><span class="graybg">监控丢包率</span></div>
<pre class="crayon-plain-tag">define service{
   use                    generic-service
   host_name              router
   service_description    PING
   # CRITICAL：RTA大于600ms或者丢包率不小于60%
   # WARNING：RTA大于200ms或者丢包率不小于20%
   # OK：RTA小于200ms并且丢包率小于20%
   check_command          check_ping!200.0,20%!600.0,60%
}</pre>
<div class="blog_h3"><span class="graybg">监控SNMP</span></div>
<p>你可以执行命令：<pre class="crayon-plain-tag">snmpwalk -v1 -c public 192.168.1.1 -m ALL .1</pre> 来获取路由器/交换机上可以监控的信息列表。</p>
<p>监控命令举例：</p>
<pre class="crayon-plain-tag"># 监控路由器已经启动的时间
check_command        check_snmp!-C public -o sysUpTime.0
# 监控端口1的连接状态
check_command       check_snmp!-C public -o ifOperStatus.1 -r 1 -m RFC1213-MIB</pre>
<div class="blog_h3"><span class="graybg">监控带宽/速率</span></div>
<p>如果你安装了<a href="http://oss.oetiker.ch/mrtg/">MRTG </a>，则Shinken支持通过<pre class="crayon-plain-tag">check_mrtgtraf</pre> 插件来监控路由器的带宽使用情况：</p>
<pre class="crayon-plain-tag">define service{
   use                 generic-service
   host_name           router
   # 端口1的带宽使用情况
   service_description Port 1 Bandwidth Usage
   check_command       check_local_mrtgtraf!/var/lib/mrtg/192.168.1.253_1.log!AVG!1000000,2000000!5000000,5000000!10
}</pre>
<div class="blog_h3"><span class="graybg">使用check_nwc_health</span></div>
<p>通过该插件，你可以监控任意支持SNMP的网络设备（主要是交换机、路由器）的网络使用情况、CPU负载、内存使用、端口使用、硬件状态等方面的信息。 监控命令举例：</p>
<pre class="crayon-plain-tag"># 列出所有接口的状态
/var/lib/shinken/libexec/check_nwc_health --hostname 192.168.0.1 --timeout 60 --community "public" --mode interface-status
# 显示健康状态 
/var/lib/shinken/libexec/check_nwc_health --hostname 192.168.0.1 --timeout 60 --community "public" --mode hardware-health</pre>
<div class="blog_h2"><span class="graybg">监控打印机</span></div>
<p>支持JetDirect协议的打印机往往也启用了SNMP，可以通过插件check_hpjd监控之。</p>
<p>安装包：<pre class="crayon-plain-tag">shinken install hp-printers</pre> </p>
<p>修改主机配置：</p>
<pre class="crayon-plain-tag">define host {
    use    printer-hp
} </pre>
<div class="blog_h2"><span class="graybg">公共服务</span></div>
<p>这里的公共服务是指对外开放的，可以通过网络访问的服务、应用或者协议。公共服务的例子包括：HTTP、POP3、IMAP、FTP、SSH等。</p>
<div class="blog_h3"><span class="graybg">用于监控公共服务的插件</span></div>
<p>官方的<span style="color: #404040;">Nagios/Shinken插件支持很多常见服务、协议的监控。如果找不到合适的插件，你也可以自己开发。</span></p>
<div class="blog_h3"><span class="graybg">监控HTTP/HTTPS</span></div>
<p>安装http包：<pre class="crayon-plain-tag">shinken install http</pre> </p>
<p>修改主机配置：</p>
<pre class="crayon-plain-tag">define host{
        # 继承http或（和）https模板
        use                http,https  
        # 监听端口
        _CHECK_HTTP_PORT   80
        _CHECK_HTTPS_PORT  443
        # 测试的URI
        _CHECK_HTTP_URI    /index.html
        _CHECK_HTTPS_URI   /index.html
}</pre>
<div class="blog_h3"><span class="graybg">监控FTP</span></div>
<p>安装ftp包：<pre class="crayon-plain-tag">shinken install ftp</pre> </p>
<p>修改主机配置：</p>
<pre class="crayon-plain-tag">define host{
        # 继承ftp模板
        use               ftp
}</pre>
<div class="blog_h3"><span class="graybg">监控SSH</span></div>
<p>安装ssh包：<pre class="crayon-plain-tag">shinken install ssh</pre>  </p>
<p>修改主机配置，继承ssh。注意，如果你的主机已经继承linux，则不需要再继承ssh。</p>
<div class="blog_h3"><span class="graybg">监控MySQL</span></div>
<p>使用Shinken你可以很好的监控MySQL的运行状态，获取包括InnoDB缓冲池状态、连接数、查询缓存命中率、缓慢查询、锁争用在内的数据。</p>
<p>安装mysql包：<pre class="crayon-plain-tag">shinken install mysql</pre> </p>
<p>安装MySQL的Perl驱动：<pre class="crayon-plain-tag">yum install -y perl-DBD-MySQL</pre> </p>
<p>修改主机配置：</p>
<pre class="crayon-plain-tag">define host{
        # 继承MySQL模板
        use                     mysql
        _MYSQLUSER              pems
        _MYSQLPASSWORD          pemsroot
} </pre>
<div class="blog_h3"><span class="graybg">监控IIS</span></div>
<p>前提条件：你需要一个合法的Windows本地/域账号。</p>
<p>你可以监控：连接数、错误数量、登陆用户数等方面的信息。</p>
<p>安装需要的包：</p>
<pre class="crayon-plain-tag">shiken install windows
shinken install  iis</pre>
<p>修改主机配置：</p>
<pre class="crayon-plain-tag">define host {
    # 继承iis和windows
    user    iis,windows
}</pre>
<div class="blog_h3"><span class="graybg">监控其它公共服务</span></div>
<p>Shinken还提供了很多其它的包，方便你监控常见的服务：</p>
<pre class="crayon-plain-tag"># 监控邮件服务
shinken install imap
shinken install smtp
shinken install pop3</pre>
<div class="blog_h1"><span class="graybg">常见问题</span></div>
<div class="blog_h2"><span class="graybg">主机检查报错：[Errno 2] No such file or directory</span></div>
<div class="blog_h3">报错示例</div>
<p>[1467096368] ERROR: [Shinken] Fail launching command: /usr/lib/nagios/plugins/check_ping -H localhost -w 1000,100% -c 3000,100% -p 1 [Errno 2] No such file or directory False</p>
<div class="blog_h3"><span class="graybg">报错原因</span></div>
<p>Shinken基本配置中的命令，主要是调用$NAGIOSPLUGINSDIR$目录下的监控插件（命令行），例如：</p>
<pre class="crayon-plain-tag">define command {
    command_name    check_ping
    command_line    $NAGIOSPLUGINSDIR$/check_icmp -H $HOSTADDRESS$ -w 3000,100% -c 5000,100% -p 10
}</pre>
<p>宏$NAGIOSPLUGINSDIR$指向插件的安装目录，该宏的默认值定义在： </p>
<pre class="crayon-plain-tag"># Nagios legacy macros
$USER1$=$NAGIOSPLUGINSDIR$
$NAGIOSPLUGINSDIR$=/usr/lib/nagios/plugins

#-- Location of the plugins for Shinken
$PLUGINSDIR$=/var/lib/shinken/libexec</pre>
<p>如果你没有安装这些插件，或者安装位置不是/usr/lib/nagios/plugins，就会报找不到文件的错误。</p>
<div class="blog_h3"><span class="graybg">解决办法</span></div>
<p>你可以从多个地方获取插件：</p>
<ol>
<li><a href="http://www.nagios-plugins.org/download/nagios-plugins-2.1.1.tar.gz">Nagios Core Plugins</a>：你可以下载50个核心Nagios插件</li>
<li><a href="https://www.monitoring-plugins.org/">The Monitoring Plugins Project</a>：监控插件项目，这个开源项目维护更多的插件</li>
</ol>
<p>安装插件的示例脚本：</p>
<pre class="crayon-plain-tag">yum -y install openssl openssl-devel

wget https://www.monitoring-plugins.org/download/monitoring-plugins-2.1.2.tar.gz
tar xzf monitoring-plugins-2.1.2.tar.gz 
cd monitoring-plugins-2.1.2/
./configure --with-openssl
make &amp;&amp; make install</pre>
<p>修改宏定义，指向监控插件实际安装目录：</p>
<pre class="crayon-plain-tag">$NAGIOSPLUGINSDIR$=/usr/local/libexec</pre>
<div class="blog_h2"><span class="graybg">https服务检查报错</span></div>
<div class="blog_h3"><span class="graybg">check_http: Invalid option - SSL is not available</span></div>
<p>出现此错误的原因是编译插件的时候没有安装OpenSSL，参考上面的脚本，先安装OpenSSL再配置、构建、安装插件。</p>
<div class="blog_h2"><span class="graybg">检查MySQL报错</span></div>
<div class="blog_h3"><span class="graybg">cannot connect to information_schema. Can't locate DBI.pm</span></div>
<p>出现此错误的原因是没有安装Perl的MySQL驱动，安装即可：<pre class="crayon-plain-tag">yum -y install -y perl-DBD-MySQL</pre> </p>
<div class="blog_h2"><span class="graybg">监控Windows设备时报错</span></div>
<div class="blog_h3"><span class="graybg">Can't locate Number/Format.pm</span></div>
<p>出现此错误的原因是缺少对应的Perl模块，安装即可：<pre class="crayon-plain-tag">yum -y install perl-Number-Format</pre> </p>
<div class="blog_h3"><span class="graybg">can't locate Config/IniFiles.pm </span></div>
<p>出现此错误的原因是缺少对应的Perl模块，安装即可：<pre class="crayon-plain-tag">yum -y install perl-Config-IniFiles</pre> </p>
<div class="blog_h3"><span class="graybg">Can't locate DateTime.pm</span></div>
<p>出现此错误的原因是缺少对应的Perl模块，安装即可：<pre class="crayon-plain-tag">yum -y install -y perl-DateTime</pre> </p>
<div class="blog_h2"><span class="graybg">CentOS下Shinken启动System V脚本报错</span></div>
<div class="blog_h3"><span class="graybg">log_warning_msg: command not found </span></div>
<p>安装缺少的函数库：<pre class="crayon-plain-tag">yum -y install redhat-lsb redhat-lsb-core</pre> </p>
<div class="blog_h2"><span class="graybg">基于SNMP的监控报错</span></div>
<div class="blog_h3"><span class="graybg">/bin/sh: /var/lib/shinken/libexec/check_netint.pl: No such file or directory</span></div>
<p>某些Shinken插件可能没有随基本配置安装，你可以到<a href="https://github.com/Sysnove/shinken-plugins">shiken-plugins</a>网站下载：</p>
<pre class="crayon-plain-tag">cd /var/lib/shinken/libexec
wget https://raw.githubusercontent.com/Sysnove/shinken-plugins/master/check_netint.pl
chmod +x check_netint.pl</pre>
<div class="blog_h3"><span class="graybg">/bin/sh: /var/lib/shinken/libexec/check_nwc_health: No such file or directory</span></div>
<p>该插件是Native应用程序，需要手工编译：</p>
<pre class="crayon-plain-tag">wget https://labs.consol.de/assets/downloads/nagios/check_nwc_health-5.7.1.1.tar.gz
tar xzf check_nwc_health-5.7.1.1.tar.gz  &amp;&amp; rm -f check_nwc_health-5.7.1.1.tar.gz
cd check_nwc_health-5.7.1.1/
./configure  &amp;&amp; make
cp plugins-scripts/check_nwc_health* /var/lib/shinken/libexec/</pre>
<div class="blog_h3"><span class="graybg">Can't locate Module/Load.pm in @INC </span></div>
<pre class="crayon-plain-tag"># 初次使用cpanm命令时
cpan App::cpanminus

# 安装Load模块
cpanm Module::Load

# cpanm默认安装位置为~/perl5/lib/perl5/无法被check_nwc_health命令找到，因此需要手工拷贝一下
mkdir /usr/lib64/perl5/vendor_perl/Module
cp /root/perl5/lib/perl5/Module/Load.pm /usr/lib64/perl5/vendor_perl/Module</pre>
<p>&nbsp;</p>
</div><p>The post <a rel="nofollow" href="https://blog.gmem.cc/shinken-study-note">Shinken学习笔记</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.gmem.cc/shinken-study-note/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
