Python模板-Mako语法介绍

 python  Python模板-Mako语法介绍已关闭评论
9月 052019
 

资源

官网 http://www.makotemplates.org/

文档 http://docs.makotemplates.org/en/latest/

文档翻译 Mako模板入门 http://help.42qu.com/code/mako.html

安装

pip install mako

HelloWorld

from mako.template import Template

mytemplate = Template("hello world!")
print mytemplate.render()

-------------------------

from mako.template import Template
print Template("hello ${data}!").render(data="world")

语法

输出变量 ${x}

数学计算 ${1+1}
the contents within the ${} tag are evaluated by Python directly, so full expressions are OK

filter
${"test"|u}
${"test"|u,trim}
内置filter列表
    u : URL escaping, provided by urllib.quote_plus(string.encode('utf-8'))
    h : HTML escaping, provided by markupsafe.escape(string)
    x : XML escaping
    trim : whitespace trimming, provided by string.strip()
    entity : produces HTML entity references for applicable strings, derived from htmlentitydefs
    unicode (str on Python 3): produces a Python unicode string (this function is applied by default)
    decode.<some encoding> : decode input into a Python unicode with the specified encoding
    n : disable all default filtering; only filters specified in the local expression tag will be applied.

分支
% if x == 5:
    abcd
% endif

循环
% for a in ['1', '2', '3']:
    % if a == '1':
      abc
    % elif a == '2':
      def
    % else:
      gh
    % endif
$ endfor

Python语法
this is a template
<%
    x = db.get_resource('foo')
    y = [z.element for z in x if x.frobnizzle==5]
%>
% for elem in y:
    element: ${elem}
% endfor

换行

加 / 强制不换行


设置变量
% for item in ('apple', 'banana'):
    <%
        isBanana = False
    %>
    % if item == 'banana':
    <%
        isBanana = True
    %>
    %endif
    % if isBanana:
        <span> Bought a banana</span>
    %endif
%endfor

注释

## 这是一个注释.
...text ...

多行
<%doc>
这里是注释
更多注释
</%doc>

模块级别语句

<% %> 的一个变体是 <%! %>,代表模块级别的代码块。其中的代码会在模板的模块级别执行,而不是在模板的 rendering 函数中。

<%!
import mylib
import re

def filter(text):
    return re.sub(r'^@', '', text)
%>

标签

定义了当前模板的总体特性,包括缓存参数,以及模板被调用时期待的参数列表(非必须)
<%page args="x, y, z='default'"/>
<%page cached="True" cache_type="memory"/>


<%include file="header.html"/>
hello world
<%include file="footer.html"/>

%def 标签用于定义包含一系列内容的一个 Python 函数,此函数在当前模板的其他某个地方被调用到
<%def name="myfunc(x)">
this is myfunc, x is ${x}
</%def>
${myfunc(7)}

<%block filter="h">
some <html> stuff.
</%block>
<%block name="header">
    <h2><%block name="title"/></h2>
</%block>

Mako 中的 %namespace 等价于 Python 里的 import 语句。它允许访问其他模板文件的所有 rendering 函数和元数据
<%namespace file="functions.html" import="*"/>

<%inherit file="base.html"/>

处理多行注释:
<%doc>
    these are comments
    more comments
</%doc>

该标签使得 Mako 的词法器对模板指令的常规解析动作停止,并以纯文本的形式返回其整个内容部分
<%text filter="h">
heres some fake mako ${syntax}
<%def name="x()">${x}</%def>
</%text>

有时你想中途停止执行一个模板或者 <%def> 方法,只返回已经收集到的文本信息,可以通过在 Python 代码块中使用 return 语句来完成

% if not len(records):
    No records found.
    <% return %>
% endif

文件template

为提高性能,从文件中加载的 Template, 可以将它产生的模块的源代码以普通 python 模块文件的形式(.py),

缓存到文件系统中。只要加一个参数 module_directory 即可做到这一点:

from mako.template import Template

mytemplate = Template(filename='/docs/mytmpl.txt', module_directory='/tmp/mako_modules')
print mytemplate.render()

当上述代码被 render 的时候,会创建文件 /tmp/mako_modules/docs/mytmpl.txt.py.

下一次 Template 对象被用同样参数调用的时候,就会直接重用该模块文件。

文件TemplateLookup

#有一个对 header.txt 文件的包含引用。而从何处去查找 header.txt, 则由 TemplateLookup 指明,是 "/docs" 目录
from mako.template import Template
from mako.lookup import TemplateLookup

mylookup = TemplateLookup(directories=['/docs'])
mytemplate = Template("""<%include file="header.txt"/> hello world!""", lookup=mylookup)


--------------

#可以直接通过 TemplateLookup 来获取模板对象,利用 TemplateLookup 的 get_template 方法,
#并传递模板的 URI 作为参数
mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace')
mytemplate = mylookup.get_template("foo.txt")
print mytemplate.render()

-------------
参数
mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace', , collection_size=500)
TemplateLookup 同时也会在内存中缓存一组模板,所以并不是每一次请求都会导致模板的重新编译和模块重新加载。默认 TemplateLookup 的大小没有限制,但你可以通过 collection_size 参数来限制它
以上的 lookup 会持续加载模板到内存中,直到达到 500 的时候,它就会清除掉一定比例的模板缓存项,根据“最近最少访问”原则

另一个 TemplateLookup 相关的标志是  filesystem_checks. 默认为 True,
每一次 get_template() 方法返回模板后,原始的模板文件的 revision time 会和上次加载模板的时间做对比,
如果文件更新,则会加载其内容,并重新编译该模板。
在生产环境下,设置 filesystem_checks 为 False 可以带来一定的性能提升(和具体的文件系统有关)

自己创建context

from mako.template import Template
from mako.runtime import Context
from StringIO import StringIO

mytemplate = Template("hello, ${name}!")
buf = StringIO()
ctx = Context(buf, name="jack")
mytemplate.render_context(ctx)
print buf.getvalue()

其他

1.解决mako中文乱码问题

TemplateLookup(... , output_encoding='utf-8', ...)
Template(..., input_encoding='utf-8')
又在mako的模板文件的首行添加
## -*- encoding:utf8 -*-

web.py 模板

 python  web.py 模板已关闭评论
10月 242016
 

关于web.py中模板使用的文章,分享下:

在 Python 中写 HTML 不是聪明的选择,相反在 HTML 中写 Python 则有趣的多。幸运的是,web.py 让这件事情做得简单而又漂亮。

创建模板

这里,我们先在项目中新建一个目录templates集中存放模板文件,便于管理。然后在templates下新建一个index.html文件,在新文件中写入如下代码:

$def with (name) <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml”> <head> <meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ /> <title>Template</title> </head> <body> Hi, $name </body> </html>

这是一个最简单的html页面代码。

使用模板

然后在修改使用这个模板的类,比如说我们在main.py模块中的新写一个index类,入下:

class index: def GET(self): render=web.template.render(“templates”) return render.index(“Lisa”)

同时修改urls为:

urls = (“/”, “index”)

这样,网站默认调用index类,进而使用index.html模板,打开浏览器查看结果,页面就会打印出Hello, Lisa的字样。

除此之外还有两种使用模板的方法:

  • 使用frender直接指定模板文件,GET函数最后两行改为:

    render=web.template.frender(“templates/index.html”) return render(“Lisa”)
  • 直接在代码里写出模板文件,GET最后两行改为:

    template = “$def with (name)\nHello $name”
      render = web.template.Template(template) return render(“Lisa”)

模板含义

解释一下这个模板的含义:

在index.html第一行$def with (name)表示本模板接受一个名为name的参数,也就是对应index类中return render.index(“Lisa”)中的Lisa。而render=web.template.render(“templates”)表示创建一个模板对象,模板是存放于templates目录下,然后就可以用所创建的 render 对象来访问相应的模板

比如templates目录下的index.html就是用render.index来表示(实际上是匹配寻找index.*文件,第一个匹配的就认为是所对应的模板文件),如果templates下还有个a目录,a目录下有个pagea.html,那么访问这个pagea模板就要用render.a.pagea的形式了。

页面参数

页面接收的参数可以多于一个,也可以没有,如果不需要参数,则就不需要$def with (name)这样的代码,删除掉这一句,同时修改模板中对name变量的引用,修改index类最后一句为return render.index()就可以了。

如果有参数,那么模板的第一行代码就必须是这个$def with (…),可以多于一个参数,比如是这样$def with (gname, fname)。模板下面的那行字改为Hi, $gname $fname。同时Index类GET返回的时候赋予对应两个参数return render.index(“Lisa”,”Hayes”)。这样,页面最后显示的是打印出Hi, Lisa Hayes的字样。

另外,模板接受的这个参数也可以是一个元组,比如像下面这样:

return render.index((“Lisa”,”Hayes”))

在模板中可以如下以元组方式访问参数数据:

Hi, $name[0] $name[1]

模板语法

模板语法与python语法基本一致,主要差别可以从上面的代码中看到,要使用到$符号表明这不是文本而是模板代码。也就是每当用到程序代码、对象的时候就必须用$来与html代码和页面显示文本相区别。

对象赋值

向对象赋值时需要在$与对象名之间留空格,如为一个名为vara的字符串对象赋值apple的代码为$vara = “apple”。

另外,对象赋值语句必须独占一行,前面或后面有其他代码则会程序出错。

对象引用

引用对象的时候直接使用$+对象名的形式,如$vara。

另外引用对象时还可以用{}或()将对象进行明确的分组,如$(vara)s就会表示apples,如果没有括号,程序则会把$varas作为一个整体,也就变成对varas对象的引用而发生错误。

另如果向如下定义两个数字型对象:

$varb = 1 $varc = 2

然后希望计算两个值的和,如果用$varb+$varc的形式,页面上只会得到1+2而不是3,这时也就需要把两个对象放在括号里,如$(varb+varc)的形式才能得到正确答案3。

注释

模板中支持单行注释,以$#符号开始到行末都是注释内容。

$#This is comment

注释前面可以有其他内容,但是不可以有赋值代码

如下代码是正确的:

Hi $#This is comment

但下面的则会出错:

$ vara = “apple” $#This is comment

打印$符号

由于$符号在模板中有特殊用途,所以在页面上输出$时需要进行转义操作,用连续两个$表示在页面上输出一个$符号。

Can you lend me $$50?

控制代码(循环、条件判断)

模板中支持for、while、if、elif、else,用法与在python一致,只是控制代码行要以$开始(包括break和continue命令),$开始的代码行中对象不需要在前面再加$符号,同时要注意缩进规则,如:

for 循环:

$def with (toUser,fromUser,createTime,articleCnt,articles) <xml> <ToUserName><![CDATA[$toUser]]></ToUserName> <FromUserName><![CDATA[$fromUser]]></FromUserName> <CreateTime>$createTime</CreateTime> <MsgType><![CDATA[news]]></MsgType> <ArticleCount>$articleCnt</ArticleCount> <Articles> $for a in articles: <item> <Title><![CDATA[$a['title']]]></Title> <Description><![CDATA[$a['desc']]]></Description> <PicUrl><![CDATA[$a['picUrl']]]></PicUrl> <Url><![CDATA[$a['url']]]></Url> </item> </Articles> </xml>

if else判断:

$if times > max:
    Stop! In the name of love. $else:
    Keep on, you can do it.

在for循环中,有一组内置的变量可以使用,非常方便,分别如下所示:

  • loop.index: 循环次数计数 (1-开始)
  • loop.index0: 循环次数计数(0-开始)
  • loop.first: 如果是第一次循环则为True
  • loop.last: 如果是最后一次循环则为True
  • loop.odd: 如果是第奇数次循环则为True
  • loop.even: 如果是第偶数次循环则为True
  • loop.parity: 如果循环次数为奇数值为“odd” ,反之为 “even”
  • loop.parent: 本循环的外层循环对象
$for a in ["a", "b", "c", "d"]: $loop.index,$loop.index0,$loop.first,$loop.last,$loop.odd,$loop.even,$loop.parity<br/>

将在页面上打印出:

1,0,True,False,True,False,odd 2,1,False,False,False,True,even 3,2,False,False,True,False,odd 4,3,False,True,False,True,even

函数-$def

函数定义也是与在python中类似,用def,只是也要在前面加$,代码也要注意$的使用和缩进:

$def hello(name=”"):
Hello $name!

函数调用也是用$加函数名的形式:

$hello(“Lisa”)

当然,定义函数时也可以与html代码混编:

$def hello(name=”"):
<strong/>Hello $name!</strong>

但是调用的时候需要在函数名前用$:前缀,否则html代码将以plain text形式打印到页面上。

$:hello(“Lisa”)

输出程序代码-$code块

如果想在模板里输入写一段python代码而又不想被$所烦恼,那么可以用到$code块。

页面上输出一段代码而不希望被系统理解为模板程序代码,就需要用到$code命令,比如在模板文件中写入下面一段:

$code:
    x=10 def print_num(num): return “num is %d” % num

然后再加上下面代码:

$print_num(x)
<br/> $x

这里就用在$code块中定义的print_num函数以x变量为参数在页面上输出一行:

num is 10

然后下一行直接引用x变量,直接在页面上输出数字10。

$var

$var命令可以在模板中定义变量,在其他地方引用此模板对象的时候可以访问此定义的变量。

比如我们可以在index.html中添加如下一行:

$var vara: this is vara

表示定义了一个名为vara的变量,变量值是字符串this is vara。

把index的GET函数改为:

def GET(self): render=web.template.render(“templates”) return render.index(“Lisa”, “Hayes”).vara

那么结果显示在页面上的就是this is vara这句话。

要注意一点的是,这种变量是字符串,即便如下定义变量:

$var vara: 0

Vara也并不是数字0,

如果把GET函数最后改成:

return render.index(“Lisa”, “Hayes”).vara+1

会导致程序出错。如果希望得到期望中的结果1,则需要如下形式代码:

return int(render.index(“Lisa”, “Hayes”).vara)+1

builtins and globals

在模板中,用户可以直接使用python的内建函数和变量,写函数变量包括range, min, max 以及 True 和 False等。 除此之外,如果希望在模板中使用其他的非内建功能,就需要一点特殊操作。要在创建render的时候显式指定所需要的功能函数。

import web import markdown

globals = {‘markdown’: markdown.markdown}
render =web.template.render(‘templates’, globals=globals)

这样,在模板中就可以用$markdown来引用markdown.markdown了。

同样,也可以用这种办法来禁用builtins

# disable all builtins render = web.template.render(‘templates’, builtins={})

模板复用

当多个页面有着相同的结构框架的时候,为每一个页面单独维护一个模板就显得比较麻烦,web.py提供了一种简易的解决方法。

这时候就要用到创建render时使用base参数:

render=web.template.render(“templates”,base=”layout”) return render.index(“Lisa”, “Hayes”)

这个layout表示要以templates下的layout.html模板为通用模板框架。

因此我们还要在templates目录下新建一个layout.html文件,写下如下代码:

$def with (content) <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml”> <head> <meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ /> <title>Layout</title> </head> <body> $:content </body> </html>

可以看到,这个模板文件必须是有一个参数content。

然后修改index.html,只保留如下代码,其他删掉:

$def with(gname, fname)
    Hi, $(gname) $(fname)

运行程序,页面上打印Hi, Lisa Hayes,查看代码会发现最终代码就是index.html和layout.html合并在一起的结果,index.html中的内容被嵌入到layout.html中的$:content处。

在layout.html模板中还可以引用index.html中定义的var变量,这为程序带来了更多的灵活性,比如我们希望在不同的页面在使用同一个layout模板的时候能有不同的title,可以在使用layout的模板中定义如下一个var变量:

$var title:This is index.html

然后在layout.html中的title处修改为:

<title>$content.title</title>

这样,访问index.html时显示在浏览器上的title就是This is index.html,而不是原来的Layout了。

在模板中使用python代码模块

在默认状态下,在模板中是不能直接调用其他python代码模块文件中的程序的,必须做一些额外的操作。
首先,我们新建一个模块,叫module1.py,在里面写一个函数:

def hello_from_m1(name="):
    return “hello %s, this is module1″ % name

在main.py里导入module1:

import module1

并且修改GET函数中创建render的代码为:

def GET(self): render=web.template.render(“templates”,base=”layout”,globals={“m1″:module1}) return render.index(“Lisa”)

globals参数中传递的是一个字典,key以字符串表示模块在模板中使用时的名称,value部分就是这个要在模块中使用的模块或对象的真实名称了。

最后在要使用此模块的模板中就可以用$m1来引用此模块了。比如在index.html中添加下面一行代码:

$m1.hello_from_m1(gname)

就会调用module1中的hello_from_m1函数,在页面上打印出:

hello Lisa, this is module1

在web.py模板中使用jQuery

在jQuery中$也是一个关键字,这样的话如果在模板中使用jQuery就会冲突,这时候只需要用$做一下转义就可以了,比如:

<script type=”text/javascript”> $$(document).ready(function() {
    alert(“It works.”);
}); </script>

参考


原文链接:http://www.jianshu.com/p/7817641efe8d

10月 122013
 

I.总览                                          

    Cacti和Nagios的监控体系可以说是使用广泛而且支持丰富的国内外的运维人员都需要掌握的一套监控体系,这套体系的好处在于使用Cacti的强大画图和自定义画图能力,以及Nagios的可控报警。但是网上的大部分内容都是如何安装,在安装成功如何使用的方面介绍的很少,而真正开始用之后,为了工作需要就需要不断地去Cacti官网查看使用文档,或者论坛去翻别人的帖子,十分麻烦。于是我决定写一篇使用方面的手册,以让大家真正会用这套系统。

II.Cacti的使用                                  

    Cacti的常用服务器的画图大部分都是使用模板的形式做的,而Cacti安装好之后本身自带了一部分模板,这些模板虽然可用,但是支持的项目太少,于是我们要寻求更多的模板以及更优化的内容。

    Cacti的官方的模板库:http://docs.cacti.net/templates  

 

1:cacti模板的一般加载方法:

    一个Cacti的模板一般有两部分组成。一部分是xml模板文件,另一部分是xml的数据收集文件,虽然这两种文件都是xml格式的,但是你可以很显而易见的就能分出它们的不同。因为它们的文件大小一点都不相似。

    举个简单的例子:





这个是一个windows的监控模板,我们可以简单的根据文件的大小来看。

    *  大小大于10KB的,那就是xml模板文件。

    *  大小小于10KB的,那就是xml数据收集文件。


Xml模板文件是要在cacti的Web页面的Console选项卡内Import Templates项进行添加:

    而xml数据收集文件,则是要放在Linux上Cacti的安装目录的cacti/resource/snmp_queries中:



    只要将两种类型的xml正确的导入/放入到应有的位置,那么模板就添加成功了。 

 

 

2:如何在Cacti上添加一个新主机并监控相关的内容:(以添加Linux主机为例)

1.创建画图

a. 在Cacti的Web页面Console->Import Templates导入响应的xml模板文件。

b. 在Linux上cacti/resource/snmp_queries中放入模板相关的xml数据收集文件。并确保属主和属组均为cacti。

c. 点击Console->Devices,打开设备管理页面。

d. 点击右上角的add,添加一个新的机器

e. 当主机的信息填好之后,点击Create

f. 此时你的页面左上角应该显示:Save Successful,并且已经显示出了主机信息和SNMP信息,如果SNMP信息显示 SNMP error,请查看最后的问题综述。

g. 这时我们就可以添加相应的监控项了,在页面最下方的Associated Graph Templates中添加图形模板,在Associated Data Queries中添加数据模板。

h. 添加好相应的模板之后点击Save。此时左上角会出现Save Successful.

i. 点击右上角的Create Graphs for this Host,来为刚才通过模板所获得到的数据进行画图。

j. 选中需要画图的项,其中依然分为两部分:

    通过Graph Templates中的内容都需要选中,而Data Query获取的内容比较详细,所以可以按需选择。

k. 选择好需要画图的项目后,点击右下角的Create,左上角会出现被创建出来的画图项。

2.在Graphs界面显示新添加主机。

a. 在Cacti Web界面Graph Trees中,选择相应的列(或者系统默认的Default Tree)。

b. 进去Tree之后,点击右上角的Add,添加一个新的显示项。

c. 在Tree Item Type中选择Host,然后在下面的Host中选择我们刚才创建的主机。点击Create。

d. 此时,再进入Graphs界面,就可以看到在Default Tree下加入了我们新创建的主机。

 

 

III.Cacti的常用模板                         

 

1.Windows常用模板

    Windows一般所需要监控的基本内容有:

    1.    CPU Use

    2.    Memory Use

    3.    Disk Size

    4.    Interface Traffic

    为了解决基本的监控项,我们需要以下模板。

    A.    Cacti_SNMP_Informant_Standard_Metrics_v12.zip

    B.    Cacti_host_template_ucdnet_snmp_host.gz

    我们还需要在Windows主机上安装一个软件,以确保SNMP能发送更多的信息为我们提供数据采集:informant-std-16.exe

    使用A模板来监控Windows的CPU项目

    使用B模板来监控网络,硬盘,内存。 

    最终,添加完相关模板,在创建Windows主机之后,在Devices->Your Windows host ->页面下方正确添加的各种Templates如下:



    由于Windows模板下都是Data Queries。所以请确保添加完相关的Data Queries之后,所有项目的Status下应该都是Success以及是能看到很多Items以及Rows的。这说明数据正确采集,如果没有,请移步最后问题综述的问题4。

    最后添加完并且画图的监控结果:

 

 

2.Linux常用模板

    Linux与Windows监控的内容基本相同:

    1.    CPU Use

    2.    Load Average

    3.    Memory Usage

    4.    Swap Usage

    5.    Disk I/O

    6.    Disk Size

    7.    Interface Traffic

    为了解决Linux监控内容,我们使用以下模板:

    A.    Cacti_host_template_ucdnet_snmp_host.gz

    B.    Cacti_graph_template_ucdnet_-_memory/swap_usage_linux.xml

    C.    Data_query_snmp_-_get_disk_io

    最终,添加完相关模板,在创建Linux主机之后,在Devices->Your Linux host ->页面下方正确添加的各种Templates如下:



    在所有的Linux监控添加后的内容如下:

 

3.Switch && Router的相关模板

    由于市面上Switch和Router的型号众多,而不同的型号可能就需要不同的模板,不能像Windows和Linux一样进行统一,所以当你需要监控Switch和Router的时候,请Google响应的型号的模板,或者在Cacti官方的模板库中进行查找。查找之后添加的过程都大同小异,这里不再赘述。

 

 

IV:自定义脚本的添加以及监控                 

    很多时候,我们需要为我们独有的环境去指定监控内容,那么如何制定呢?就可以通过自己写脚本的方式进行收集数据。这里我用一个监控QQ在线人数的例子来举例。

准备工作:

    1.我们需要一个脚本,脚本的语言随意,只要在Linux的机器上能够使用运行并且有返回内容。比如我们即将使用的脚本:


 
  1. #!/bin/bash 
  2. echo "QQ_Now:`curl im.qq.com/online.shtml | grep qqdata | cut -d":" -f 3 | cut -d">" -f 2 | cut -d"<" -f 1`" 

    此脚本运行之后输出内容为:

    这个里面只有最后一行是有用的,其他的为curl的抓取信息。

    2.我们的脚本要放在一个确保Cacti用户可访问的位置。常用的地方是:cacti/scripts/*中,那么当脚本准备停当之后,就开始我们的监控工作。

 

 

1.创建数据输入方式

    1.    在Console–>点击Data Input Methods

    2.    点击右上角的Add,添加一个新的数据获取方式



    3.    点击Create,出现新的项目

    4.    新的项目包括Input Fields和Output Fields,即输入内容和输出内容,输入内容其实就是向脚本传递函数,我们这个脚本不需要传递什么参数进去,于是没有,只有Output Fields。

    5.    在Output Fields上点击Add,添加新的输出内容。

    6.    在Field[Output]中输入我们脚本的输出项:这里我填写“QQ_Now”

    7.    在Friendly Name中输入解释输出项的内容,内容随意。

    8.    勾选Update RRD File后,点击Create

    9.    然后查看我们整个的数据获取方式信息,点击Save,左上角应出现“Save Successful”

2.创建数据源

    1.    在Console->点击Data Sources,进入数据源界面

    2.    点击右上角的Add,添加新的数据源

    3.    确保Data Template和Host均为None。直接点击Create

    4.    在新出现的信息面板中输入相关内容

    5.    点击Create,此时左上角会出现Save Successful

    6.    注意系统自动给生成的RRD文件路径,确保里面不会出现连续两个反斜线的路径信息。如果出现,请手动修改为一个反斜线。如:<path_rra>/1194.rrd

    7.    点击Save,看到Save Successful,则数据源创建成功。 

3.创建图像

    1.    选择Console–> Graph Management,进入图像管理

    2.    点击右上角的Add,添加一个新的图像

    3.    选择Graph Template以及Host均为None,然后点击Create

    4.    Title中输入图像的名字,其他保持不变。并点击Create

    5.    然后你会看到多出的Graph Items,以及中间有一个看不到图的红叉,因为这个图我们还没有定义。

    6.    在Graph Items中点击Add,添加画图规则。



    7.    添加完画图内容之后,点击Create/Save,返回之前的页面,接下来还要添加数据的展示内容。

    8.    再次点击Graph Items中的Add,这次添加的是数据的展示,展示当前值。

 

    9.    设置好后点击Create创建这个项目,然后按照这个方法,分别创建最大值,最小值,平均值的展示内容。




    10.   添加好后内容如图。

4.将自定义好的图形,加入到Graphs面板

    1.    在Cacti Web界面Graph Trees中,选择相应的列(或者系统默认的Default Tree)。

    2.    进去Tree之后,点击右上角的Add,添加一个新的显示项。

    3.    在Tree Item Type中选择Graph,然后在下面的Graph中选择我们刚才创建的图像。点击Create。

    4.    此时,再进入Graphs界面,就可以看到在Default Tree下已经出现了我们新创建的图像。

 

V.Cacti问题 Q & A                           

1.填完Drivers信息之后显示红色的SNMP error

    这是由于被监控机的SNMP设置问题,没有允许我们监控机进行监控,或者Community不匹配导致的。

    Linux可以在/etc/snmp/snmpd.conf中修改/增加发送snmp的机器,以及community。

    Windows可以在Snmp服务中增加允许发送snmp的机器,以及community。 

2.添加完图之后,等待了无数时间图依然无法绘制,反馈给我们一个红色的X。

    首先,如果你是用添加的模板创建的图,那么显示不了的话,很有可能是由于模板太老,或者模板不正确导致的。可以考虑更新作者的最新模板以重新画图。当然,如果图像的确画不出来,那么我们可以打开画图的Debug日志的方式进行排错。

    进入Graph Management,在Host中选择我们画不出图的那个Host,然后点Go,这样就在下面列出了所有在这个Host中的图像列表,点击那个无法画图的列表。这就进入了我们选定主机的相关图像的设置界面,我们应该可以看到这个界面下方依然有一个红X,证明我们无法画图,所以点击右上角的“Turn on Graph Debug Mode.”来打开Debug日志,这时候,就可以看到页面下方多出了"RRD Tool Command:"的列表,里面详细的描述了RRD工具是如何为我们画图的,这都不是关键,关键是最后的RRD Tool Says:比如

    这里面是RRD Tool 告诉的我们为什么它无法画图,我们可以看到我当前例子的没有画图的原因是316.rrd这个文件不存在,说明在创建的时候rrd没有正确的创建出这个文件,这就有可能是所用的模板有问题了。

    在这里,这是一个很好的查看为什么没有画出图的地方,没有画出的图RRD Tool会一一的告诉我们,我们只需要根据它说的来修正,直到RRD Tool Says: OK

3.图什么的都有,但是数据都是N/A,这是要闹哪样?

    这个的解决办法其实跟无法画图的解决一样,就是我们去看数据的Debug日志。

    进入Data Sources,在Host中选择没有数据的Host,然后在下面的列表中选择没有数据的那个图。进入数据设置界面,然后点击右上角的“Turn on Data Source Debug mode”,然后去分析它的报错。

4.在给主机添加Data Query的监控项的时候发现里面没有获取到数据。

    这时候,如果它获取不到数据,我们就无法给它画图。因为在给它创建的图的界面上显示没有内容。

    这时候可以直接点击上图中的Debugging下的相关内容,直接打开Debug查看状态。

    这时就可以看到反馈出得信息,比如上图,发现SNMP无法获取数据。当然也有其他的,比如MIB文件不存在。只要你仔细看它反馈出来的问题,知道问题的根源,就一定能解决。当解决了数据获取之后,可以直接点击右边的绿色的小圆圈,就刷新了数据的获取状态。

5.关于cacti下文件的权限问题。

    Cacti目录中的内容权限并不统一,而且权限要求的也很少,并不像其他的比如Nagios要求的那么多。我们可以简单的保持整个Cacti目录的属主和属组都是Cacti即可。但是有两个特殊的例外:

    第一个是cacti/rra目录,整个目录里的内容是RRD的画图文件自动在里面生成的。而生成之后里面文件的属主和属组到底是谁,取决最终是由哪个用户来创建的,而这个就是在Cacti的那个crontab里控制,如果我们使用的是root用户添加的crontab,那么这个rra目录中的内容属主和属组都是root。同理,如果我们的crontab是在cacti中设置的,那么rra目录中的内容属主和属组都是cacti。

    第二个目录是cacti/scripts目录,这里面存的大部分都是我们自定义的脚本,一定要确保里面的脚本是cacti用户可执行的。最好的检测方法就是su到cacti用户中,进入这个目录,手动运行一下脚本,查看脚本是否成功执行

 

转自:http://foreveryan.blog.51cto.com/3508502/775558