<?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>CTPAHHuK.RU</title>
	<atom:link href="http://ctpahhuk.ru/feed" rel="self" type="application/rss+xml" />
	<link>http://ctpahhuk.ru</link>
	<description></description>
	<lastBuildDate>Sat, 08 Oct 2011 20:52:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.3</generator>
		<item>
		<title>Stive Jobs</title>
		<link>http://ctpahhuk.ru/archives/234</link>
		<comments>http://ctpahhuk.ru/archives/234#comments</comments>
		<pubDate>Sat, 08 Oct 2011 20:52:58 +0000</pubDate>
		<dc:creator>CTPAHHuK</dc:creator>
				<category><![CDATA[Мысли вслух]]></category>

		<guid isPermaLink="false">http://ctpahhuk.ru/?p=234</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.apple.com/ru/stevejobs" target="_blank"><img class="alignleft" src="http://images.apple.com/euro/home/images/t_title.png" alt="Steve Jobs 1955-2011" width="205" height="75" /></a><br />
<a href="http://www.apple.com/ru/stevejobs" target="_blank"><img class="roundedbottomright alignleft" src="http://images.apple.com/euro/home/images/t_hero.png" alt="" width="706" height="644" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://ctpahhuk.ru/archives/234/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>#8</title>
		<link>http://ctpahhuk.ru/archives/231</link>
		<comments>http://ctpahhuk.ru/archives/231#comments</comments>
		<pubDate>Fri, 01 Apr 2011 15:47:53 +0000</pubDate>
		<dc:creator>CTPAHHuK</dc:creator>
				<category><![CDATA[no comments]]></category>

		<guid isPermaLink="false">http://ctpahhuk.ru/?p=231</guid>
		<description><![CDATA[мля&#8230;. у меня в сидироме живут хомячки-дискогрызы, судя по звукам]]></description>
			<content:encoded><![CDATA[<p>мля&#8230;. у меня в сидироме живут хомячки-дискогрызы, судя по звукам</p>
]]></content:encoded>
			<wfw:commentRss>http://ctpahhuk.ru/archives/231/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Суровая проверка валидности e-mail на PHP</title>
		<link>http://ctpahhuk.ru/archives/220</link>
		<comments>http://ctpahhuk.ru/archives/220#comments</comments>
		<pubDate>Wed, 09 Feb 2011 18:27:28 +0000</pubDate>
		<dc:creator>CTPAHHuK</dc:creator>
				<category><![CDATA[PHP скриптинг]]></category>
		<category><![CDATA[Статьи]]></category>
		<category><![CDATA[e-mail verification]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php e-mail validation]]></category>
		<category><![CDATA[YDACHA]]></category>
		<category><![CDATA[проверка e-mail на php]]></category>

		<guid isPermaLink="false">http://ctpahhuk.ru/?p=220</guid>
		<description><![CDATA[Возникла задача проверять валидность вводимого в форме e-mail адреса. Поиск выдал кучу ссылок на проверку валидности написания самого адреса. Кто как не извращается, хотя для этого есть встроенная функция. Мне же, требовалась более суровая проверка, ну хотябы на существование релея. А раз уж и до релея добрались, то почему бы не проверить и существование на [...]]]></description>
			<content:encoded><![CDATA[<p>Возникла задача проверять валидность вводимого в форме e-mail адреса.</p>
<p>Поиск выдал кучу ссылок на проверку валидности написания самого адреса. Кто как не извращается, хотя для этого есть встроенная функция.<br />
Мне же, требовалась более суровая проверка, ну хотябы на существование релея. А раз уж и до релея добрались, то почему бы не проверить и существование на нем пользователя?<br />
Понятно, что многие релеи не выдают 550 если пользователя нет, но попытка &#8211; не пытка. Даже если на левого пользователя мы получим ответ 250, мы хотябы попытались и убедились в том, что релей есть и он живой.</p>
<p><span id="more-220"></span></p>
<p>Скрипт с комментами.</p>
<p>До вызова функции необходимо определить переменную $mymxhost &#8211; именем этого хоста, скрипт будет представляться почтовому релею.</p>
<pre>&lt;?
<span style="color: #0000ff;">function</span> <span style="color: #008080;">check_email</span>(<span style="color: #800000;">$email</span>) {
  <span style="color: #0000ff;">global</span> <span style="color: #800000;">$mymxhost</span>;

  <span style="color: #999999;">/**
   * Проверяем валидность написания email.
   */</span>
  <span style="color: #0000ff;">if</span>(!<span style="color: #008080;">filter_var</span>(<span style="color: #800000;">$email</span>, <span style="color: #008080;">FILTER_VALIDATE_EMAIL</span>)) {
    <span style="color: #0000ff;">return false</span>;
  }

  <span style="color: #999999;">/**
   * Выкусываем имя хоста из email
   */</span>
  <span style="color: #008080;">preg_match</span>(<span style="color: #ff00ff;">'/^[^@]+@([a-zA-Z0-9._-]+\.[a-zA-Z]+)$/'</span>,<span style="color: #800000;">$email</span>, <span style="color: #800000;">$host</span>);

  <span style="color: #999999;">/**
   * Проверяем наличие MX записи для хоста.
   */</span>
  <span style="color: #008080;">getmxrr</span>(<span style="color: #800000;">$host</span>[<span style="color: #339966;">1</span>], &amp;<span style="color: #800000;">$mxhosts</span>);
  <span style="color: #0000ff;">if</span>(!<span style="color: #008080;">count</span>(<span style="color: #800000;">$mxhosts</span>)) {
    <span style="color: #0000ff;">return false</span>;
  }

  <span style="color: #999999;">/**
   * Парсим массив MX записей и коннектимся к хосту.
   */</span>
  <span style="color: #0000ff;">foreach</span>(<span style="color: #800000;">$mxhosts</span> <span style="color: #0000ff;">as</span> <span style="color: #800000;">$host</span>) {
    <span style="color: #0000ff;">if</span>(<span style="color: #800000;">$fp</span>=<span style="color: #008080;">pfsockopen</span>(<span style="color: #800000;">$host</span>,<span style="color: #008080;">25</span>)) {
      <span style="color: #999999;">/**
       * Читаем приглашение от хоста. Ожидаем строки "220 HELO ...." в течении 30 секунд.
       */</span>
      <span style="color: #800000;">$string</span>=<span style="color: #008080;">read_string</span>(<span style="color: #800000;">$fp</span>,<span style="color: #008080;">30</span>);
      <span style="color: #0000ff;">if</span>(<span style="color: #008080;">substr</span>(<span style="color: #800000;">$string</span>,<span style="color: #008080;">0</span>,<span style="color: #008080;">3</span>)!=<span style="color: #ff00ff;">"220"</span>) {
        <span style="color: #999999;">/**
         * Если ответа не получили или получили не приветсвие, закрываем соединение.
         */</span>
        <span style="color: #008080;">fclose</span>(<span style="color: #800000;">$fp</span>);
        <span style="color: #0000ff;">return false</span>;
      }

      <span style="color: #999999;">/**
       * Отправляем приветсвие и ждем ответа от сервера в течении 5 секунд.
       */</span>
      <span style="color: #008080;">fwrite</span>(<span style="color: #800000;">$fp</span>,<span style="color: #ff00ff;">"HELO $mymxhost\n"</span>);
      <span style="color: #800000;">$string</span>=<span style="color: #008080;">read_string</span>(<span style="color: #800000;">$fp</span>,<span style="color: #008080;">5</span>);
      <span style="color: #0000ff;">if</span>(<span style="color: #008080;">substr</span>(<span style="color: #800000;">$string</span>,<span style="color: #008080;">0</span>,<span style="color: #008080;">3</span>)!=<span style="color: #ff00ff;">"250"</span>) {
        <span style="color: #999999;">/**
         * Если ответа не получили или получили что отличное от 250, закрываем соединение.
         * Возможные причины отказа:
         * Отсутсвие PTR запси для вашего хоста
         * Отсутствие  А и/или MX записи для хоста, которым вы представляетесь ($mymxhost)
         */</span>
        <span style="color: #008080;">fclose</span>(<span style="color: #800000;">$fp</span>);
        <span style="color: #0000ff;">return false</span>;
      }

      <span style="color: #999999;">/**
       * Отправляем на сервер строку MAIL FROM: и ждем ответа от сервера в течении 5 секунд.
       */</span>
      <span style="color: #008080;">fwrite</span>(<span style="color: #800000;">$fp</span>,<span style="color: #ff00ff;">"MAIL FROM: &lt;&gt;\n"</span>);
      <span style="color: #800000;">$string</span>=<span style="color: #008080;">read_string</span>(<span style="color: #800000;">$fp</span>,<span style="color: #339966;">5</span>);
      <span style="color: #0000ff;">if</span>(<span style="color: #008080;">substr</span>(<span style="color: #800000;">$string</span>,<span style="color: #008080;">0</span>,<span style="color: #008080;">3</span>)!=<span style="color: #ff00ff;">"250"</span>) {
        <span style="color: #999999;">/**
         * Если ответа не получили или получили что отличное от 250, закрываем соединение.
         * Возможные причины отказа:
         * Сервер получатель отказывается принимать пустое поле MAIL FROM.
         * По RFC такие поля должны приниматься для обработки reverse connect, что мы и пытаемся сделать.
         */</span>
        <span style="color: #008080;">fclose</span>(<span style="color: #800000;">$fp</span>);
        <span style="color: #0000ff;">return false</span>;
      }

      <span style="color: #999999;">/**
       * Отправляем на сервер строку RCPT TO: и ждем ответа от сервера в течении 5 секунд.
       * Если получили в ответ 250 - то сервер ответил, что пользователь у него есть (хотя это не значит, что он есть на самом деле).
       */</span>
      <span style="color: #008080;">fwrite</span>($fp,<span style="color: #ff00ff;">"RCPT TO: $email\n"</span>);
      $string=<span style="color: #008080;">read_string</span>($fp,<span style="color: #008080;">5</span>);
      <span style="color: #0000ff;">if</span>(<span style="color: #008080;">substr</span>($string,<span style="color: #008080;">0</span>,<span style="color: #008080;">3</span>)!=<span style="color: #ff00ff;">"250"</span>) {
        <span style="color: #008080;">fclose</span>($fp);
        <span style="color: #0000ff;">return false</span>;
      }
      <span style="color: #0000ff;">else</span> {
        <span style="color: #008080;">fclose</span>($fp);
        <span style="color: #0000ff;">return true</span>;
      }
    }
  }
}
<pre><span style="color: #999999;">/**
* Читаем строку возврата. Если ничего не вернулось, ждем 1 секунду и читаем снова.
* Если через $timeout секунд ничего не вернулось, то возвращаем false.
*/</span>
<span style="color: #0000ff;">function</span> <span style="color: #008080;">read_string</span>(<span style="color: #800000;">$fp</span>,<span style="color: #800000;">$timeout</span>) {
  <span style="color: #800000;">$string</span>=<span style="color: #ff00ff;">""</span>;
  <span style="color: #0000ff;">for</span>(<span style="color: #800000;">$i</span>=<span style="color: #008000;">1</span>;<span style="color: #800000;">$i</span>&lt;<span style="color: #800000;">$timeout</span>;<span style="color: #800000;">$i</span>++){
    <span style="color: #800000;">$string</span>=<span style="color: #008080;">fread</span>(<span style="color: #800000;">$fp</span>, <span style="color: #008080;">128</span>);
    <span style="color: #0000ff;">if</span>(<span style="color: #800000;">$string</span>!=<span style="color: #ff00ff;">""</span>){
      <span style="color: #0000ff;">return</span> <span style="color: #800000;">$string</span>;
    }
    <span style="color: #008080;">sleep</span>(<span style="color: #008080;">1</span>);
  }
  <span style="color: #0000ff;">return false</span>;
}</pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://ctpahhuk.ru/archives/220/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Заезд на участок.</title>
		<link>http://ctpahhuk.ru/archives/207</link>
		<comments>http://ctpahhuk.ru/archives/207#comments</comments>
		<pubDate>Mon, 06 Dec 2010 11:11:21 +0000</pubDate>
		<dc:creator>CTPAHHuK</dc:creator>
				<category><![CDATA[Дачные дела]]></category>
		<category><![CDATA[YDACHA]]></category>
		<category><![CDATA[Верховье]]></category>
		<category><![CDATA[Удача]]></category>

		<guid isPermaLink="false">http://ctpahhuk.ru/?p=207</guid>
		<description><![CDATA[Желающие принять участие в самостоятельном устройстве заезда на участок, могут обращаться ко мне в личку http://www.ydacha.ru/forum/ucp.php?i=pm&#38;mode=compose&#38;u=388 за дополнительной информацией. Цена вопроса дешевле чем в ДНП. В настоящий момент заказ почти укомплектован. Необходимо еще два желающих.]]></description>
			<content:encoded><![CDATA[<p>Желающие принять участие в самостоятельном устройстве заезда на участок, могут обращаться ко мне в личку <a href="http://www.ydacha.ru/forum/ucp.php?i=pm&amp;mode=compose&amp;u=388" target="_blank">http://www.ydacha.ru/forum/ucp.php?i=pm&amp;mode=compose&amp;u=388</a> за дополнительной информацией.</p>
<p>Цена вопроса дешевле чем в ДНП. В настоящий момент заказ почти укомплектован. Необходимо еще два желающих.</p>
]]></content:encoded>
			<wfw:commentRss>http://ctpahhuk.ru/archives/207/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Удача &#8211; наша дача</title>
		<link>http://ctpahhuk.ru/archives/200</link>
		<comments>http://ctpahhuk.ru/archives/200#comments</comments>
		<pubDate>Mon, 29 Nov 2010 17:40:53 +0000</pubDate>
		<dc:creator>CTPAHHuK</dc:creator>
				<category><![CDATA[Дачные дела]]></category>
		<category><![CDATA[YDACHA]]></category>
		<category><![CDATA[Верховье]]></category>
		<category><![CDATA[Удача]]></category>

		<guid isPermaLink="false">http://ctpahhuk.ru/?p=200</guid>
		<description><![CDATA[Купили дачу у Удачи Демократичные цены, отличный сервис. Ждем весны и начнем осваивать. следим за обновлениями.]]></description>
			<content:encoded><![CDATA[<p><a title="YDACHA" href="http://www.ydacha.ru/verhovie.html" target="_blank"><img class="alignnone" title="ydacha_logo" src="http://www.ydacha.ru/forum/styles/Bl%40ck/imageset/site_logo.png" alt="" width="448" height="90" /></a></p>
<p>Купили дачу у <a href="http://www.ydacha.ru/verhovie.html" target="_blank">Удачи</a> <img src='http://ctpahhuk.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Демократичные цены, отличный сервис.</p>
<p>Ждем весны и начнем осваивать. следим за обновлениями.</p>
]]></content:encoded>
			<wfw:commentRss>http://ctpahhuk.ru/archives/200/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>#7</title>
		<link>http://ctpahhuk.ru/archives/196</link>
		<comments>http://ctpahhuk.ru/archives/196#comments</comments>
		<pubDate>Thu, 29 Jul 2010 07:29:29 +0000</pubDate>
		<dc:creator>CTPAHHuK</dc:creator>
				<category><![CDATA[no comments]]></category>

		<guid isPermaLink="false">http://ctpahhuk.ru/?p=196</guid>
		<description><![CDATA[Реклама в метро. Большой плакат пиво Kozel смешай светлого с темным. По верх него, наклеен стикер, наверное свидетелей Иеговы &#8211; &#171;Господь скоро придет. Не пей!&#187;. Рядом маркером подписано &#171;без него&#187;.]]></description>
			<content:encoded><![CDATA[<p>Реклама в метро. Большой плакат пиво Kozel смешай светлого с темным. По верх него, наклеен стикер, наверное свидетелей Иеговы &#8211; &laquo;Господь скоро придет. Не пей!&raquo;.</p>
<p>Рядом маркером подписано &laquo;без него&raquo;.</p>
]]></content:encoded>
			<wfw:commentRss>http://ctpahhuk.ru/archives/196/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>#6</title>
		<link>http://ctpahhuk.ru/archives/189</link>
		<comments>http://ctpahhuk.ru/archives/189#comments</comments>
		<pubDate>Tue, 02 Feb 2010 08:21:28 +0000</pubDate>
		<dc:creator>CTPAHHuK</dc:creator>
				<category><![CDATA[no comments]]></category>
		<category><![CDATA[Mac OS]]></category>
		<category><![CDATA[Хакинтош]]></category>

		<guid isPermaLink="false">http://ctpahhuk.ru/?p=189</guid>
		<description><![CDATA[Только русские мучаются устанавливая Mac OS на РС и с гордостью работают в Windows на Mac.]]></description>
			<content:encoded><![CDATA[<p>Только русские мучаются устанавливая Mac OS на РС и с гордостью работают в Windows на Mac.</p>
]]></content:encoded>
			<wfw:commentRss>http://ctpahhuk.ru/archives/189/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Создание отказоустойчивого кластера для биллинговой системы UTM5 на базе FreeBSD</title>
		<link>http://ctpahhuk.ru/archives/175</link>
		<comments>http://ctpahhuk.ru/archives/175#comments</comments>
		<pubDate>Tue, 08 Dec 2009 11:44:49 +0000</pubDate>
		<dc:creator>CTPAHHuK</dc:creator>
				<category><![CDATA[Биллинг]]></category>
		<category><![CDATA[Статьи]]></category>
		<category><![CDATA[arpwatch]]></category>
		<category><![CDATA[CARP]]></category>
		<category><![CDATA[cricket]]></category>
		<category><![CDATA[devd]]></category>
		<category><![CDATA[devd.conf]]></category>
		<category><![CDATA[em0]]></category>
		<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[gprs]]></category>
		<category><![CDATA[MRTG]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Nagios]]></category>
		<category><![CDATA[NetUP]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[RRD]]></category>
		<category><![CDATA[RRDTool]]></category>
		<category><![CDATA[sms]]></category>
		<category><![CDATA[SNMP]]></category>
		<category><![CDATA[UTM5]]></category>
		<category><![CDATA[кластер]]></category>
		<category><![CDATA[репликация]]></category>

		<guid isPermaLink="false">http://xn--80aqgkapgi.net/?p=175</guid>
		<description><![CDATA[В статье рассматривается создание отказоустойчивого кластера для работы с биллинговой системой NetUP UTM на базе двух физических серверов. В качестве операционной системы используется FreeBSD. База данных mysql. Создание отказоустойчивого кластера для биллинговой системы на базе Gentoo Linux подробно рассматривается в соответствующей статье на сайте компании NetUP.[1] Поскольку у меня объем трафика довольно большой, для избежания [...]]]></description>
			<content:encoded><![CDATA[<p>В статье рассматривается создание отказоустойчивого кластера для работы с биллинговой системой NetUP UTM на базе двух физических серверов. В качестве операционной системы используется FreeBSD. База данных mysql. Создание отказоустойчивого кластера для биллинговой системы на базе Gentoo Linux подробно рассматривается в соответствующей статье на сайте компании NetUP.<a href="https://secure.netup.biz/articles.php?n=13" target="_blank">[1]</a></p>
<p><span id="more-175"></span></p>
<div id="attachment_176" class="wp-caption alignnone" style="width: 568px"><a href="http://xn--80aqgkapgi.net/wp-content/uploads/2009/12/utm5_cluster.gif"><img class="size-full wp-image-176" title="utm5_cluster" src="http://xn--80aqgkapgi.net/wp-content/uploads/2009/12/utm5_cluster.gif" alt="Рисунок 1. Схема кластера." width="558" height="726" /></a><p class="wp-caption-text">Рисунок 1. Схема кластера.</p></div>
<p>Поскольку у меня объем трафика довольно большой, для избежания потерь данных о трафике, NetFlow поток передается и принимается в отдельной подсети и выделенных под это отдельных физических интерфейсах. Физические интерфейсы em0,em1 и em2 имеют общие IP-адреса по которым доступен кластер. В случае выходя из строя сервера, либо проблем на любом из этих трех интерфейсах, резервный сервер забирает на себя функции мастера и соответствующие IP-адреса назначаются его интерфейсам.</p>
<p>Данная система построена на базе протокола CARP (Common Address Redundancy Protocol — протокол избыточности общего адреса)<a href="http://www.freebsd.org/cgi/man.cgi?query=carp&amp;apropos=0&amp;sektion=0&amp;manpath=FreeBSD+7.1-RELEASE&amp;format=html" target="_blank">[2]</a></p>
<p>Каждый сервер укомплектован четырьмя сетевыми интерфейсами стандарта Gigabit Ethernet.<br />
Интерфейсы em0 поддерживают работу службы авторизации на базе протокола RADIUS и имеют общий IP 1.2.3.243 (сервер utm1 IP-1.2.3.244, utm2 IP-1.2.3.245)<br />
Интерфейсы em1 предназначены для сбора статистики по протоколу NetFlow и имеют общий IP 172.31.31.2 (сервер utm1 IP-172.31.31.3, utm2 IP-172.31.31.4)<br />
Интерфейсы em2 предназначены для доступа к ядру из интерфейсов администратора, дилера и кассира, а также сервиса http для доступа клиентов к «Личному кабинету».<br />
Интерфейсы имеют общий IP 1.2.3.99 (сервер utm1 IP-1.2.3.108, utm2 IP-1.2.3.109). Интерфейсы em3 на обоих серверах соединяются кроссоверным патчкордом и используются для репликации БД.<br />
В настройках UTM соответствующие сервисы настроены на работу на CARP IP. MySQL запущен только на IP интерфейса em3<br />
Настройку кластера начнем с включения поддержки CARP ядром ОС. Поскольку CARP портирован во FreeBSD из OpenBSD, ключ carpdev не поддерживается. Это влечет за собой то, что CARP IP-адресс и IP-адреса интерфейсов для данного IP должны находиться в одной подсети. Для включения CARP, необходимо добавить в конфигурационный файл строку</p>
<p>device carp</p>
<p>Но, прежде чем пересобрать ядро, рекомендую пропатчить файл ip_carp.c Нужно это для того, чтобы можно было перехватывать события, происходящие с интерфейсами CARP при помощи devd. Если вы не планируете управлять кластером по событиям CARP, а запускать проверку по cron, патч можно не ставить.</p>
<pre><span style="color: #0000ff;">sys/netinet/ip_carp.c.orig	2008-08-18 02:49:50.000000000 +0400
+++ sys/netinet/ip_carp.c	2008-08-18 02:16:50.000000000 +0400
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -2108,6 +2109,7 @@
static void
carp_set_state(struct carp_softc *sc, int state)

+	char vhid_buf[15], *dev_msg;

if (sc-&gt;sc_carpdev)
CARP_SCLOCK_ASSERT(sc);
@@ -2119,15 +2121,20 @@
switch (state) {
case BACKUP:
SC2IFP(sc)-&gt;if_link_state = LINK_STATE_DOWN;
+		dev_msg = "CARP_SLAVE";
break;
case MASTER:
SC2IFP(sc)-&gt;if_link_state = LINK_STATE_UP;
+		dev_msg = "CARP_MASTER";
break;
default:
SC2IFP(sc)-&gt;if_link_state = LINK_STATE_UNKNOWN;
+		dev_msg = "CARP_UNKNOWN";
break;
}
rt_ifmsg(SC2IFP(sc));
+	snprintf(vhid_buf, sizeof(vhid_buf), "vhid=%d", sc-&gt;sc_vhid);
+	devctl_notify("IFNET", SC2IFP(sc)-&gt;if_xname, dev_msg, vhid_buf);
}</span></pre>
<p>После применения патча и добавления в ядро поддержки CARP, необходимо пересобрать ядро:</p>
<pre><span style="color: #0000ff;"># cd /usr/src
# make buildkernel KERNCONF=UTM
# make installkernel KERNCONF=UTM</span></pre>
<p>Где UTM &#8211; имя моего конфигурационного файла ядра.<br />
Перед перезагрузкой можно сразу поправить файл /etc/rc.conf добавив в него: Сервер utm1:</p>
<pre><span style="color: #0000ff;">cloned_interfaces="carp0 carp1 carp2"
ifconfig_em0="inet 1.2.3.244 netmask 255.255.255.240"
ifconfig_em1="inet 1.2.3.108 netmask 255.255.255.240"
ifconfig_em2="inet 172.31.31.3 netmask 255.255.255.240"
ifconfig_em3="inet 172.30.30.172 netmask 255.255.255.248"
ifconfig_carp0="vhid 1 pass secret 1.2.3.242 netmask 255.255.255.240"
ifconfig_carp1="vhid 2 pass secret 1.2.3.99 netmask 255.255.255.240"
ifconfig_carp2="vhid 3 pass secret 172.31.31.2 netmask 255.255.255.240"</span></pre>
<p>Сервер utm2:</p>
<pre><span style="color: #0000ff;">cloned_interfaces="carp0 carp1 carp2"
ifconfig_em0="inet 1.2.3.245 netmask 255.255.255.240"
ifconfig_em1="inet 1.2.3.109 netmask 255.255.255.240"
ifconfig_em2="inet 172.31.31.3 netmask 255.255.255.240"
ifconfig_em3="inet 172.30.30.173 netmask 255.255.255.248"
ifconfig_carp0="vhid 1 pass secret 1.2.3.242 netmask 255.255.255.240"
ifconfig_carp1="vhid 2 pass secret 1.2.3.99 netmask 255.255.255.240"
ifconfig_carp2="vhid 3 pass secret 172.31.31.4 netmask 255.255.255.240"</span></pre>
<p>Все сетевые соединения должны быть подключены.<br />
Перегружаем сервера и смотрим:</p>
<pre><span style="color: #0000ff;">#utm1 carp0: flags=49 metric 0 mtu 1500
carp: MASTER vhid 1 advbase 1 advskew 0
carp1: flags=49 metric 0 mtu 1500
carp: MASTER vhid 2 advbase 1 advskew 0
carp2: flags=49 metric 0 mtu 1500
carp: MASTER vhid 3 advbase 1 advskew 0

#utm2 carp0: flags=49 metric 0 mtu 1500
carp: BACKUP vhid 1 advbase 1 advskew 100
carp1: flags=49 metric 0 mtu 1500
carp: BACKUP vhid 2 advbase 1 advskew 100
carp2: flags=49 metric 0 mtu 1500
carp: BACKUP vhid 3 advbase 1 advskew 100</span></pre>
<p>Как видно, на сервере utm1 интерфейсы carp имеют статус MASTER, а на utm2 – BACKUP<br />
Теперь, если отключить любой CARP интерфейс на сервере utm1, то все CARP интерфейсы на сервере utm2 перейдут в статус MASTER, а на сервере utm1 отключенный интерфейс будет иметь статус INIT, а остальные BACKUP.<br />
После восстановления связности, сервер utm1 опять захватит роль MASTER сервера в кластере. При этом dmesg покажет следующее</p>
<pre><span style="color: #0000ff;">em1: link state changed to DOWN
carp0: MASTER -&gt; BACKUP (more frequent advertisement received)
carp2: MASTER -&gt; BACKUP (more frequent advertisement received)
carp1: INIT -&gt; BACKUP
em1: link state changed to UP
carp2: BACKUP -&gt; MASTER (preempting a slower master)
carp0: BACKUP -&gt; MASTER (preempting a slower master)</span></pre>
<p>На этом оставим пока работу CARP и настроим репликацию БД.<br />
Репликация будет осуществляться двухсторонняя, т.е. изменения, сделанные на основном сервере, будут передаваться на резервный и наоборот. Нужно это для того, чтобы при остановке основного сервера, не произошла рассинхронизация БД.<br />
База данных должна быть типа innodb. Помимо того, что это рекомендовано NetUP, только с таким типом работает репликация.<br />
Реплицировать будем только базу UTM5.<br />
Останавливаем ядро UTM, если оно запущено, а также все приложения, которые имеют доступ к базе UTM5. На основном сервере делаем дамп базы и переносим его на резервный.<br />
Выполняем на основном сервере</p>
<pre><span style="color: #0000ff;">#utm1 mysql –u root -p
mysql&gt; GRANT REPLICATION SLAVE ON UTM5.* TO 'utmuser'@'utm2.domain.ru' \
IDENTIFIED BY 'password';
mysql&gt; flush privileges;
mysql&gt; quit</span></pre>
<p>Где utmuser – имя пользователя, который будет подключаться с резервного сервера для репликации, utm2.domain.ru имя сервера (или IP адрес) резервного сервера, password – пароль пользователя utmuser На резервном сервере выполняем тоже самое, заменив имя сервера на основной и при необходимости имя пользователя и пароль.<br />
Останавливаем mysql на обоих серверах и вносим изменения в файл my.cnf (у меня это /var/db/mysql/my.cnf<br />
На сервере utm1 добавляем:</p>
<pre><span style="color: #0000ff;">log-bin
server-id=1
max_binlog_size = 1G
max_relay_log_size = 0
binlog-do-db=UTM5
master-host = 172.30.30.173
master-user = utmuser
master-password = password</span></pre>
<p>На сервере utm2:</p>
<pre><span style="color: #0000ff;">log-bin
server-id=2
max_binlog_size = 1G
max_relay_log_size = 0
binlog-do-db=UTM5
master-host = 172.30.30.172
master-user = utmuser
master-password = password</span></pre>
<p>Запускаем mysql на основном сервере, затем на резервном. Заходим в mysql и проверяем:</p>
<pre><span style="color: #0000ff;">mysql&gt; show master status;
+-----------------+----------+--------------+------------------+
| File            | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-----------------+----------+--------------+------------------+
| nup2-bin.000003 |      106 | UTM5,UTM5    |                  |
+-----------------+----------+--------------+------------------+
1 row in set (0.00 sec)
mysql&gt; show slave status;</span></pre>
<p>Выводит таблицу состояния SLAVE, там куча ячеек, думаю, сами разберетесь.<br />
Главное, на что стоит обратить внимание, значения полей File и Position в выводе show master status на первом сервере, должны совпадать со значениями полей Master_Log_File и Read_Master_Log_Pos на втором. И наоборот, значения полей File и Position в выводе show master status на втором сервере, должны совпадать со значениями полей Master_Log_File и Read_Master_Log_Pos на первом.<br />
Если все так и есть, репликация работает нормально.<br />
Для проверки, можно внести абонента на основном сервере и проверить, появилась ли соответствующая запись на втором.<br />
Более подробно с настройкой репликации можно ознакомиться на сайте mysql.ru <a href="http://www.mysql.ru/docs/man/Replication_Implementation.html" target="_blank">[3]</a></p>
<p>Теперь переходим к процессу автоматизации.<br />
Проблемой (а может быть и правильно, что так сделано) UTM, является то, что данные в БД предназначены для длительного хранения. Все последние изменения ядро хранит в ОЗУ и как следствие, запущенное на резервном сервере ядро не видит изменений, сделанных на основном сервере.<br />
С другой стороны, согласен с разработчиками, что для корректной работы одновременно должно работать только одно ядро utm5_core.<br />
Поэтому наша задача: контролировать статус сервер и в случае если SLAVE сервер берет на себя функции MASTER, запустить на нем ядро. И если MASTER сервер переходит в статус SLAVE, то гасить на нем ядро. Данную задачу можно реализовать через cron, периодически опрашивая состояние интерфейсов CARP. Ктомуже, это будет не лишним и в случае если по каким-либо причинам окажется, что на MASTER сервере ядро не запущено.<br />
Скрипт проверяющий состояние сервера и запущены ли на нем необходимые модули приведен ниже:</p>
<pre><span style="color: #0000ff;">#!/bin/sh
#Присвоение значения переменным
#Имя файла в который будут писаться сообщения о смене
#статуса и запуска процессов
log=/netup/utm5/log/_carp.log
#Имя директории с исполняемым скриптами UTM5
rc_dir=/usr/local/etc/rc.d
#Имя скрипта запуска ядра UTM5
core_script=utm5_core.sh
#Имя скрипта запуска RADIUS-сервера UTM5
#Если RADIUS-сервер не используется, закомментировать
radius_script=utm5_radius.sh
#Имя скрипта запуска RFW UTM5
#Если RFW-сервер не исползуется, закомментировать
#rfw_script=utm5_rfw.sh
#Включено ли логирование событий. 0-1
#Если включено, сто в файл определенный в переменной log будут писаться
#сообщения о смене состояния сервера и запуске или остановке сервисов UTM5
debug=1
DATE=`/bin/date +"%Y-%m-%d %H:%M:%S"`
CARP_STATUS="MASTER"

for CARP in `/sbin/ifconfig | /usr/bin/grep carp: | /usr/bin/awk \
'{print $2}'`
do
    if [ $CARP = "BACKUP" ] || [ $CARP = "INIT" ]; then
        CARP_STATUS="BACKUP";
    fi
done
if [ $core_script ];then
    UTM5_CORE=`/bin/ps ax | /usr/bin/grep utm5_core | /usr/bin/grep -v stop \
             | /usr/bin/grep safe | /usr/bin/awk '{print $1}'`
    if [ $CARP_STATUS = "BACKUP" ] &amp;&amp; [ $UTM5_CORE ]; then
        $rc_dir/$core_script stop 1&gt; /dev/null 2&gt; /dev/null
        if [ $debug != 0 ];then
            /bin/echo $DATE "CARP is BACKUP &amp;&amp; utm5_core is started. \
            Stop it." &gt;&gt; $log
        fi
    fi
    if [ $CARP_STATUS = "MASTER" ] &amp;&amp; [ ! $UTM5_CORE ]; then
        $rc_dir/$core_script start 1&gt; /dev/null 2&gt; /dev/null
        if [ $debug != 0 ];then
            /bin/echo $DATE "CARP is MASTER &amp;&amp; utm5_core is stoped. \
            Start it." &gt;&gt; $log
        fi
        sleep 5
    fi
fi
if [ $radius_script ];then
    UTM5_RADIUS=`/bin/ps ax | /usr/bin/grep utm5_radius \
              | /usr/bin/grep -v stop | /usr/bin/grep safe \
              | /usr/bin/awk '{print $1}'`
    if [ $CARP_STATUS = "BACKUP" ] &amp;&amp; [ $UTM5_RADIUS ]; then
        $rc_dir/$radius_script stop 1&gt; /dev/null 2&gt; /dev/null
        if [ $debug != 0 ];then
            /bin/echo $DATE "CARP is BACKUP &amp;&amp; utm5_radius is started. \
            Stop it." &gt;&gt; $log
        fi
    fi
    if [ $CARP_STATUS = "MASTER" ] &amp;&amp; [ ! $UTM5_RADIUS ]; then
        $rc_dir/$radius_script start 1&gt; /dev/null 2&gt; /dev/null
        if [ $debug != 0 ];then
            /bin/echo $DATE "CARP is MASTER &amp;&amp; utm5_radius is stoped. \
            Start it." &gt;&gt; $log
        fi
    fi
fi
if [ $rfw_script ];then
    UTM5_RFW=`/bin/ps ax | /usr/bin/grep utm5_rfw \
            | /usr/bin/grep -v stop | /usr/bin/grep safe \
            | /usr/bin/awk '{print $1}'`
    if [ $CARP_STATUS = "BACKUP" ] &amp;&amp; [ $UTM5_RFW ]; then
        $rc_dir/$rfw_script stop 1&gt; /dev/null 2&gt; /dev/null
        if [ $debug != 0 ];then
            /bin/echo $DATE "CARP is BACKUP &amp;&amp; utm5_rfw is started. \
            Stop it." &gt;&gt; $log
        fi
    fi
    if [ $CARP_STATUS = "MASTER" ] &amp;&amp; [ ! $UTM5_RFW ]; then
        $rc_dir/$rfw_script start 1&gt; /dev/null 2&gt; /dev/null
        if [ $debug != 0 ];then
            /bin/echo $DATE "CARP is MASTER &amp;&amp; utm5_rfw is stoped. \
            Start it." &gt;&gt; $log
        fi
    fi
fi</span></pre>
<p>Данный скрипт проверяет, в каком состоянии находиться сервер:<br />
Если сервер MASTER, то проверяется, запущенны ли сервисы utm5_core, utm5_radius и utm5_rfw (если какой то из сервисов не нужен, то нужно закомментировать строку определяющую имя запускающего данный сервис скрипта в начале файла. Если нужные сервисы не запущены, то дается команда на их запуск.<br />
Если переменная debug=1 то информация о запуске или останове процессов пишется в файл определенный в переменной log<br />
Для примера, сервер имеет статус MASTER но ядро UTM5 и RDIUS –сервер на нем не запущены. Дана команда на запуск этих сервисов.</p>
<pre><span style="color: #0000ff;">2009-04-03 21:13:47 CARP is MASTER &amp;&amp; utm5_core is stoped. Start it.
2009-04-03 21:13:47 CARP is MASTER &amp;&amp; utm5_radius is stoped. Start it.</span></pre>
<p>Сервер имеет состояние SLAVE но ядро и RADIUS на нем запущены, дана команда на их остановку</p>
<pre><span style="color: #0000ff;">2009-04-03 21:10:22 CARP is BACKUP &amp;&amp; utm5_core is started. Stop it.
2009-04-03 21:10:22 CARP is BACKUP &amp;&amp; utm5_radius is started. Stop it.</span></pre>
<p>На этом можно было бы и закончить, но пытливый читатель спросит, зачем мы патчили ip_carp.c в самом начале?<br />
Отвечаю. Вариант с проверкой статуса сервера хоть и хорош, но выполнять его даже раз в минуту не очень хочется, а порой минута может стоить много денег и нервов. Поэтому, проверка состояния сервера и сервисов у меня выполняется раз в пять минут, а события вызываемые патченным сервисом carp обрабатываются налету при помощи демона devd. <a href="http://www.freebsd.org/cgi/man.cgi?query=devd&amp;apropos=0&amp;sektion=0&amp;manpath=FreeBSD+7.1-RELEASE&amp;format=html" target="_blank">[4]</a><br />
Внесем изменения в файл /etc/devd.conf <a href="http://www.freebsd.org/cgi/man.cgi?query=devd.conf&amp;apropos=0&amp;sektion=0&amp;manpath=FreeBSD+7.1-RELEASE&amp;format=html" target="_blank">[5]</a></p>
<pre><span style="color: #0000ff;">notify 100 {
    match "system" "IFNET";
    match "type" "CARP_SLAVE";
    action "/usr/local/sbin/carp.sh $subsystem $vhid $type";
};

notify 100 {
    match "system" "IFNET";
    match "type" "CARP_MASTER";
    action "/usr/local/sbin/carp.sh $subsystem $vhid $type";
};
notify 100 {
    match "system" "IFNET";
    match "type" "CARP_UNKNOWN";
    action "/usr/local/sbin/carp.sh $subsystem $vhid $type";
};</span></pre>
<p>Перезапускаем сервис devd:</p>
<pre><span style="color: #0000ff;"># /etc/rc.d/devd stop
# /etc/rc.d/devd start</span></pre>
<p>Внесенные изменения позволят запускать скрипты при наступлении определенных событий вызванных интерфейсами CARP.<br />
Сделанный нами патч выдает три состояния CARP_MASTER – если carp интерфейс переходит в состояние MASTER, CARP_SLAVE – если carp интерфейс переходит в состояние SLAVE и CARP_UNCNOWN – если состояние интерфейса не удается определить.<br />
При наступлении любого из этих событий, devd вызовет исполнение скрипта указанного в параметре action конфигурационного файла devd.conf для данного события. У меня это &laquo;/usr/local/sbin/carp.sh $subsystem $vhid $type&raquo;, где $subsystem – имя carp интерфейса (carp0, carp1 и т.п.), $vhid – VHID интерфейса заданного в rc.conf, $type – тип события (CARP_SLAVE, CARP_MASTER, CARP_UNKNOWN).<br />
По хорошему, нам нужно перехватывать только тип события, но в дальнейшем можно найти применения и для других параметров, пусть будут <img src='http://ctpahhuk.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Скрипт carp.sh</p>
<pre><span style="color: #0000ff;">sleep 5
debug=1
log=/netup/utm5/log/_carp.log
bin_dir=/netup/utm5/bin
DATE=`/bin/date +"%Y-%m-%d %H:%M:%S"`
UTM5_CORE=`/bin/ps ax | /usr/bin/grep utm5_core | /usr/bin/grep -v stop \
         | /usr/bin/grep safe | /usr/bin/awk '{print $1}'`
TYPE=$3
if [ $TYPE = "CARP_MASTER" ] &amp;&amp; [ ! $UTM5_CORE ]; then
    if [ $debug != 0 ];then
        /bin/echo "$DATE $TYPE ($1): Running \
        $bin_dir/check_utm5.sh" &gt;&gt; $log
    fi
    $bin_dir/check_utm5.sh
fi
if [ $TYPE = "CARP_SLAVE" ] &amp;&amp; [ $UTM5_CORE ]; then
    if [ $debug != 0 ];then
        /bin/echo "$DATE $TYPE ($1):  Running \
        $bin_dir/check_utm5.sh" &gt;&gt; $log;
    fi
    $bin_dir/check_utm5.sh
fi</span></pre>
<p>Данный скрипт проверяет только статус сервера и запущено ли ядро. Если сервер стал мастером и ядро не запущено или сервер стал ведомым и на нем запущено ядро, то выполняется скрипт check_utm5.sh описанный чуть выше.<br />
Вобщемто, эта доработка позволяет сократить время поднятия сервисов в случае отказа основного сервера до 5-10 секунд.<br />
Строка sleep 5 в начале файла нужна если у нас более чем один carp интерфейс. Поскольку при смене статуса одного из CARP интерфейсов, все остальные тоже меняют статус, соответсвенно и события вызывают данный скрипт несколько раз.<br />
Так как запуск ядра UTM5 требует некоторого времени, чтобы ядро не запускалось несколько раз и введена данная задержка.<br />
Кроме того, скрипт carp.sh пишет в логфайл время и тип наступившего события. Пример:</p>
<pre><span style="color: #0000ff;">2009-04-03 21:12:09 CARP_MASTER (carp0): Running /netup/utm5/bin/check_utm5.sh
2009-04-03 21:12:09 CARP is MASTER &amp;&amp; utm5_core is stoped. Start it.
2009-04-03 21:12:09 CARP is MASTER &amp;&amp; utm5_radius is stoped. Start it.
2009-04-03 21:13:15 CARP_SLAVE (carp0):  Running /netup/utm5/bin/check_utm5.sh
2009-04-03 21:13:15 CARP is BACKUP &amp;&amp; utm5_core is started. Stop it.
2009-04-03 21:13:15 CARP is BACKUP &amp;&amp; utm5_radius is started. Stop it.</span></pre>
<p>Скрипт carp.sh был запущен из devd с передачей типа CARP_MASTER. Скрипт поверил, что ядро не запущено и вызвал скрипт /netup/utm5/bin/check_utm5.sh, который в свою очередь проверил, что сервер имеет статус MASTER но на нем не запущено ядро и RADIUS сервер.<br />
Дана команда на запуск данных сервисов.<br />
Затем скрипт carp.sh был вызван с передачей типа CARP_SLAVE. Поскольку на сервере были запущены сервисы utm5_core и utm5_radius вызван скрипт check_utm5.sh который их остановил.<br />
[1] Создание отказоустойчивого кластера для биллинговой системы на базе Gentoo Linux<br />
[2] FreeBSD Man Pages (CARP)<br />
[3] Репликация в MySQL<br />
[4] FreeBSD Man Pages (devd)<br />
[5] FreeBSD Man Pages (devd.conf)</p>
]]></content:encoded>
			<wfw:commentRss>http://ctpahhuk.ru/archives/175/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Сбор и обработка статистики по использованию памяти</title>
		<link>http://ctpahhuk.ru/archives/169</link>
		<comments>http://ctpahhuk.ru/archives/169#comments</comments>
		<pubDate>Tue, 08 Dec 2009 11:31:20 +0000</pubDate>
		<dc:creator>CTPAHHuK</dc:creator>
				<category><![CDATA[Мониторинг]]></category>
		<category><![CDATA[Статьи]]></category>
		<category><![CDATA[arpwatch]]></category>
		<category><![CDATA[CPU]]></category>
		<category><![CDATA[cricket]]></category>
		<category><![CDATA[gprs]]></category>
		<category><![CDATA[memAvailReal]]></category>
		<category><![CDATA[memAvailSwap]]></category>
		<category><![CDATA[memBuffer]]></category>
		<category><![CDATA[memCached]]></category>
		<category><![CDATA[memTotalReal]]></category>
		<category><![CDATA[memTotalSwap]]></category>
		<category><![CDATA[MRTG]]></category>
		<category><![CDATA[Nagios]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[ROM]]></category>
		<category><![CDATA[RRD]]></category>
		<category><![CDATA[RRDTool]]></category>
		<category><![CDATA[sms]]></category>
		<category><![CDATA[SNMP]]></category>
		<category><![CDATA[SWAP]]></category>

		<guid isPermaLink="false">http://xn--80aqgkapgi.net/?p=169</guid>
		<description><![CDATA[В данной статье рассматривается сбор и вывод информации об использовании памяти сервера под FreeBSD. Скрипт для сбора статистики по памяти. Данный скрипт собирает статистику по нескольким параметрам загруженности памяти. Впринципе, скрипт не сильно отличается от скрипта сбора статистики по CPU , поэтому остановимся на некоторых тонкостях. В базу мы будем писать значения: 1. Всего свопа [...]]]></description>
			<content:encoded><![CDATA[<p>В данной статье рассматривается сбор и вывод информации об использовании памяти сервера под FreeBSD.</p>
<p><span id="more-169"></span><strong>Скрипт для сбора статистики по памяти.</strong><br />
Данный скрипт собирает статистику  по нескольким параметрам загруженности памяти.<br />
Впринципе, скрипт не сильно отличается от <a href="/archives/165">скрипта сбора статистики по CPU</a> , поэтому остановимся на некоторых тонкостях.<br />
В базу мы будем писать значения:</p>
<p>1. Всего свопа<br />
2. Доступно свопа<br />
3. Доступно основной памяти<br />
4. Используется основной памяти<br />
5. Используется под буфера<br />
6. Используется под кэш<br />
7. Используется свопа<br />
8. Всего основной памяти (RAM)</p>
<p>Итого 8 параметров. Но по SNMP возможно получить только параметры</p>
<p>1. Всего свопа<br />
2. Доступно свопа<br />
3. Всего основной памяти (RAM)<br />
4. Доступно основной памяти<br />
5. Используется под буфера<br />
6. Используется под кэш</p>
<p>Параметры «Используется свопа» и «Всего основной памяти» мы вычисляем в скрипте.<br />
Все остальное аналогично скрипту для CPU.</p>
<p>&#8212;- START makerrdmem.sh &#8212;-<br />
<span style="color: #0000ff;">#!/bin/sh<br />
RRDDIR=&raquo;/usr/local/rrd&raquo; #Директория базы данных<br />
CMD=&raquo;/usr/local/bin/snmpget -r 9 -t 3 -Oqv -v2c&raquo; #Команда для сбора статистики по SNMP<br />
RRDCMD=&raquo;/usr/local/bin/rrdtool&raquo;<br />
COMNAME=&raquo;public&raquo; #Комьюнити сервера (серверов)<br />
FILENAME=&raquo;mem.rrd&raquo; #суффикс файла<br />
CONFIG=&raquo;/usr/local/etc/rrdconf/cpu.conf&raquo;<br />
OID=&raquo;.1.3.6.1.4.1.2021.4.3.0 \<br />
.1.3.6.1.4.1.2021.4.4.0 \<br />
.1.3.6.1.4.1.2021.4.5.0 \<br />
.1.3.6.1.4.1.2021.4.6.0 \<br />
.1.3.6.1.4.1.2021.4.14.0 \<br />
.1.3.6.1.4.1.2021.4.15.0&#8243;<br />
#OIDs<br />
#memTotalSwap .1.3.6.1.4.1.2021.4.3.0<br />
#memAvailSwap .1.3.6.1.4.1.2021.4.4.0<br />
#memTotalReal .1.3.6.1.4.1.2021.4.5.0<br />
#memAvailReal .1.3.6.1.4.1.2021.4.6.0<br />
#memBuffer .1.3.6.1.4.1.2021.4.14.0<br />
#memCached .1.3.6.1.4.1.2021.4.15.0<br />
for i in `cat $CONFIG | grep -v &laquo;^#&raquo;`<br />
do<br />
HOST=$i<br />
if [ ! -e "$RRDDIR/$HOST-$FILENAME" ]; then<br />
[ -e "$RRDDIR" ] || mkdir &laquo;$RRDDIR&raquo;<br />
$RRDCMD create &laquo;$RRDDIR/$HOST-$FILENAME&raquo; -s 60\<br />
DS:tswap:GAUGE:360:0:U\<br />
DS:aswap:GAUGE:360:0:U\<br />
DS:treal:GAUGE:360:0:U\<br />
DS:areal:GAUGE:360:0:U\<br />
DS:buff:GAUGE:360:0:U\<br />
DS:cach:GAUGE:360:0:U\<br />
DS:uswap:GAUGE:360:0:U\<br />
DS:ureal:GAUGE:360:0:U\<br />
RRA:AVERAGE:0.5:1:1440\<br />
RRA:AVERAGE:0.5:5:1440\<br />
RRA:AVERAGE:0.5:30:1440\<br />
RRA:AVERAGE:0.5:120:1440\<br />
RRA:AVERAGE:0.5:720:1440\<br />
RRA:MAX:0.5:1:1440\<br />
RRA:MAX:0.5:5:1440\<br />
RRA:MAX:0.5:30:1440\<br />
RRA:MAX:0.5:120:1440\<br />
RRA:MAX:0.5:720:1440<br />
fi<br />
STRING=`$CMD -c $COMNAME $HOST $OID | awk &#8216;{printf &laquo;:&raquo;$1}&#8217;`<br />
TREAL=`$CMD -c $COMNAME $HOST .1.3.6.1.4.1.2021.4.5.0`<br />
AREAL=`$CMD -c $COMNAME $HOST .1.3.6.1.4.1.2021.4.6.0`<br />
UREAL=`expr $TREAL &#8211; $AREAL`<br />
TSWAP=`$CMD -c $COMNAME $HOST .1.3.6.1.4.1.2021.4.3.0`<br />
ASWAP=`$CMD -c $COMNAME $HOST .1.3.6.1.4.1.2021.4.4.0`<br />
USWAP=`expr $TSWAP &#8211; $ASWAP`<br />
FSTRING=$STRING:$USWAP:$UREAL<br />
if [ -w "$RRDDIR/$HOST-$FILENAME" ]; then<br />
$RRDCMD update $RRDDIR/$HOST-$FILENAME N$FSTRING<br />
else<br />
echo $HOST-$FILENAME is not writable<br />
fi<br />
done</span><br />
&#8212;- END makerrdmem.sh &#8212;-</p>
<p><strong>Вывод информации по памяти.</strong><br />
Хотя запись и ведется в одну базу, но на мой взгляд, разумнее выводить два графика.</p>
<p>1. Основная память<br />
2. Своп</p>
<p>Скрипт вывода графика использования основной памяти:<br />
Скрипт вызывается аналогично скрипту по процессору.<br />
mem.cgi?DS= mail.maindomain.ru-mem.rrd&amp;title=6%20hour%20graph&amp;start=-6h</p>
<p>&#8212;- START mem.cgi &#8212;-<br />
<span style="color: #0000ff;">#!/usr/local/bin/perl -w<br />
use RRDs;<br />
use CGI qw(:standard);<br />
use Math::Round qw(:all);<br />
$rrddir=&raquo;/usr/local/rrd&raquo;;<br />
my (@DEF, @FETCH_DEF, @PLOT, @options);<br />
my $statfmt = &laquo;%.3lf%s&raquo;;<br />
$|=1;<br />
print header(&#8216;image/gif&#8217;);<br />
$database = param(&#8216;DS&#8217;);<br />
push (@FETCH_DEF, &laquo;$rrddir/$database&raquo;,<br />
&laquo;AVERAGE&raquo;, &laquo;-s&raquo;, param(&#8216;start&#8217;));<br />
push(@DEF, &laquo;DEF:CP_TREAL=$rrddir/$database:treal:AVERAGE&raquo;);<br />
push(@DEF, &laquo;DEF:CP_AREAL=$rrddir/$database:areal:AVERAGE&raquo;);<br />
push(@DEF, &laquo;DEF:CP_BUFF=$rrddir/$database:buff:AVERAGE&raquo;);<br />
push(@DEF, &laquo;DEF:CP_UREAL=$rrddir/$database:ureal:AVERAGE&raquo;);<br />
push(@DEF, &laquo;CDEF:TREAL=CP_TREAL,1000,*&raquo;);<br />
push(@DEF, &laquo;CDEF:AREAL=CP_AREAL,1000,*&raquo;);<br />
push(@DEF, &laquo;CDEF:UREAL=CP_UREAL,1000,*&raquo;);<br />
push(@DEF, &laquo;CDEF:BUFF=CP_BUFF,1000,*&raquo;);<br />
push(@PLOT,<br />
&laquo;COMMENT:Memory          &laquo;,<br />
&laquo;AREA:TREAL#1000CC:Total         &laquo;,<br />
&laquo;AREA:TREAL#54EC48:Free          &laquo;,<br />
&laquo;AREA:UREAL#EA644A:Used          &laquo;,<br />
&laquo;AREA:BUFF#48C4EC:Buffer&raquo;,<br />
&laquo;LINE3:TREAL#1000AA&raquo;,<br />
&laquo;LINE1:UREAL#CC3118&#8243;,<br />
&laquo;LINE1:BUFF#1598C3&#8243;,<br />
&#8216;COMMENT:\n&#8217;);<br />
push(@PLOT,<br />
&laquo;GPRINT:TREAL:LAST:Now           ${statfmt} total        &laquo;,<br />
&laquo;GPRINT:AREAL:LAST: ${statfmt} free      &laquo;,<br />
&laquo;GPRINT:UREAL:LAST: ${statfmt} used      &laquo;,<br />
&laquo;GPRINT:BUFF:LAST: ${statfmt} buffers&raquo;,<br />
&#8216;COMMENT:\n&#8217;);<br />
push(@PLOT,<br />
&laquo;GPRINT:TREAL:AVERAGE:Average    ${statfmt} total        &laquo;,<br />
&laquo;GPRINT:AREAL:AVERAGE: ${statfmt} free   &laquo;,<br />
&laquo;GPRINT:UREAL:AVERAGE: ${statfmt} used   &laquo;,<br />
&laquo;GPRINT:BUFF:AVERAGE: ${statfmt} buffers&raquo;,<br />
&#8216;COMMENT:\n&#8217;);<br />
push(@PLOT,<br />
&laquo;GPRINT:TREAL:MAX:Maximum        ${statfmt} total        &laquo;,<br />
&laquo;GPRINT:AREAL:MAX: ${statfmt} free       &laquo;,<br />
&laquo;GPRINT:UREAL:MAX: ${statfmt} used       &laquo;,<br />
&laquo;GPRINT:BUFF:MAX: ${statfmt} buffers&raquo;,<br />
&#8216;COMMENT:\n&#8217;);<br />
foreach $opt (&#8216;start&#8217;,'title&#8217;) {<br />
if (param($opt)) {<br />
push(@options, &laquo;&#8211;${opt}&raquo;, param($opt));<br />
}<br />
}<br />
push(@options, &laquo;&#8211;width&raquo;,&raquo;450&#8243;,&raquo;&#8211;height&raquo;,&raquo;120&#8243;);<br />
push(@options, &laquo;&#8211;vertical-label&raquo;,&raquo;Memory Size&raquo;);<br />
push(@options, &laquo;&#8211;lower-limit&raquo;,&raquo;1&#8243;);<br />
push(@options, &laquo;&#8211;font&raquo;,&raquo;DEFAULT:8:/usr/lib/fonts/arial.ttf&raquo;);<br />
RRDs::graph(&#8216;-&#8217;,@options,@DEF,@PLOT);<br />
exit 0;</span><br />
&#8212;- END mem.cgi &#8212;-</p>
<div id="attachment_172" class="wp-caption alignnone" style="width: 557px"><a href="http://xn--80aqgkapgi.net/wp-content/uploads/2009/12/rrd2.jpg"><img class="size-full wp-image-172" title="rrd2" src="http://xn--80aqgkapgi.net/wp-content/uploads/2009/12/rrd2.jpg" alt="Рисунок 1. График использования основной памяти." width="547" height="242" /></a><p class="wp-caption-text">Рисунок 1. График использования основной памяти.</p></div>
<p>&#8212;- START swap.cgi &#8212;-<br />
<span style="color: #0000ff;">#!/usr/local/bin/perl -w<br />
use RRDs;<br />
use CGI qw(:standard);<br />
use Math::Round qw(:all);<br />
$rrddir=&raquo;/usr/local/rrd&raquo;;<br />
my (@DEF, @FETCH_DEF, @PLOT, @options);<br />
my $statfmt = &laquo;%.3lf%s&raquo;;<br />
$|=1;<br />
print header(&#8216;image/gif&#8217;);<br />
$database = param(&#8216;DS&#8217;);<br />
push (@FETCH_DEF, &laquo;$rrddir/$database&raquo;,<br />
&laquo;AVERAGE&raquo;, &laquo;-s&raquo;, param(&#8216;start&#8217;));<br />
push(@DEF, &laquo;DEF:CP_TSWAP=$rrddir/$database:tswap:AVERAGE&raquo;);<br />
push(@DEF, &laquo;DEF:CP_ASWAP=$rrddir/$database:aswap:AVERAGE&raquo;);<br />
push(@DEF, &laquo;DEF:CP_CACH=$rrddir/$database:cach:AVERAGE&raquo;);<br />
push(@DEF, &laquo;DEF:CP_USWAP=$rrddir/$database:uswap:AVERAGE&raquo;);<br />
push(@DEF, &laquo;CDEF:TSWAP=CP_TSWAP,1000,*&raquo;);<br />
push(@DEF, &laquo;CDEF:ASWAP=CP_ASWAP,1000,*&raquo;);<br />
push(@DEF, &laquo;CDEF:USWAP=CP_USWAP,1000,*&raquo;);<br />
push(@DEF, &laquo;CDEF:CACH=CP_CACH,1000,*&raquo;);<br />
push(@PLOT,<br />
&laquo;COMMENT:Swap            &laquo;,<br />
&laquo;AREA:TSWAP#CC7016:Total         &laquo;,<br />
&laquo;AREA:TSWAP#ECD748:Free          &laquo;,<br />
&laquo;AREA:USWAP#7648EC:Used          &laquo;,<br />
&laquo;AREA:CACH#DE48EC:Cached&raquo;,<br />
&laquo;LINE3:TSWAP#CC7016&#8243;,<br />
&laquo;LINE1:USWAP#4D18E4&#8243;,<br />
&laquo;LINE1:CACH#B415C7&#8243;,<br />
&#8216;COMMENT:\n&#8217;);<br />
push(@PLOT,<br />
&laquo;GPRINT:TSWAP:LAST:Now           ${statfmt} total        &laquo;,<br />
&laquo;GPRINT:ASWAP:LAST: ${statfmt} free      &laquo;,<br />
&laquo;GPRINT:USWAP:LAST: ${statfmt} used      &laquo;,<br />
&laquo;GPRINT:CACH:LAST: ${statfmt} cached&raquo;,<br />
&#8216;COMMENT:\n&#8217;);<br />
push(@PLOT,<br />
&laquo;GPRINT:TSWAP:AVERAGE:Average    ${statfmt} total        &laquo;,<br />
&laquo;GPRINT:ASWAP:AVERAGE: ${statfmt} free   &laquo;,<br />
&laquo;GPRINT:USWAP:AVERAGE: ${statfmt} used   &laquo;,<br />
&laquo;GPRINT:CACH:AVERAGE: ${statfmt} cached&raquo;,<br />
&#8216;COMMENT:\n&#8217;);<br />
push(@PLOT,<br />
&laquo;GPRINT:TSWAP:MAX:Maximum        ${statfmt} total        &laquo;,<br />
&laquo;GPRINT:ASWAP:MAX: ${statfmt} free       &laquo;,<br />
&laquo;GPRINT:USWAP:MAX: ${statfmt} used       &laquo;,<br />
&laquo;GPRINT:CACH:MAX: ${statfmt} cached&raquo;,<br />
&#8216;COMMENT:\n&#8217;);<br />
foreach $opt (&#8216;start&#8217;,'title&#8217;) {<br />
if (param($opt)) {<br />
push(@options, &laquo;&#8211;${opt}&raquo;, param($opt));<br />
}<br />
}<br />
push(@options, &laquo;&#8211;width&raquo;,&raquo;450&#8243;,&raquo;&#8211;height&raquo;,&raquo;120&#8243;);<br />
push(@options, &laquo;&#8211;vertical-label&raquo;,&raquo;Memory Size&raquo;);<br />
push(@options, &laquo;&#8211;lower-limit&raquo;,&raquo;1&#8243;);<br />
push(@options, &laquo;&#8211;font&raquo;,&raquo;DEFAULT:8:/usr/lib/fonts/arial.ttf&raquo;);<br />
RRDs::graph(&#8216;-&#8217;,@options,@DEF,@PLOT);<br />
exit 0;</span><br />
&#8212;- END swap.cgi &#8212;-</p>
<div id="attachment_171" class="wp-caption alignnone" style="width: 557px"><a href="http://xn--80aqgkapgi.net/wp-content/uploads/2009/12/rrd3.jpg"><img class="size-full wp-image-171" title="rrd3" src="http://xn--80aqgkapgi.net/wp-content/uploads/2009/12/rrd3.jpg" alt="Рисунок 2. График использования своп." width="547" height="241" /></a><p class="wp-caption-text">Рисунок 2. График использования своп.</p></div>
]]></content:encoded>
			<wfw:commentRss>http://ctpahhuk.ru/archives/169/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Сбор и обработка статистики по загрузке CPU</title>
		<link>http://ctpahhuk.ru/archives/165</link>
		<comments>http://ctpahhuk.ru/archives/165#comments</comments>
		<pubDate>Tue, 08 Dec 2009 11:19:08 +0000</pubDate>
		<dc:creator>CTPAHHuK</dc:creator>
				<category><![CDATA[Мониторинг]]></category>
		<category><![CDATA[Статьи]]></category>
		<category><![CDATA[arpwatch]]></category>
		<category><![CDATA[CPU]]></category>
		<category><![CDATA[cricket]]></category>
		<category><![CDATA[gprs]]></category>
		<category><![CDATA[MRTG]]></category>
		<category><![CDATA[Nagios]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[ROM]]></category>
		<category><![CDATA[RRD]]></category>
		<category><![CDATA[RRDTool]]></category>
		<category><![CDATA[sms]]></category>
		<category><![CDATA[SNMP]]></category>
		<category><![CDATA[ssCpuRawIdle]]></category>
		<category><![CDATA[ssCpuRawInterrupt]]></category>
		<category><![CDATA[ssCpuRawKernel]]></category>
		<category><![CDATA[ssCpuRawNice]]></category>
		<category><![CDATA[ssCpuRawSystem]]></category>
		<category><![CDATA[ssCpuRawUser]]></category>
		<category><![CDATA[SWAP]]></category>

		<guid isPermaLink="false">http://xn--80aqgkapgi.net/?p=165</guid>
		<description><![CDATA[В данной статье рассматривается сбор и вывод информации о загруженности процессора сервера под FreeBSD. Для сбора статистики используется утилита snmpget из состава пакета net-snmp (/usr/ports/net-mgmt/net-snmp). Для хранения информации и генерации графиков, используется пакет rrdtool (round robin database tool). Закачать пакет можно отсюда: http://rrdtool.eu.org или http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/ Подробно ознакомиться с этим пакетом можно здесь: http://www.bog.pp.ru/work/rrdtool.html (Российская). В [...]]]></description>
			<content:encoded><![CDATA[<p>В данной статье рассматривается сбор и вывод информации о загруженности процессора сервера под FreeBSD.<br />
Для сбора статистики используется утилита snmpget из состава пакета net-snmp (/usr/ports/net-mgmt/net-snmp).<br />
Для хранения информации и генерации графиков, используется пакет rrdtool (round robin database tool). Закачать пакет можно отсюда: <a href="http://rrdtool.eu.org" target="_blank">http://rrdtool.eu.org</a> или <a href="http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/" target="_blank">http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/</a> Подробно ознакомиться с этим пакетом можно здесь: <a href="http://www.bog.pp.ru/work/rrdtool.html" target="_blank">http://www.bog.pp.ru/work/rrdtool.html</a> (Российская). В принципе, скрипт самостоятельно создаст необходимые базы так, что дополнительных знаний не нужно.</p>
<p><span id="more-165"></span>Скрипт для сбора статистики по CPU.<br />
Данный скрипт собирает статистику  по нескольким параметрам загруженности CPU.<br />
<strong>User</strong> – загрузка процессора пользовательскими приложениями;<br />
<strong>Nice</strong> – загрузка процессора переназначенными приоритетами пользовательскими приложениями;<br />
<strong>System</strong> – загрузка процессора системными приложениями;<br />
<strong>Idle</strong> – свободные ресурсы процессора;<br />
<strong>Kernel</strong> – загрузка процессора ядром системы;<br />
I<strong>nterrupt</strong> – загрузка процессора программными прерываниями.</p>
<p>&#8212;- START makerrdcpu.sh &#8212;-<br />
<span style="color: #0000ff;">#!/bin/sh<br />
RRDDIR=&raquo;/usr/local/rrd&raquo; #Директория базы данных<br />
CMD=&raquo;/usr/local/bin/snmpget -r 9 -t 3 -Oqv -v2c&raquo; #Команда для сбора статистики по SNMP<br />
RRDCMD=&raquo;/usr/local/bin/rrdtool&raquo;<br />
COMNAME=&raquo;public&raquo; #Комьюнити сервера (серверов)<br />
FILENAME=&raquo;cpu.rrd&raquo; #суффикс файла<br />
CONFIG=&raquo;/usr/local/etc/rrdconf/cpu.conf&raquo;<br />
#OIDs<br />
#ssCpuRawUser .1.3.6.1.4.1.2021.11.50.0<br />
#ssCpuRawNice .1.3.6.1.4.1.2021.11.51.0<br />
#ssCpuRawSystem .1.3.6.1.4.1.2021.11.52.0<br />
#ssCpuRawIdle .1.3.6.1.4.1.2021.11.53.0<br />
#ssCpuRawKernel .1.3.6.1.4.1.2021.11.55.0<br />
#ssCpuRawInterrupt .1.3.6.1.4.1.2021.11.56.0<br />
OID=&raquo;.1.3.6.1.4.1.2021.11.50.0 \<br />
.1.3.6.1.4.1.2021.11.51.0 \<br />
.1.3.6.1.4.1.2021.11.52.0 \<br />
.1.3.6.1.4.1.2021.11.53.0 \<br />
.1.3.6.1.4.1.2021.11.55.0 \<br />
.1.3.6.1.4.1.2021.11.56.0&#8243;<br />
for i in `cat $CONFIG | grep -v &laquo;^#&raquo;`<br />
do<br />
HOST=$i<br />
if [ ! -e "$RRDDIR/$HOST-$FILENAME" ]; then<br />
[ -e "$RRDDIR" ] || mkdir &laquo;$RRDDIR&raquo;<br />
$RRDCMD create &laquo;$RRDDIR/$HOST-$FILENAME&raquo; -s 60\<br />
DS:user:COUNTER:360:0:U\<br />
DS:nice:COUNTER:360:0:U\<br />
DS:sys:COUNTER:360:0:U\<br />
DS:idle:COUNTER:360:0:U\<br />
DS:kernel:COUNTER:360:0:U\<br />
DS:interrupt:COUNTER:360:0:U\<br />
RRA:AVERAGE:0.5:1:1440\<br />
RRA:AVERAGE:0.5:5:1440\<br />
RRA:AVERAGE:0.5:30:1440\<br />
RRA:AVERAGE:0.5:120:1440\<br />
RRA:AVERAGE:0.5:720:1440\<br />
RRA:MAX:0.5:1:1440\<br />
RRA:MAX:0.5:5:1440\<br />
RRA:MAX:0.5:30:1440\<br />
RRA:MAX:0.5:120:1440\<br />
RRA:MAX:0.5:720:1440<br />
fi<br />
STRING=`$CMD -c $COMNAME $HOST $OID | awk &#8216;{printf &laquo;:&raquo;$1}&#8217;`<br />
if [ -w "$RRDDIR/$HOST-$FILENAME" ]; then<br />
$RRDCMD update $RRDDIR/$HOST-$FILENAME N$STRING<br />
else<br />
echo $HOST-$FILENAME is not writable<br />
fi<br />
done</span><br />
&#8212;- END makerrdcpu.sh &#8212;-</p>
<p>IP адреса или имена хостов с которых нужно собирать статистику храняться в файле определяемом перменной CONFIG<br />
Пример файла конфигурации:</p>
<p>&#8212;- START cpu.conf &#8212;<br />
<span style="color: #0000ff;">192.168.0.1<br />
mail.maindomain.ru<br />
fw</span><br />
&#8212;- END cpu.conf &#8212;</p>
<p>Скрипт создает в папке определенной переменной RRDDIR файл базы для каждого хоста.<br />
Мя файла формируется из IP/Имени хоста полученного из файла конфигурации и суффикса заданного переменной FILENAME<br />
Для нашего примера в папке /usr/local/rrd будут созданы файлы:<br />
192.168.0.1-cpu.rrd<br />
mail.maindomain.ru-cpu.rrd<br />
fw-cpu.rrd<br />
Скрипт нужно запускать cron-ом раз в минуту.<br />
Для этого добавляем в cron строку</p>
<p><span style="color: #0000ff;">*/1 * * * *     /usr/local/etc/rc.d/makerrdcpu.sh</span></p>
<p>Вывод информации.<br />
Для вывода информации используется perl-скрипт cpu.cgi<br />
В переменной $rrddir необходимо указать путь к вашим базам. Значение переменной $rrddir должно совпадать со значением переменной RRDDIR из скрипта сбора статистики.<br />
Для вывода надписай используется ttf шрифт /usr/lib/fonts/arial.ttf</p>
<p>&#8212;- START cpu.cgi &#8212;-<br />
<span style="color: #0000ff;">#!/usr/local/bin/perl -w<br />
use RRDs;<br />
use CGI qw(:standard);<br />
use Math::Round qw(:all);<br />
$rrddir=&raquo;/usr/local/rrd&raquo;;<br />
my (@DEF, @FETCH_DEF, @PLOT, @options);<br />
my $statfmt = &laquo;%.1lf%%&raquo;;<br />
$|=1;<br />
print header(&#8216;image/gif&#8217;);<br />
$database = param(&#8216;DS&#8217;);<br />
push (@FETCH_DEF, &laquo;$rrddir/$database&raquo;,<br />
&laquo;AVERAGE&raquo;, &laquo;-s&raquo;, param(&#8216;start&#8217;));<br />
push(@DEF, &laquo;DEF:CP_USER=$rrddir/$database:user:AVERAGE&raquo;);<br />
push(@DEF, &laquo;DEF:CP_NICE=$rrddir/$database:nice:AVERAGE&raquo;);<br />
push(@DEF, &laquo;DEF:CP_SYS=$rrddir/$database:sys:AVERAGE&raquo;);<br />
push(@DEF, &laquo;DEF:CP_IDLE=$rrddir/$database:idle:AVERAGE&raquo;);<br />
push(@DEF, &laquo;DEF:CP_INTER=$rrddir/$database:interrupt:AVERAGE&raquo;);<br />
push(@DEF, &laquo;CDEF:SUM=CP_USER,CP_NICE,+,CP_SYS,+,CP_IDLE,+,CP_INTER,+&raquo;);<br />
push(@DEF, &laquo;CDEF:USER=CP_USER,100,*,SUM,/&raquo;);<br />
push(@DEF, &laquo;CDEF:NICE=CP_NICE,100,*,SUM,/&raquo;);<br />
push(@DEF, &laquo;CDEF:SYS=CP_SYS,100,*,SUM,/&raquo;);<br />
push(@DEF, &laquo;CDEF:IDLE=CP_IDLE,100,*,SUM,/&raquo;);<br />
push(@DEF, &laquo;CDEF:INTER=CP_INTER,100,*,SUM,/&raquo;);<br />
push(@DEF, &laquo;CDEF:TUSE=USER,SYS,+,NICE,+,INTER,+&raquo;);<br />
push(@PLOT,<br />
&laquo;COMMENT:Legend          &laquo;,<br />
&laquo;AREA:TUSE#DE48EC&raquo;,<br />
&laquo;AREA:SYS#EA644A&raquo;,<br />
&laquo;AREA:USER#54EC48&#8243;,<br />
&laquo;AREA:INTER#7648EC&raquo;,<br />
&laquo;LINE1:USER#24BC14:User  &laquo;,<br />
&laquo;LINE1:NICE#CC7016:Nice  &laquo;,<br />
&laquo;LINE1:SYS#CC3118:System  &laquo;,<br />
&laquo;LINE1:INTER#4D18E4:Interrupt    &laquo;,<br />
&laquo;LINE1:TUSE#B415C7:Total&raquo;,<br />
&#8216;COMMENT:\n&#8217;);<br />
push(@PLOT,<br />
&laquo;GPRINT:USER:LAST:Now            ${statfmt} user &laquo;,<br />
&laquo;GPRINT:NICE:LAST:${statfmt} nice &laquo;,<br />
&laquo;GPRINT:SYS:LAST:${statfmt} sys &laquo;,<br />
&laquo;GPRINT:INTER:LAST:${statfmt} inter &laquo;,<br />
&laquo;GPRINT:TUSE:LAST:${statfmt} total &laquo;,<br />
&laquo;GPRINT:IDLE:LAST:${statfmt} idle &laquo;,<br />
&#8216;COMMENT:\n&#8217;);<br />
push(@PLOT,<br />
&laquo;GPRINT:USER:AVERAGE:Average     ${statfmt} user &laquo;,<br />
&laquo;GPRINT:NICE:AVERAGE:${statfmt} nice &laquo;,<br />
&laquo;GPRINT:SYS:AVERAGE:${statfmt} sys &laquo;,<br />
&laquo;GPRINT:INTER:AVERAGE:${statfmt} inter&raquo;,<br />
&laquo;GPRINT:TUSE:AVERAGE:${statfmt} total &laquo;,<br />
&laquo;GPRINT:IDLE:AVERAGE:${statfmt} idle&raquo;,<br />
&#8216;COMMENT:\n&#8217;);<br />
push(@PLOT,<br />
&laquo;GPRINT:USER:MAX:Max             ${statfmt} user&raquo;,<br />
&laquo;GPRINT:NICE:MAX:${statfmt} nice &laquo;,<br />
&laquo;GPRINT:SYS:MAX:${statfmt} sys &laquo;,<br />
&laquo;GPRINT:INTER:MAX:${statfmt} inter &laquo;,<br />
&laquo;GPRINT:TUSE:MAX:${statfmt} total &laquo;,<br />
&laquo;GPRINT:IDLE:MAX:${statfmt} idle &laquo;,<br />
&#8216;COMMENT:\n&#8217;);<br />
foreach $opt (&#8216;start&#8217;,'title&#8217;) {<br />
if (param($opt)) {<br />
push(@options, &laquo;&#8211;${opt}&raquo;, param($opt));<br />
}<br />
}</span></p>
<p><span style="color: #0000ff;">push(@options, &laquo;&#8211;width&raquo;,&raquo;450&#8243;,&raquo;&#8211;height&raquo;,&raquo;240&#8243;);<br />
push(@options, &laquo;&#8211;vertical-label&raquo;,&raquo;percents&raquo;);<br />
push(@options, &laquo;&#8211;lower-limit&raquo;,&raquo;1&#8243;);<br />
push(@options, &laquo;&#8211;upper-limit&raquo;,&raquo;100&#8243;);<br />
push(@options, &laquo;&#8211;font&raquo;,&raquo;DEFAULT:8:/usr/lib/fonts/arial.ttf&raquo;);<br />
RRDs::graph(&#8216;-&#8217;,@options,@DEF,@PLOT);<br />
exit 0;<br />
&#8212;- END cpu.cgi &#8212;-</span></p>
<p>Вызов скрипта осуществляется с передачей ему в качестве параметров:<br />
<strong>DS</strong> – имя базы данных<br />
<strong>title</strong> – заголовок графика<br />
start – начальная позиция времени по оси Х (смещение относительно опорного времени)<br />
* в одно смещение можно конкатенировать несколько единиц &#8211; 1h30m;<br />
* можно использовать несколько смещений &#8211; -6h+15min;<br />
* знак (+ или -)<br />
* число<br />
* единица измерения (years, months, weeks, days, hours, minutes, seconds). Можно сокращать вплоть до одной буквы. Чтобы понять, что означает буква m &#8211; минуты или месяца программе приходится читать мысли <img src='http://ctpahhuk.ru/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Напрмр при запросе:<br />
cpu.cgi?DS= mail.maindomain.ru-cpu.rrd&amp;title=6%20hour%20graph&amp;start=-6h<br />
Будет выведен график из базы mail.maindomain.ru-cpu.rrd с заголовком 6 hour graph за 6 частов.<br />
Что каким цветом показывается, понятно из легенды под графиком.<br />
Легенда содержит три строки с данными.<br />
1. Last – последнее (текущее) значение.<br />
2. Average – среднее значение за показанный на графике период<br />
3. Max – максимальное значение за показанный период.</p>
<div id="attachment_167" class="wp-caption alignnone" style="width: 557px"><a href="http://xn--80aqgkapgi.net/wp-content/uploads/2009/12/rrd1.jpg"><img class="size-full wp-image-167" title="rrd1" src="http://xn--80aqgkapgi.net/wp-content/uploads/2009/12/rrd1.jpg" alt="Рисунок 1. График использования CPU." width="547" height="361" /></a><p class="wp-caption-text">Рисунок 1. График использования CPU.</p></div>
]]></content:encoded>
			<wfw:commentRss>http://ctpahhuk.ru/archives/165/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

