[-]
[+]
|
Changed |
nagios-mod_gearman.changes
|
|
[-]
[+]
|
Changed |
nagios-mod_gearman.spec
^
|
|
[-]
[+]
|
Added |
mod_gearman-worker-config.patch
^
|
@@ -0,0 +1,15 @@
+--- extras/standalone_worker.conf.orig 2011-01-29 16:57:12.750005736 +0100
++++ extras/standalone_worker.conf 2011-01-29 17:09:09.834288554 +0100
+@@ -77,10 +77,10 @@
+ #identifier=hostname
+
+ # Path to the pidfile.
+-pidfile=./worker.pid
++pidfile=/var/run/mod_gearman/mod_gearman_worker.pid
+
+ # Path to the logfile.
+-logfile=./worker.log
++logfile=/var/log/mod_gearman_worker/worker.log
+
+ # Minimum number of worker processes which should
+ # run at any time.
|
[-]
[+]
|
Deleted |
mod_gearman-0.8.tar.bz2/README.html
^
|
@@ -1,2186 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
- "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-<meta name="generator" content="AsciiDoc 8.5.2" />
-<title>Gearman Module for Nagios</title>
-<style type="text/css">
-/* Debug borders */
-p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
-/*
- border: 1px solid red;
-*/
-}
-
-body {
- margin: 1em 5% 1em 5%;
-}
-
-a {
- color: blue;
- text-decoration: underline;
-}
-a:visited {
- color: fuchsia;
-}
-
-em {
- font-style: italic;
- color: navy;
-}
-
-strong {
- font-weight: bold;
- color: #083194;
-}
-
-tt {
- color: navy;
-}
-
-h1, h2, h3, h4, h5, h6 {
- color: #527bbd;
- font-family: sans-serif;
- margin-top: 1.2em;
- margin-bottom: 0.5em;
- line-height: 1.3;
-}
-
-h1, h2, h3 {
- border-bottom: 2px solid silver;
-}
-h2 {
- padding-top: 0.5em;
-}
-h3 {
- float: left;
-}
-h3 + * {
- clear: left;
-}
-
-div.sectionbody {
- font-family: serif;
- margin-left: 0;
-}
-
-hr {
- border: 1px solid silver;
-}
-
-p {
- margin-top: 0.5em;
- margin-bottom: 0.5em;
-}
-
-ul, ol, li > p {
- margin-top: 0;
-}
-
-pre {
- padding: 0;
- margin: 0;
-}
-
-span#author {
- color: #527bbd;
- font-family: sans-serif;
- font-weight: bold;
- font-size: 1.1em;
-}
-span#email {
-}
-span#revnumber, span#revdate, span#revremark {
- font-family: sans-serif;
-}
-
-div#footer {
- font-family: sans-serif;
- font-size: small;
- border-top: 2px solid silver;
- padding-top: 0.5em;
- margin-top: 4.0em;
-}
-div#footer-text {
- float: left;
- padding-bottom: 0.5em;
-}
-div#footer-badges {
- float: right;
- padding-bottom: 0.5em;
-}
-
-div#preamble {
- margin-top: 1.5em;
- margin-bottom: 1.5em;
-}
-div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
-div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
-div.admonitionblock {
- margin-top: 1.0em;
- margin-bottom: 1.5em;
-}
-div.admonitionblock {
- margin-top: 2.0em;
- margin-bottom: 2.0em;
- margin-right: 10%;
- color: #606060;
-}
-
-div.content { /* Block element content. */
- padding: 0;
-}
-
-/* Block element titles. */
-div.title, caption.title {
- color: #527bbd;
- font-family: sans-serif;
- font-weight: bold;
- text-align: left;
- margin-top: 1.0em;
- margin-bottom: 0.5em;
-}
-div.title + * {
- margin-top: 0;
-}
-
-td div.title:first-child {
- margin-top: 0.0em;
-}
-div.content div.title:first-child {
- margin-top: 0.0em;
-}
-div.content + div.title {
- margin-top: 0.0em;
-}
-
-div.sidebarblock > div.content {
- background: #ffffee;
- border: 1px solid silver;
- padding: 0.5em;
-}
-
-div.listingblock > div.content {
- border: 1px solid silver;
- background: #f4f4f4;
- padding: 0.5em;
-}
-
-div.quoteblock, div.verseblock {
- padding-left: 1.0em;
- margin-left: 1.0em;
- margin-right: 10%;
- border-left: 5px solid #dddddd;
- color: #777777;
-}
-
-div.quoteblock > div.attribution {
- padding-top: 0.5em;
- text-align: right;
-}
-
-div.verseblock > div.content {
- white-space: pre;
-}
-div.verseblock > div.attribution {
- padding-top: 0.75em;
- text-align: left;
-}
-/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
-div.verseblock + div.attribution {
- text-align: left;
-}
-
-div.admonitionblock .icon {
- vertical-align: top;
- font-size: 1.1em;
- font-weight: bold;
- text-decoration: underline;
- color: #527bbd;
- padding-right: 0.5em;
-}
-div.admonitionblock td.content {
- padding-left: 0.5em;
- border-left: 3px solid #dddddd;
-}
-
-div.exampleblock > div.content {
- border-left: 3px solid #dddddd;
- padding-left: 0.5em;
-}
-
-div.imageblock div.content { padding-left: 0; }
-span.image img { border-style: none; }
-a.image:visited { color: white; }
-
-dl {
- margin-top: 0.8em;
- margin-bottom: 0.8em;
-}
-dt {
- margin-top: 0.5em;
- margin-bottom: 0;
- font-style: normal;
- color: navy;
-}
-dd > *:first-child {
- margin-top: 0.1em;
-}
-
-ul, ol {
- list-style-position: outside;
-}
-ol.arabic {
- list-style-type: decimal;
-}
-ol.loweralpha {
- list-style-type: lower-alpha;
-}
-ol.upperalpha {
- list-style-type: upper-alpha;
-}
-ol.lowerroman {
- list-style-type: lower-roman;
-}
-ol.upperroman {
- list-style-type: upper-roman;
-}
-
-div.compact ul, div.compact ol,
-div.compact p, div.compact p,
-div.compact div, div.compact div {
- margin-top: 0.1em;
- margin-bottom: 0.1em;
-}
-
-div.tableblock > table {
- border: 3px solid #527bbd;
-}
-thead, p.table.header {
- font-family: sans-serif;
- font-weight: bold;
-}
-tfoot {
- font-weight: bold;
-}
-td > div.verse {
- white-space: pre;
-}
-p.table {
- margin-top: 0;
-}
-/* Because the table frame attribute is overriden by CSS in most browsers. */
-div.tableblock > table[frame="void"] {
- border-style: none;
-}
-div.tableblock > table[frame="hsides"] {
- border-left-style: none;
- border-right-style: none;
-}
-div.tableblock > table[frame="vsides"] {
- border-top-style: none;
- border-bottom-style: none;
-}
-
-
-div.hdlist {
- margin-top: 0.8em;
- margin-bottom: 0.8em;
-}
-div.hdlist tr {
- padding-bottom: 15px;
-}
-dt.hdlist1.strong, td.hdlist1.strong {
- font-weight: bold;
-}
-td.hdlist1 {
- vertical-align: top;
- font-style: normal;
- padding-right: 0.8em;
- color: navy;
-}
-td.hdlist2 {
- vertical-align: top;
-}
-div.hdlist.compact tr {
- margin: 0;
- padding-bottom: 0;
-}
-
-.comment {
- background: yellow;
-}
-
-.footnote, .footnoteref {
- font-size: 0.8em;
-}
-
-span.footnote, span.footnoteref {
- vertical-align: super;
-}
-
-#footnotes {
- margin: 20px 0 20px 0;
- padding: 7px 0 0 0;
-}
-
-#footnotes div.footnote {
- margin: 0 0 5px 0;
-}
-
-#footnotes hr {
- border: none;
- border-top: 1px solid silver;
- height: 1px;
- text-align: left;
- margin-left: 0;
- width: 20%;
- min-width: 100px;
-}
-
-
-@media print {
- div#footer-badges { display: none; }
-}
-
-div#toc {
- margin-bottom: 2.5em;
-}
-
-div#toctitle {
- color: #527bbd;
- font-family: sans-serif;
- font-size: 1.1em;
- font-weight: bold;
- margin-top: 1.0em;
- margin-bottom: 0.1em;
-}
-
-div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
- margin-top: 0;
- margin-bottom: 0;
-}
-div.toclevel2 {
- margin-left: 2em;
- font-size: 0.9em;
-}
-div.toclevel3 {
- margin-left: 4em;
- font-size: 0.9em;
-}
-div.toclevel4 {
- margin-left: 6em;
- font-size: 0.9em;
-}
-/* Workarounds for IE6's broken and incomplete CSS2. */
-
-div.sidebar-content {
- background: #ffffee;
- border: 1px solid silver;
- padding: 0.5em;
-}
-div.sidebar-title, div.image-title {
- color: #527bbd;
- font-family: sans-serif;
- font-weight: bold;
- margin-top: 0.0em;
- margin-bottom: 0.5em;
-}
-
-div.listingblock div.content {
- border: 1px solid silver;
- background: #f4f4f4;
- padding: 0.5em;
-}
-
-div.quoteblock-attribution {
- padding-top: 0.5em;
- text-align: right;
-}
-
-div.verseblock-content {
- white-space: pre;
-}
-div.verseblock-attribution {
- padding-top: 0.75em;
- text-align: left;
-}
-
-div.exampleblock-content {
- border-left: 3px solid #dddddd;
- padding-left: 0.5em;
-}
-
-/* IE6 sets dynamically generated links as visited. */
-div#toc a:visited { color: blue; }
-</style>
-<script type="text/javascript">
-/*<![CDATA[*/
-window.onload = function(){asciidoc.footnotes(); asciidoc.toc(2);}
-var asciidoc = { // Namespace.
-
-/////////////////////////////////////////////////////////////////////
-// Table Of Contents generator
-/////////////////////////////////////////////////////////////////////
-
-/* Author: Mihai Bazon, September 2002
- * http://students.infoiasi.ro/~mishoo
- *
- * Table Of Content generator
- * Version: 0.4
- *
- * Feel free to use this script under the terms of the GNU General Public
- * License, as long as you do not remove or alter this notice.
- */
-
- /* modified by Troy D. Hanson, September 2006. License: GPL */
- /* modified by Stuart Rackham, 2006, 2009. License: GPL */
-
-// toclevels = 1..4.
-toc: function (toclevels) {
-
- function getText(el) {
- var text = "";
- for (var i = el.firstChild; i != null; i = i.nextSibling) {
- if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
- text += i.data;
- else if (i.firstChild != null)
- text += getText(i);
- }
- return text;
- }
-
- function TocEntry(el, text, toclevel) {
- this.element = el;
- this.text = text;
- this.toclevel = toclevel;
- }
-
- function tocEntries(el, toclevels) {
- var result = new Array;
- var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
- // Function that scans the DOM tree for header elements (the DOM2
- // nodeIterator API would be a better technique but not supported by all
- // browsers).
- var iterate = function (el) {
- for (var i = el.firstChild; i != null; i = i.nextSibling) {
- if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
- var mo = re.exec(i.tagName);
- if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
- result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
- }
- iterate(i);
- }
- }
- }
- iterate(el);
- return result;
- }
-
- var toc = document.getElementById("toc");
- var entries = tocEntries(document.getElementById("content"), toclevels);
- for (var i = 0; i < entries.length; ++i) {
- var entry = entries[i];
- if (entry.element.id == "")
- entry.element.id = "_toc_" + i;
- var a = document.createElement("a");
- a.href = "#" + entry.element.id;
- a.appendChild(document.createTextNode(entry.text));
- var div = document.createElement("div");
- div.appendChild(a);
- div.className = "toclevel" + entry.toclevel;
- toc.appendChild(div);
- }
- if (entries.length == 0)
- toc.parentNode.removeChild(toc);
-},
-
-
-/////////////////////////////////////////////////////////////////////
-// Footnotes generator
-/////////////////////////////////////////////////////////////////////
-
-/* Based on footnote generation code from:
- * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
- */
-
-footnotes: function () {
- var cont = document.getElementById("content");
- var noteholder = document.getElementById("footnotes");
- var spans = cont.getElementsByTagName("span");
- var refs = {};
- var n = 0;
- for (i=0; i<spans.length; i++) {
- if (spans[i].className == "footnote") {
- n++;
- // Use [\s\S] in place of . so multi-line matches work.
- // Because JavaScript has no s (dotall) regex flag.
- note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
- noteholder.innerHTML +=
- "<div class='footnote' id='_footnote_" + n + "'>" +
- "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
- n + "</a>. " + note + "</div>";
- spans[i].innerHTML =
- "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
- "' title='View footnote' class='footnote'>" + n + "</a>]";
- var id =spans[i].getAttribute("id");
- if (id != null) refs["#"+id] = n;
- }
- }
- if (n == 0)
- noteholder.parentNode.removeChild(noteholder);
- else {
- // Process footnoterefs.
- for (i=0; i<spans.length; i++) {
- if (spans[i].className == "footnoteref") {
- var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
- href = href.match(/#.*/)[0]; // Because IE return full URL.
- n = refs[href];
- spans[i].innerHTML =
- "[<a href='#_footnote_" + n +
- "' title='View footnote' class='footnote'>" + n + "</a>]";
- }
- }
- }
-}
-
-}
-/*]]>*/
-</script>
-</head>
-<body style="max-width:800">
-<div id="header">
-<h1>Gearman Module for Nagios</h1>
-<div id="toc">
- <div id="toctitle">Table of Contents</div>
- <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
-</div>
-</div>
-<div id="content">
-<div id="preamble">
-<div class="sectionbody">
-<div class="paragraph"><p>Mod_Gearman (<a href="http://labs.consol.de/nagios/mod-gearman">http://labs.consol.de/nagios/mod-gearman</a>) is a new
-way of distributing active Nagios checks across your network. It
-consists of two parts: There is a NEB module which resides in the
-Nagios core and adds servicechecks, hostchecks and eventhandler to a
-Gearman (<a href="http://gearman.org">http://gearman.org</a>) queue. There can be multiple equal
-gearman servers. The counterpart is one or more worker clients for
-the checks itself. They can be bound to host and servicegroups.</p></div>
-</div>
-</div>
-<h2 id="_how_does_it_work">How does it work</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>When the broker module is loaded, it captures all servicecheck,
-hostcheck and the eventhandler events. Eventhandler are sent to a
-generic <em>eventhandler</em> queue. Checks for hosts which are in one of the
-specified hostgroups, are sent into a seperate hostgroup queue. All
-non matching hosts are sent to a generic <em>hosts</em> queue. Checks for
-services are first checked against the list of servicegroups, then
-against the hostgroups and if none matches they will be sent into a
-generic <em>service</em> queue.
-The NEB module starts a single thread, which monitors the
-<em>check_results</em> where all results come in.</p></div>
-<div class="paragraph"><p><span class="image">
-<img alt="Workflow" src="data:image/png;base64,
-iVBORw0KGgoAAAANSUhEUgAAA8AAAAJYCAMAAACaSn8zAAAAAXNSR0IArs4c6QAAAitQTFRFAAAA
-OF2KOF6MOl+NOV6NOmCPPmaXPWSUPmeYPmKOO2KSO2GRPWWWOmCNPmKPP2mcPWeYPGSVP2ibPGOU
-OmCOP2qdTU1NUXGZQGqcQWudS2yVQGiaV3acQGWSQWyfRWqYQ2iVS3GeRWeRXnygQ2+jSHatSXix
-S3qzTH22RnKoTHy1Tn+6Q22hSnmxTX64RHClRnOqSXevRXGmQ26iWH6rUHajR3SrVHimVnupSn67
-Sn25RnavRXWvRXKsSXmzQm2iSny5TH69Q2+mT4G9T4C7XoOyW4CvToG9V4G2ToHDUorOVY7VVI3S
-UYjLToPEUITHTYDAVIvRaGhofHx8aoaocIurfZWzd5CvZIGkaY67a5G+Y4m2YYa0eJ7NbpPCc5nH
-eJ/MYY7Ee6DPfqPSjIyMmpqag5q2iZ+6kKS+m67ElqnBl7TYia/egafVhqzbg6nYjq/VjrTjjLHg
-mrzmvb29srKyp6enqLjLobPIrr3Ppb7dpL7dusfWtMLTvMrbsMbhuc3lvNPuu87lsszsqMXpvNLu
-wcza2dnZ0NDQx8fHx9He09vlzdbi0d7uwtToytnrzN3yxdjx0t/uxNjx2uDp2OPx3+jz3ej32OX1
-0uH02ub20+L05uvw4Obt+fr77PD08PDw4eHh6enp8/X4+vz96vD39fj75ez18PT58vb8/P3+4uz4
-9fn9+Pv95u/56vH67vT76O/26/L6+vz+8PX74Or35u759fj9////L4QIjwAAAAFiS0dEAIgFHUgA
-AAAJcEhZcwAADsQAAA7EAZUrDhsAAAAHdElNRQfaCQ4JAhpSOyDcAAAgAElEQVR42u2d+WMc5Znn
-q+xBYJzZYzLbBoclu7YQ5owDs9llM8lkVt7ZJUomG7UN7DE5diQHodmdMGq1iQLbIpKRBJYsMBZg
-G6OWJVs+wETn++fte9TVrVbf1V3H5/uDuqrft0vP877vp96z6rUEQii2skgChAAYIQTACCEARgiA
-EUIAjBACYIQQACMEwAghAEYIATBCAIwQAmCEEAAjhAAYIQBGCAEwQgiAEUIAjBAAI4QAGCEEwAgB
-MEIIgBFCAIwQAuB6de3cyNnTCJXpzMhbnwNw1PX5yHEboX105PWPATjKle8rlFFUXac/AOCI6vrr
-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
-SPly1XmHYgAAAABJRU5ErkJggg==" />
-</span></p></div>
-<div class="paragraph"><p>A simple example queue would look like:</p></div>
-<div class="exampleblock">
-<div class="exampleblock-content">
-<div class="literalblock">
-<div class="content">
-<pre><tt>+---------------+------------------+--------------+--------------+
-| Queue Name | Worker Available | Jobs Waiting | Jobs Running |
-+---------------+------------------+--------------+--------------+
-| check_results | 1 | 0 | 0 |
-| host | 50 | 0 | 1 |
-| service | 50 | 0 | 13 |
-| eventhandler | 50 | 0 | 0 |
-+---------------+------------------+--------------+--------------+</tt></pre>
-</div></div>
-</div></div>
-<div class="paragraph"><p>There is one queue for the results and two for the checks plus the
-eventhandler.</p></div>
-<div class="paragraph"><p>The workflow is simple:</p></div>
-<div class="olist arabic"><ol class="arabic">
-<li>
-<p>
-Nagios wants to execute a service check.
-</p>
-</li>
-<li>
-<p>
-The check is intercepted by the mod_gearman neb module.
-</p>
-</li>
-<li>
-<p>
-mod_gearman puts the job into the <em>service</em> queue.
-</p>
-</li>
-<li>
-<p>
-a worker grabs the job and puts back the result into the
- <em>check_results</em> queue
-</p>
-</li>
-<li>
-<p>
-mod_gearman grabs the result job and puts back the result onto the
- check result list
-</p>
-</li>
-<li>
-<p>
-The reaper reads all checks from the result list and updates hosts / services
-</p>
-</li>
-</ol></div>
-<div class="paragraph"><p>You can set some host or servicegroups for special worker. This
-example uses a seperate hostgroup for Japan and a seperate
-servicegroup for jmx4perl.</p></div>
-<div class="paragraph"><p>It would look like this:</p></div>
-<div class="exampleblock">
-<div class="exampleblock-content">
-<div class="literalblock">
-<div class="content">
-<pre><tt>+-----------------------+------------------+--------------+--------------+
-| Queue Name | Worker Available | Jobs Waiting | Jobs Running |
-+-----------------------+------------------+--------------+--------------+
-| check_results | 1 | 0 | 0 |
-| host | 50 | 0 | 1 |
-| service | 50 | 0 | 13 |
-| servicegroup_jmx4perl | 3 | 0 | 3 |
-| hostgroup_japan | 3 | 1 | 3 |
-| eventhandler | 50 | 0 | 0 |
-+-----------------------+------------------+--------------+--------------+</tt></pre>
-</div></div>
-</div></div>
-<div class="paragraph"><p>You still have the generic queues and in addition there are two queues
-for the specific groups.</p></div>
-<div class="paragraph"><p>The worker processes will take jobs from the queues and put the result
-back into the check_result queue which will then be taken back by the
-neb module and put back into the nagios core. A worker can work on one
-or more queues. So you could start a worker which only handles the
-<em>hostgroup_japan</em> group. One worker for the <em>jmx4perl</em> checks and one
-worker which covers the other queues. There can be more than one
-worker on each queue to share the load.</p></div>
-</div>
-<h2 id="_installation">Installation</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>Pre Requirements:</p></div>
-<div class="ulist"><ul>
-<li>
-<p>
-gcc / g++
-</p>
-</li>
-<li>
-<p>
-autoconf / automake / autoheader
-</p>
-</li>
-<li>
-<p>
-libtool
-</p>
-</li>
-<li>
-<p>
-libgearman (>= 0.14)
-</p>
-</li>
-</ul></div>
-<div class="paragraph"><p>Download the tarball and perform the following steps:</p></div>
-<div class="literalblock">
-<div class="content">
-<pre><tt> #> ./configure
- #> make
- #> make install</tt></pre>
-</div></div>
-<div class="paragraph"><p>Then add the mod_gearman.o to your nagios installation and add a
-broker line to your nagios.cfg:</p></div>
-<div class="exampleblock">
-<div class="exampleblock-content">
-<div class="literalblock">
-<div class="content">
-<pre><tt>broker_module=.../mod_gearman.o server=localhost:4730 eventhandler=yes services=yes hosts=yes</tt></pre>
-</div></div>
-</div></div>
-<div class="paragraph"><p>see <a href="#_configuration">Configuration</a> for details on all parameters</p></div>
-<div class="paragraph"><p>The last step is to start one or more worker. You may use the same
-configuration file as for the neb module.</p></div>
-<div class="exampleblock">
-<div class="exampleblock-content">
-<div class="literalblock">
-<div class="content">
-<pre><tt>./mod_gearman_worker --server=localhost:4730 --services --hosts</tt></pre>
-</div></div>
-</div></div>
-<div class="paragraph"><p>or use the supplied init script.</p></div>
-<div class="admonitionblock">
-<table><tr>
-<td class="icon">
-<img alt="Note" src="data:image/png;base64,
-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" />
-</td>
-<td class="content">Make sure you have started your gearmand job server. Usually
-it can be started with</td>
-</tr></table>
-</div>
-<div class="exampleblock">
-<div class="exampleblock-content">
-<div class="literalblock">
-<div class="content">
-<pre><tt>/usr/sbin/gearmand -t 10 -j 0</tt></pre>
-</div></div>
-</div></div>
-<div class="paragraph"><p>or a supplied init script (extras/gearmand-init).</p></div>
-<h3 id="_patch_nagios">Patch Nagios</h3><div style="clear:left"></div>
-<div class="admonitionblock">
-<table><tr>
-<td class="icon">
-<img alt="Note" src="data:image/png;base64,
-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" />
-</td>
-<td class="content">The needed patch is already included since Nagios 3.2.2. Use the patch if you
-use an older version.</td>
-</tr></table>
-</div>
-<div class="paragraph"><p>It is not possible to distribute eventhandler with Nagios versions
-prior 3.2.2. Just apply the patch from the patches directory to your
-Nagios sources and build Nagios again if you want to use an older
-version. You only need to replace the nagios binary. Nothing else has
-changed. If you plan to distribute only Host/Servicechecks, no patch
-is needed.</p></div>
-</div>
-<h2 id="_configuration">Configuration</h2>
-<div class="sectionbody">
-<h3 id="_neb_module">NEB Module</h3><div style="clear:left"></div>
-<div class="paragraph"><p>A sample broker in your nagios.cfg could look like:</p></div>
-<div class="exampleblock">
-<div class="exampleblock-content">
-<div class="literalblock">
-<div class="content">
-<pre><tt>broker_module=/usr/local/share/nagios/mod_gearman.o keyfile=/usr/local/share/nagios/secret.txt server=localhost eventhandler=yes hosts=yes services=yes</tt></pre>
-</div></div>
-</div></div>
-<div class="paragraph"><p>See the following list for a detailed explaination of available
-options:</p></div>
-<div class="paragraph"><p>Shared options for worker and the NEB module:</p></div>
-<div class="literalblock">
-<div class="content">
-<pre><tt>config: read config from this file. Options are the same
- like described here.
-
- Example: config=/etc/nagios3/mod_gm_worker.conf
-
-
-debug: use debug to increase the verbosity of the module.
- Possible values are:
- 0 = only errors
- 1 = debug messages
- 2 = trace messages
- 3 = trace and all gearman related logs are going to stdout.
- Default is 0.
-
- Example: debug=1
-
-
-server: sets the addess of your gearman job server. Can be specified
- more than once to add more server.
-
- Example: server=localhost:4730,remote_host:4730
-
-
-eventhandler: defines if the module should distribute execution of
- eventhandlers.
-
- Example: eventhandler=yes
-
-
-services: defines if the module should distribute execution of
- service checks.
-
- Example: services=yes
-
-
-hosts: defines if the module should distribute execution of
- host checks.
-
- Example: hosts=yes
-
-
-hostgroups: sets a list of hostgroups which will go into seperate
- queues.
-
- Example: hostgroups=name1,name2,name3
-
-
-servicegroups: sets a list of servicegroups which will go into seperate
- queues.
-
- Example: servicegroups=name1,name2,name3
-
-
-encryption: enables or disables encryption. It is strongly
- advised to not disable encryption. Anybody will be
- able to inject packages to your worker.
- Encryption is enabled by default and you have to
- explicitly disable it.
- When using encryption, you will either have to
- specify a shared password with key=... or a
- keyfile with keyfile=...
- Default is On.
-
- Example: encryption=yes
-
-
-key: A shared password which will be used for
- encryption of data pakets. Should be at least 8
- bytes long. Maximum length is 32 characters.
-
- Example: key=secret
-
-
-keyfile: The shared password will be read from this file.
- Use either key or keyfile. Only the first 32
- characters will be used.
-
- Example: keyfile=/path/to/secret.file</tt></pre>
-</div></div>
-<div class="paragraph"><p>Additional options for the NEB module:</p></div>
-<div class="literalblock">
-<div class="content">
-<pre><tt>localhostgroups: sets a list of hostgroups which will not be executed
- by gearman. They are just passed through.
-
- Example: localhostgroups=name1,name2,name3
-
-
-localservicegroups: sets a list of servicegroups which will not be executed
- by gearman. They are just passed through.
-
- Example: localservicegroups=name1,name2,name3
-
-
-result_workers Number of result worker threads. Usually one is
- enough. You may increase the value if your
- result queue is not processed fast enough.
-
- Example: result_workers=3
-
-
-perfdata: defines if the module should distribute perfdata
- to gearman.
- Note: processing of perfdata is not part of
- mod_gearman. You will need additional worker for
- handling performance data. For example: pnp4nagios
- Performance data is just written to the gearman
- queue.
-
- Example: perfdata=yes
-
-result_queue: sets the result queue. Necessary when putting jobs
- from several nagios instances into the same
- gearman queues.
- Default: check_results
-
- Example: result_queue=check_results_nagios1</tt></pre>
-</div></div>
-<div class="paragraph"><p>Additional options for worker:</p></div>
-<div class="literalblock">
-<div class="content">
-<pre><tt>identifier: Identifier for this worker. Will be used for the
- 'worker_identifier' queue for status requests. You
- may want to change it if you are using more than
- one worker on a single host.
- Default: current hostname
-
- Example: identifier=hostname_test
-
-
-pidfile: Path to the pidfile.
-
- Example: pidfile=/path/to/pid.file
-
-
-logfile: Path to the logfile.
-
- Example: logfile=/path/to/log.file
-
-
-min-worker: Minimum number of worker processes which should
- run at any time.
- Default: 1
-
- Example: min-worker=1
-
-
-max-worker: Maximum number of worker processes which should
- run at any time. You may set this equal to
- min-worker setting to disable dynamic starting of
- workers. When setting this to 1, all services from
- this worker will be executed one after another.
- Default: 20
-
- Example: max-worker=20
-
-
-idle-timeout: Time after which an idling worker exists. This
- parameter controls how fast your waiting workers
- will exit if there are no jobs waiting.
- Default: 10
-
- Example: idle-timeout=30
-
-
-max-jobs: Controls the amount of jobs a worker will do
- before he exits. Use this to control how fast the
- amount of workers will go down after high load
- times.
- Default: 20
-
- Example: max-jobs=50</tt></pre>
-</div></div>
-</div>
-<h2 id="_queue_names">Queue Names</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>You may want to watch your gearman server job queue. The shipped
-tools/queue_top.pl does this. It polls the gearman server every second
-and displays the current queue statistics.</p></div>
-<div class="exampleblock">
-<div class="exampleblock-content">
-<div class="literalblock">
-<div class="content">
-<pre><tt>+-----------------------+--------+-------+-------+---------+
-| Name | Worker | Avail | Queue | Running |
-+-----------------------+--------+-------+-------+---------+
-| check_results | 1 | 1 | 0 | 0 |
-| host | 3 | 3 | 0 | 0 |
-| service | 3 | 3 | 0 | 0 |
-| eventhandler | 3 | 3 | 0 | 0 |
-| servicegroup_jmx4perl | 3 | 3 | 0 | 0 |
-| hostgroup_japan | 3 | 3 | 0 | 0 |
-+-----------------------+--------+-------+-------+---------+</tt></pre>
-</div></div>
-</div></div>
-<div class="literalblock">
-<div class="content">
-<pre><tt>check_results this queue is monitored by the neb module to
- fetch results from the worker.
- You don't need an extra worker for this queue.
- The number of result workers can be set to a
- maximum of 256, but usually one is enough.
- One worker is capable of processing several
- thousand results per second.
-
-
-host This is the queue for generic host checks. If
- you enable host checks with the hosts=yes switch.
- Before a host goes into this queue, it is
- checked if any of the local groups matches or a
- seperate hostgroup machtes. If nothing matches,
- then this queue is used.
-
-
-service This is the queue for generic service checks. If
- you enable service checks with the services=yes
- switch. Before a service goes into this queue
- it is checked against the local host- and
- service-groups. Then the normal host- and
- servicegroups are checked and if none matches,
- this queue is used.
-
-
-hostgroup_<name> This queue is created for every hostgroup which
- has been defined by the hostgroups=... option.
- Make sure you have at least one worker for every
- hostgroup you specify. Start the worker with
- --hostgroups=... to work on hostgroup queues.
- Note that this queue may also contain service
- checks if the hostgroup of a service matches.
-
-
-servicegroup_<name> This queue is created for every servicegroup
- which has been defined by the servicegroup=...
- option.
-
-
-eventhandler This is the generic queue for all eventhandler.
- Make sure you have a worker for this queue if
- you have eventhandler enabled. Start the worker
- with --events to work on this queue.
-
-
-perfdata This is the generic queue for all performance
- data. It is created and used if you switch on
- --perfdata=yes.
- Performance data cannot be processed by the
- gearman worker itself. You will need pnp4nagios
- (http://www.pnp4nagios.org) therefor.</tt></pre>
-</div></div>
-</div>
-<h2 id="_performance">Performance</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>While the main motivation was to ease distributed configuration, this
-plugin also helps to spread the load on multiple worker. Throughput is
-mainly limited by the amount of jobs a single nagios instance can put
-onto the Gearman job server. Keep the Gearman job server close to the
-nagios box. Best practice is to put both on the same machine. Both
-processes will utilize one core. Some testing with my workstation
-(Dual Core 2.50GHz) and two worker boxes gave me these results. I used
-a sample Nagios installation with 20.000 Services at a 1 minute
-interval and a sample plugin which returns just a single line of
-output. I got over 300 Servicechecks per second, which means you could
-easily setup 100.000 services at a 5 minute interval with a single
-nagios box. The amount of worker boxes depends on your check types.</p></div>
-<div class="paragraph"><p><span class="image">
-<img alt="Performance 1" src="data:image/png;base64,
-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
-rkJggg==" />
-</span>
-<span class="image">
-<img alt="Performance 2" src="data:image/png;base64,
-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" />
-</span></p></div>
-</div>
-<h2 id="_how_to_monitor_job_server_and_worker">How to Monitor Job Server and Worker</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>Use the supplied check_gearman to monitor your worker and job server.
-Worker have a own queue for status requests.</p></div>
-<div class="literalblock">
-<div class="content">
-<pre><tt> %> ./check_gearman -H <job server hostname> -q worker_<worker hostname> -t 10 -s check
- check_gearman OK - localhost has 10 worker and is working on 1 jobs|worker=10 running=1 total_jobs_done=1508</tt></pre>
-</div></div>
-<div class="paragraph"><p>This will send a test job to the given job server and the worker will
-respond with some statistical data.</p></div>
-<div class="paragraph"><p>Job server can be monitored with:</p></div>
-<div class="literalblock">
-<div class="content">
-<pre><tt> %> ./check_gearman -H localhost -t 20
- check_gearman OK - 6 jobs running and 0 jobs waiting.|check_results=0;0;1;10;100 host=0;0;9;10;100 service=0;6;9;10;100</tt></pre>
-</div></div>
-</div>
-<h2 id="_how_to_submit_passive_checks">How to Submit Passive Checks</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>You can use send_gearman to submit active and passive checks to a
-gearman job server where they will be processed just like a finished
-check would do.</p></div>
-<div class="literalblock">
-<div class="content">
-<pre><tt> %> ./send_gearman --server=<job server> --encryption=no --host="<hostname>" --service="<service>" --message="message"</tt></pre>
-</div></div>
-</div>
-<h2 id="_how_to_submit_check_multi_results">How to Submit check_multi Results</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>check_multi is a plugin which executes multiple child checks.
-See more details about the feed_passive mode at:
-<a href="http://www.my-plugin.de/wiki/projects/check_multi/feed_passive">http://www.my-plugin.de/wiki/projects/check_multi/feed_passive</a></p></div>
-<div class="paragraph"><p>You can pass such child checks to Nagios via the mod_gearman
-neb module:</p></div>
-<div class="literalblock">
-<div class="content">
-<pre><tt> %> check_multi -f multi.cmd -r 256 | ./send_multi --server=<job server> --encryption=no --host="<hostname>" --service="<service>"</tt></pre>
-</div></div>
-<div class="paragraph"><p>If you want to use only check_multi and no other workers, you can
-achieve this with the following neb module settings:</p></div>
-<div class="literalblock">
-<div class="content">
-<pre><tt>broker_module=/usr/local/share/nagios/mod_gearman.o server=localhost encryption=no eventhandler=no hosts=no services=no hostgroups=does_not_exist</tt></pre>
-</div></div>
-<div class="paragraph"><p>Note: encryption is not necessary if you both run the check_multi checks
-and the nagios check_results queue on the same server.</p></div>
-</div>
-<h2 id="_what_about_notifications">What About Notifications</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>Notifications are very difficult to distribute. And i think its not
-very useful too. So this feature will not be implemented.</p></div>
-</div>
-<h2 id="_hints">Hints</h2>
-<div class="sectionbody">
-<div class="ulist"><ul>
-<li>
-<p>
-Make sure you have at least one worker for every queue. You should
- monitor that (check_gearman).
-</p>
-</li>
-<li>
-<p>
-Add Logfile checks for your gearmand server and mod_gearman
- worker.
-</p>
-</li>
-<li>
-<p>
-Make sure all gearman checks are in local groups. Gearman self
- checks should not be monitored through gearman.
-</p>
-</li>
-<li>
-<p>
-Keep the gearmand server close to Nagios for better performance.
-</p>
-</li>
-<li>
-<p>
-If you have some checks which should not run parallel, just setup a
- single worker with --max-worker=1 and they will be executed one
- after another. For example for cpu intesive checks with selenium.
-</p>
-</li>
-</ul></div>
-</div>
-<h2 id="_download">Download</h2>
-<div class="sectionbody">
-<div class="paragraph"><p>Mod Gearman is available for download at: <a href="http://labs.consol.de/nagios/mod-gearman">http://labs.consol.de/nagios/mod-gearman</a></p></div>
-<div class="paragraph"><p>The source is available at GitHub: <a href="http://github.com/sni/mod_gearman">http://github.com/sni/mod_gearman</a></p></div>
-</div>
-</div>
-<div id="footnotes"><hr /></div>
-<div id="footer">
-<div id="footer-text">
-Last updated 2010-11-17 16:08:29 CEST
-</div>
-</div>
-</body>
-</html>
|
[-]
[+]
|
Deleted |
mod_gearman-0.8.tar.bz2/patches
^
|
-(directory)
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/Changes
^
|
@@ -1,5 +1,19 @@
This file documents the revision history for mod_gearman.
+1.0 Mon Feb 7 11:05:29 CET 2011
+ - added dup_server option (Mark Clarkson)
+ - added stderr to send_multi
+ - added missing performance data to send_multi
+ - added error message when using unknown option
+ - fixed handling of unusual exit codes
+
+0.9 Sun Jan 16 21:20:06 CET 2011
+ - prepared debian packaging (Stig Sandbeck Mathisen)
+ - increased max output to 64k
+ - fixed default paths in gearmand init script
+ - fixed problem with too low number of workers after running for a while
+ - fixed problem with uppercase service descriptions in send_gearman
+
0.8 Wed Nov 17 14:11:54 CET 2010
- added send_multi (Matthias Flacke)
- fixed checks with popen/exec
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/INSTALL
^
|
@@ -17,4 +17,5 @@
%> make test
%> make install
-see the README for configuration examples
+see the README for configuration examples and docs/QUICKSTART for detailed
+installation instructions for debian.
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/Makefile.am
^
|
@@ -1,4 +1,4 @@
-
+# vim:ft=automake noexpandtab
###############################################################################
#
# mod_gearman - distribute checks with gearman
@@ -9,6 +9,8 @@
RPM_TOPDIR=$$(pwd)/rpm.topdir
+.PHONY: docs
+
# -g adds debug symbols, -s strips
CFLAGS=-Wall -W -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -s -O -fPIC
# for debugging
@@ -59,20 +61,25 @@
gearman_top_LDFLAGS = -lncurses
# tests
-check_PROGRAMS = 01_utils 02_full
+check_PROGRAMS = 01_utils 02_full 03_exec
01_utils_SOURCES = $(common_SOURCES) t/tap.h t/tap.c worker/worker_logger.c t/01-utils.c
02_full_SOURCES = $(common_SOURCES) t/tap.h t/tap.c worker/worker_logger.c t/02-full.c
-TESTS = 01_utils 02_full
+03_exec_SOURCES = $(common_SOURCES) t/tap.h t/tap.c worker/worker_logger.c t/03-exec_checks.c
+TESTS = $(check_PROGRAMS)
+GEARMANDS=/usr/sbin/gearmand /opt/sbin/gearmand
replace_vars = sed -e 's:%CONFIG%:$(sysconfdir)/mod_gearman.conf:g' \
-e 's:%PIDFILE%:$(localstatedir)/mod_gearman/mod_gearman_worker.pid:g' \
-e 's:%LOGFILE%:$(localstatedir)/mod_gearman/mod_gearman_worker.log:g' \
+ -e 's:%GPIDFILE%:$(localstatedir)/mod_gearman/gearmand.pid:g' \
+ -e 's:%GLOGFILE%:$(localstatedir)/mod_gearman/gearmand.log:g' \
-e 's:%WORKERBIN%:$(bindir)/mod_gearman_worker:g' \
-e 's:%USER%:$(user):g'
EXTRA_DIST = COPYING etc extras include \
- THANKS README README.html patches Changes worker/initscript.in
+ THANKS README docs/README.html Changes worker/initscript.in \
+ docs/QUICKSTART docs/QUICKSTART.html
# other targets
mod_gearman.o: $(mod_gearman_so_OBJECTS) $(mod_gearman_so_DEPENDENCIES)
@@ -91,6 +98,14 @@
gearmand-init-local:
$(replace_vars) extras/gearmand-init.in > extras/gearmand-init
+ if [ ! -z $$(which gearmand 2>/dev/null) ]; then \
+ sed -i -e "s:%GEARMAND%:$$(which gearmand 2>/dev/null):g" extras/gearmand-init; \
+ fi
+ for gearm in $(GEARMANDS); do \
+ test -f $$gearm && sed -i -e "s:%GEARMAND%:$$gearm:g" extras/gearmand-init ; \
+ done; echo done
+ sed -i -e 's:%GEARMAND%:/usr/sbin/gearmand:g' extras/gearmand-init
+ chmod 755 extras/gearmand-init
all-local: mod_gearman.o initscript-local mod_gearman.conf-local gearmand-init-local
@echo ""
@@ -114,10 +129,10 @@
@echo "################################################################"
distclean-local: clean
- $(RM) -r .deps/ Makefile.in aclocal.m4 autom4te.cache config.* configure depcomp install-sh missing *.gz
+ $(RM) -rf .deps/ Makefile.in aclocal.m4 autom4te.cache config.* configure depcomp install-sh missing *.gz
clean-local:
- $(RM) -r worker.static worker/initscript etc/mod_gearman.conf rpm.topdir *.o */*.o
+ $(RM) -rf worker.static worker/initscript etc/mod_gearman.conf rpm.topdir *.o */*.o
worker.static: worker
@echo "################################################################"
@@ -138,9 +153,9 @@
install-local-state-dir:
$(RM) $(DESTDIR)$(pkglibdir)/mod_gearman.so
if [ `id -u` -eq 0 ]; then \
- $(install_sh) -o $(user) -d $(DESTDIR)$(localstatedir)/mod_gearman/; \
+ $(install_sh_PROGRAM) -o $(user) -d $(DESTDIR)$(localstatedir)/mod_gearman/; \
else \
- $(install_sh) -o $(user) -d $(DESTDIR)$(localstatedir)/mod_gearman/; \
+ $(install_sh_PROGRAM) -o $(user) -d $(DESTDIR)$(localstatedir)/mod_gearman/; \
echo "*** You should run: sudo chown $(user) $(DESTDIR)$(localstatedir)/mod_gearman/"; \
fi
@@ -186,10 +201,18 @@
@echo "################################################################"
docs:
- $(RM) images
- ln -s /usr/share/asciidoc/images .
- asciidoc --unsafe -a toc -a toclevels=2 -a icons -a data-uri -a max-width=800 README
- chmod 644 README.html
+ @if [ `type doxygen > /dev/null 2>&1` ]; then \
+ doxygen Doxyfile; \
+ else \
+ printf "\n\n**** please install doxygen to generate doxygen docs ****\n\n"; \
+ fi;
+ $(RM) docs/images
+ cd docs && ln -s /usr/share/asciidoc/images .
+ cp -p README docs/ && cd docs && asciidoc --unsafe -a toc -a toclevels=2 -a icons -a data-uri -a max-width=800 README
+ chmod 644 docs/README.html
+ rm -f docs/README
+ cd docs && asciidoc --unsafe -a toc -a toclevels=2 -a icons -a data-uri -a max-width=800 QUICKSTART
+ chmod 644 docs/QUICKSTART.html
rpm: dist
mkdir -p $(RPM_TOPDIR)/{SOURCES,BUILD,RPMS,SRPMS,SPECS}
@@ -199,3 +222,6 @@
mv -v $(RPM_TOPDIR)/RPMS/*/*.rpm .
mv -v $(RPM_TOPDIR)/SRPMS/*.src.rpm .
rm -rf $(RPM_TOPDIR) rpm.buildroot
+
+deb:
+ dpkg-buildpackage -us -uc
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/Makefile.in
^
|
@@ -15,6 +15,7 @@
@SET_MAKE@
+# vim:ft=automake noexpandtab
###############################################################################
#
# mod_gearman - distribute checks with gearman
@@ -44,8 +45,7 @@
bin_PROGRAMS = mod_gearman_worker$(EXEEXT) send_gearman$(EXEEXT) \
send_multi$(EXEEXT) check_gearman$(EXEEXT) \
gearman_top$(EXEEXT)
-check_PROGRAMS = 01_utils$(EXEEXT) 02_full$(EXEEXT)
-TESTS = 01_utils$(EXEEXT) 02_full$(EXEEXT)
+check_PROGRAMS = 01_utils$(EXEEXT) 02_full$(EXEEXT) 03_exec$(EXEEXT)
subdir = .
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/config.h.in \
@@ -105,6 +105,10 @@
worker/worker_logger.$(OBJEXT) t/02-full.$(OBJEXT)
02_full_OBJECTS = $(am_02_full_OBJECTS)
02_full_LDADD = $(LDADD)
+am_03_exec_OBJECTS = $(am__objects_1) t/tap.$(OBJEXT) \
+ worker/worker_logger.$(OBJEXT) t/03-exec_checks.$(OBJEXT)
+03_exec_OBJECTS = $(am_03_exec_OBJECTS)
+03_exec_LDADD = $(LDADD)
am_check_gearman_OBJECTS = $(am__objects_1) \
tools/tools_logger.$(OBJEXT) tools/check_gearman.$(OBJEXT)
check_gearman_OBJECTS = $(am_check_gearman_OBJECTS)
@@ -137,11 +141,11 @@
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(mod_gearman_so_SOURCES) $(01_utils_SOURCES) \
- $(02_full_SOURCES) $(check_gearman_SOURCES) \
+ $(02_full_SOURCES) $(03_exec_SOURCES) $(check_gearman_SOURCES) \
$(gearman_top_SOURCES) $(mod_gearman_worker_SOURCES) \
$(send_gearman_SOURCES) $(send_multi_SOURCES)
DIST_SOURCES = $(mod_gearman_so_SOURCES) $(01_utils_SOURCES) \
- $(02_full_SOURCES) $(check_gearman_SOURCES) \
+ $(02_full_SOURCES) $(03_exec_SOURCES) $(check_gearman_SOURCES) \
$(gearman_top_SOURCES) $(mod_gearman_worker_SOURCES) \
$(send_gearman_SOURCES) $(send_multi_SOURCES)
ETAGS = etags
@@ -299,14 +303,20 @@
gearman_top_LDFLAGS = -lncurses
01_utils_SOURCES = $(common_SOURCES) t/tap.h t/tap.c worker/worker_logger.c t/01-utils.c
02_full_SOURCES = $(common_SOURCES) t/tap.h t/tap.c worker/worker_logger.c t/02-full.c
+03_exec_SOURCES = $(common_SOURCES) t/tap.h t/tap.c worker/worker_logger.c t/03-exec_checks.c
+TESTS = $(check_PROGRAMS)
+GEARMANDS = /usr/sbin/gearmand /opt/sbin/gearmand
replace_vars = sed -e 's:%CONFIG%:$(sysconfdir)/mod_gearman.conf:g' \
-e 's:%PIDFILE%:$(localstatedir)/mod_gearman/mod_gearman_worker.pid:g' \
-e 's:%LOGFILE%:$(localstatedir)/mod_gearman/mod_gearman_worker.log:g' \
+ -e 's:%GPIDFILE%:$(localstatedir)/mod_gearman/gearmand.pid:g' \
+ -e 's:%GLOGFILE%:$(localstatedir)/mod_gearman/gearmand.log:g' \
-e 's:%WORKERBIN%:$(bindir)/mod_gearman_worker:g' \
-e 's:%USER%:$(user):g'
EXTRA_DIST = COPYING etc extras include \
- THANKS README README.html patches Changes worker/initscript.in
+ THANKS README docs/README.html Changes worker/initscript.in \
+ docs/QUICKSTART docs/QUICKSTART.html
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
@@ -493,6 +503,11 @@
02_full$(EXEEXT): $(02_full_OBJECTS) $(02_full_DEPENDENCIES)
@rm -f 02_full$(EXEEXT)
$(LINK) $(02_full_OBJECTS) $(02_full_LDADD) $(LIBS)
+t/03-exec_checks.$(OBJEXT): t/$(am__dirstamp) \
+ t/$(DEPDIR)/$(am__dirstamp)
+03_exec$(EXEEXT): $(03_exec_OBJECTS) $(03_exec_DEPENDENCIES)
+ @rm -f 03_exec$(EXEEXT)
+ $(LINK) $(03_exec_OBJECTS) $(03_exec_LDADD) $(LIBS)
tools/$(am__dirstamp):
@$(MKDIR_P) tools
@: > tools/$(am__dirstamp)
@@ -542,6 +557,7 @@
-rm -f neb_module/result_thread.$(OBJEXT)
-rm -f t/01-utils.$(OBJEXT)
-rm -f t/02-full.$(OBJEXT)
+ -rm -f t/03-exec_checks.$(OBJEXT)
-rm -f t/tap.$(OBJEXT)
-rm -f tools/check_gearman.$(OBJEXT)
-rm -f tools/gearman_top.$(OBJEXT)
@@ -566,6 +582,7 @@
@AMDEP_TRUE@@am__include@ @am__quote@neb_module/$(DEPDIR)/result_thread.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@t/$(DEPDIR)/01-utils.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@t/$(DEPDIR)/02-full.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@t/$(DEPDIR)/03-exec_checks.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@t/$(DEPDIR)/tap.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/check_gearman.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/gearman_top.Po@am__quote@
@@ -1022,6 +1039,8 @@
uninstall-am uninstall-binPROGRAMS uninstall-pkglibLIBRARIES
+.PHONY: docs
+
# other targets
mod_gearman.o: $(mod_gearman_so_OBJECTS) $(mod_gearman_so_DEPENDENCIES)
if [ "$(OS)" == "Darwin" ]; then \
@@ -1039,6 +1058,14 @@
gearmand-init-local:
$(replace_vars) extras/gearmand-init.in > extras/gearmand-init
+ if [ ! -z $$(which gearmand 2>/dev/null) ]; then \
+ sed -i -e "s:%GEARMAND%:$$(which gearmand 2>/dev/null):g" extras/gearmand-init; \
+ fi
+ for gearm in $(GEARMANDS); do \
+ test -f $$gearm && sed -i -e "s:%GEARMAND%:$$gearm:g" extras/gearmand-init ; \
+ done; echo done
+ sed -i -e 's:%GEARMAND%:/usr/sbin/gearmand:g' extras/gearmand-init
+ chmod 755 extras/gearmand-init
all-local: mod_gearman.o initscript-local mod_gearman.conf-local gearmand-init-local
@echo ""
@@ -1062,10 +1089,10 @@
@echo "################################################################"
distclean-local: clean
- $(RM) -r .deps/ Makefile.in aclocal.m4 autom4te.cache config.* configure depcomp install-sh missing *.gz
+ $(RM) -rf .deps/ Makefile.in aclocal.m4 autom4te.cache config.* configure depcomp install-sh missing *.gz
clean-local:
- $(RM) -r worker.static worker/initscript etc/mod_gearman.conf rpm.topdir *.o */*.o
+ $(RM) -rf worker.static worker/initscript etc/mod_gearman.conf rpm.topdir *.o */*.o
worker.static: worker
@echo "################################################################"
@@ -1086,9 +1113,9 @@
install-local-state-dir:
$(RM) $(DESTDIR)$(pkglibdir)/mod_gearman.so
if [ `id -u` -eq 0 ]; then \
- $(install_sh) -o $(user) -d $(DESTDIR)$(localstatedir)/mod_gearman/; \
+ $(install_sh_PROGRAM) -o $(user) -d $(DESTDIR)$(localstatedir)/mod_gearman/; \
else \
- $(install_sh) -o $(user) -d $(DESTDIR)$(localstatedir)/mod_gearman/; \
+ $(install_sh_PROGRAM) -o $(user) -d $(DESTDIR)$(localstatedir)/mod_gearman/; \
echo "*** You should run: sudo chown $(user) $(DESTDIR)$(localstatedir)/mod_gearman/"; \
fi
@@ -1133,10 +1160,18 @@
@echo "################################################################"
docs:
- $(RM) images
- ln -s /usr/share/asciidoc/images .
- asciidoc --unsafe -a toc -a toclevels=2 -a icons -a data-uri -a max-width=800 README
- chmod 644 README.html
+ @if [ `type doxygen > /dev/null 2>&1` ]; then \
+ doxygen Doxyfile; \
+ else \
+ printf "\n\n**** please install doxygen to generate doxygen docs ****\n\n"; \
+ fi;
+ $(RM) docs/images
+ cd docs && ln -s /usr/share/asciidoc/images .
+ cp -p README docs/ && cd docs && asciidoc --unsafe -a toc -a toclevels=2 -a icons -a data-uri -a max-width=800 README
+ chmod 644 docs/README.html
+ rm -f docs/README
+ cd docs && asciidoc --unsafe -a toc -a toclevels=2 -a icons -a data-uri -a max-width=800 QUICKSTART
+ chmod 644 docs/QUICKSTART.html
rpm: dist
mkdir -p $(RPM_TOPDIR)/{SOURCES,BUILD,RPMS,SRPMS,SPECS}
@@ -1147,6 +1182,9 @@
mv -v $(RPM_TOPDIR)/SRPMS/*.src.rpm .
rm -rf $(RPM_TOPDIR) rpm.buildroot
+deb:
+ dpkg-buildpackage -us -uc
+
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/README
^
|
@@ -10,6 +10,12 @@
the checks itself. They can be bound to host and servicegroups.
+Support & Questions
+-------------------
+Please use the following google groups mailinglist for support or
+questions: https://groups.google.com/group/mod_gearman
+
+
How does it work
----------------
When the broker module is loaded, it captures all servicecheck,
@@ -180,8 +186,9 @@
Example: debug=1
-server: sets the addess of your gearman job server. Can be specified
- more than once to add more server.
+server: sets the address of your gearman job server. Can be specified
+ more than once to add more server. Gearman uses
+ the first one available.
Example: server=localhost:4730,remote_host:4730
@@ -326,7 +333,8 @@
idle-timeout: Time after which an idling worker exists. This
parameter controls how fast your waiting workers
- will exit if there are no jobs waiting.
+ will exit if there are no jobs waiting. Set to 0
+ to disable the idle timeout.
Default: 10
Example: idle-timeout=30
@@ -335,10 +343,27 @@
max-jobs: Controls the amount of jobs a worker will do
before he exits. Use this to control how fast the
amount of workers will go down after high load
- times.
- Default: 20
+ times. Disabled when set to 0.
+ Default: 1000
+
+ Example: max-jobs=500
+
+fork_on_exec: Use this option to disable an extra fork for each
+ plugin execution. This option will reduce the load
+ on the worker host.
+ Default: yes
+
+ Example: fork_on_exec=no
+
+dup_server: sets the address of gearman job server where
+ duplicated result will be sent to. Can be specified
+ more than once to add more server.
+ Useful for duplicating results for a reporting
+ installation or remote gui.
+
+ Example: dup_server=logserver:4730,logserver2:4730
+
- Example: max-jobs=50
.......
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/THANKS
^
|
@@ -12,3 +12,7 @@
http://www.efgh.com/software/rijndael.htm
for the aes-256 code.
+Thanks to
+https://github.com/zorgnax/libtap
+for the libtap code.
+
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/TODO
^
|
@@ -6,6 +6,8 @@
-------
- handle sync host checks correctly
+ - maybe use libmcrypt for encryption
+ - "include" directorys for the config file
Bugs
----
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/common/crypt.c
^
|
@@ -60,6 +60,9 @@
nrounds = rijndaelSetupEncrypt(rk, key, KEYBITS);
size = strlen(text);
totalsize = size + BLOCKSIZE-size%BLOCKSIZE;
+ if(size%BLOCKSIZE == 0) {
+ size += BLOCKSIZE;
+ }
enc = (unsigned char *) malloc(sizeof(unsigned char)*totalsize);
while(size > 0) {
unsigned char plaintext[BLOCKSIZE];
@@ -74,7 +77,7 @@
}
for (; j < BLOCKSIZE; j++)
- plaintext[j] = '\n';
+ plaintext[j] = '\x0';
rijndaelEncrypt(rk, nrounds, plaintext, ciphertext);
for (j = 0; j < BLOCKSIZE; j++)
enc[k++] = ciphertext[j];
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/common/gearman.c
^
|
@@ -78,12 +78,49 @@
}
+/* create the gearman duplicate client */
+int create_client_dup( char ** server_list, gearman_client_st *client ) {
+ gearman_return_t ret;
+ int x = 0;
+
+ gm_log( GM_LOG_TRACE, "create_client_dup()\n" );
+
+ signal(SIGPIPE, SIG_IGN);
+
+ client = gearman_client_create(client);
+ if ( client == NULL ) {
+ gm_log( GM_LOG_ERROR, "Memory allocation failure on client creation\n" );
+ return GM_ERROR;
+ }
+
+ while ( server_list[x] != NULL ) {
+ char * server = strdup( server_list[x] );
+ char * server_c = server;
+ char * host = strsep( &server, ":" );
+ char * port_val = strsep( &server, "\x0" );
+ in_port_t port = GM_SERVER_DEFAULT_PORT;
+ if(port_val != NULL) {
+ port = ( in_port_t ) atoi( port_val );
+ }
+ ret = gearman_client_add_server( client, host, port );
+ if ( ret != GEARMAN_SUCCESS ) {
+ gm_log( GM_LOG_ERROR, "client error: %s\n", gearman_client_error( client ) );
+ free(server_c);
+ return GM_ERROR;
+ }
+ free(server_c);
+ x++;
+ }
+
+ return GM_OK;
+}
+
/* create the gearman client */
int create_client( char ** server_list, gearman_client_st *client ) {
gearman_return_t ret;
int x = 0;
- gm_log( GM_LOG_TRACE, "create_gearman_client()\n" );
+ gm_log( GM_LOG_TRACE, "create_client()\n" );
signal(SIGPIPE, SIG_IGN);
@@ -134,6 +171,20 @@
size = mod_gm_encrypt(&crypted_data, data, transport_mode);
gm_log( GM_LOG_TRACE, "%d +++>\n%s\n<+++\n", size, crypted_data );
+#ifdef GM_DEBUG
+ /* verify decrypted string is equal to the original */
+ char * test;
+ test = malloc(GM_BUFFERSIZE);
+ mod_gm_decrypt(&test, crypted_data, transport_mode);
+ gm_log( GM_LOG_TRACE, "%d ===>\n%s\n<===\n", size, test );
+ if(strcmp(test, data)) {
+ gm_log( GM_LOG_ERROR, "%d --->%s<---\n", strlen(data), data );
+ gm_log( GM_LOG_ERROR, "%d ===>\n%s\n<===\n", size, test );
+ fprintf(stderr, "encrypted string does not match\n");
+ exit(EXIT_FAILURE);
+ }
+#endif
+
if( priority == GM_JOB_PRIO_LOW ) {
task = gearman_client_add_task_low_background( client, NULL, NULL, queue, uniq, ( void * )crypted_data, ( size_t )size, &ret1 );
gearman_task_give_workload(task,crypted_data,size);
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/common/utils.c
^
|
@@ -26,6 +26,7 @@
#include "crypt.h"
#include "base64.h"
+pid_t current_child_pid = 0;
/* escapes newlines in a string */
char *escape_newlines(char *rawbuf) {
@@ -226,6 +227,9 @@
opt->server_num = 0;
for(i=0;i<=GM_LISTSIZE;i++)
opt->server_list[i] = NULL;
+ opt->dupserver_num = 0;
+ for(i=0;i<=GM_LISTSIZE;i++)
+ opt->dupserver_list[i] = NULL;
opt->hostgroups_num = 0;
for(i=0;i<=GM_LISTSIZE;i++)
opt->hostgroups_list[i] = NULL;
@@ -295,58 +299,65 @@
/* daemon mode */
if ( !strcmp( key, "daemon" ) || !strcmp( key, "d" ) ) {
opt->daemon_mode = parse_yes_or_no(value, GM_ENABLED);
+ return(GM_OK);
}
/* perfdata */
else if ( !strcmp( key, "perfdata" ) ) {
opt->set_queues_by_hand++;
opt->perfdata = parse_yes_or_no(value, GM_ENABLED);
+ return(GM_OK);
}
/* hosts */
- else if ( !strcmp( key, "hosts" )
- || !strcmp( key, "host" )
- ) {
+ else if ( !strcmp( key, "hosts" ) ) {
opt->set_queues_by_hand++;
opt->hosts = parse_yes_or_no(value, GM_ENABLED);
+ return(GM_OK);
}
/* services */
- else if ( !strcmp( key, "services" )
- || !strcmp( key, "service" )
- ) {
+ else if ( !strcmp( key, "services" ) ) {
opt->set_queues_by_hand++;
opt->services = parse_yes_or_no(value, GM_ENABLED);
+ return(GM_OK);
}
/* eventhandler */
- else if ( !strcmp( key, "events" )
- || !strcmp( key, "event" )
- || !strcmp( key, "eventhandlers" )
+ else if ( !strcmp( key, "eventhandlers" )
|| !strcmp( key, "eventhandler" )
) {
opt->set_queues_by_hand++;
opt->events = parse_yes_or_no(value, GM_ENABLED);
+ return(GM_OK);
}
/* debug-result */
else if ( !strcmp( key, "debug-result" ) ) {
opt->debug_result = parse_yes_or_no(value, GM_ENABLED);
+ return(GM_OK);
}
/* encryption */
else if ( !strcmp( key, "encryption" ) ) {
opt->encryption = parse_yes_or_no(value, GM_ENABLED);
+ return(GM_OK);
}
/* fork_on_exec */
else if ( !strcmp( key, "fork_on_exec" ) ) {
opt->fork_on_exec = parse_yes_or_no(value, GM_ENABLED);
+ return(GM_OK);
}
/* active */
else if ( !strcmp( key, "active" ) ) {
opt->active = parse_yes_or_no(value, GM_ENABLED);
+ return(GM_OK);
+ }
+ else if ( value == NULL ) {
+ gm_log( GM_LOG_ERROR, "unknown switch '%s'\n", key );
+ return(GM_OK);
}
if ( value == NULL )
@@ -504,6 +515,18 @@
}
}
+ /* duplicate server */
+ else if ( !strcmp( key, "dupserver" ) ) {
+ char *servername;
+ while ( (servername = strsep( &value, "," )) != NULL ) {
+ servername = trim(servername);
+ if ( strcmp( servername, "" ) ) {
+ opt->dupserver_list[opt->dupserver_num] = strdup(servername);
+ opt->dupserver_num++;
+ }
+ }
+ }
+
/* servicegroups */
else if ( !strcmp( key, "servicegroups" )
|| !strcmp( key, "servicegroup" )
@@ -559,6 +582,9 @@
}
}
}
+ else {
+ gm_log( GM_LOG_ERROR, "unknown option '%s'\n", key );
+ }
return(GM_OK);
}
@@ -619,6 +645,7 @@
gm_log( GM_LOG_DEBUG, "identifier: %s\n", opt->identifier);
gm_log( GM_LOG_DEBUG, "pidfile: %s\n", opt->pidfile == NULL ? "no" : opt->pidfile);
gm_log( GM_LOG_DEBUG, "logfile: %s\n", opt->logfile == NULL ? "no" : opt->logfile);
+ gm_log( GM_LOG_DEBUG, "job max num: %d\n", opt->max_jobs);
gm_log( GM_LOG_DEBUG, "job max age: %d\n", opt->max_age);
gm_log( GM_LOG_DEBUG, "job timeout: %d\n", opt->job_timeout);
gm_log( GM_LOG_DEBUG, "min worker: %d\n", opt->min_worker);
@@ -638,6 +665,9 @@
for(i=0;i<opt->server_num;i++)
gm_log( GM_LOG_DEBUG, "server: %s\n", opt->server_list[i]);
gm_log( GM_LOG_DEBUG, "\n" );
+ for(i=0;i<opt->dupserver_num;i++)
+ gm_log( GM_LOG_DEBUG, "dupserver: %s\n", opt->dupserver_list[i]);
+ gm_log( GM_LOG_DEBUG, "\n" );
if(mode == GM_NEB_MODE) {
gm_log( GM_LOG_DEBUG, "perfdata: %s\n", opt->perfdata == GM_ENABLED ? "yes" : "no");
}
@@ -681,6 +711,8 @@
int i;
for(i=0;i<opt->server_num;i++)
free(opt->server_list[i]);
+ for(i=0;i<opt->dupserver_num;i++)
+ free(opt->dupserver_list[i]);
for(i=0;i<opt->hostgroups_num;i++)
free(opt->hostgroups_list[i]);
for(i=0;i<opt->servicegroups_num;i++)
@@ -912,7 +944,12 @@
parse_command_line(processed_command,argv);
if(!argv[0])
_exit(STATE_UNKNOWN);
+ current_child_pid = getpid();
execvp(argv[0], argv);
+ if(errno == 2)
+ _exit(127);
+ if(errno == 13)
+ _exit(126);
_exit(STATE_UNKNOWN);
}
@@ -934,6 +971,7 @@
retval=-1;
}
else {
+ current_child_pid = getpid();
gm_log( GM_LOG_TRACE, "using popen\n" );
fp=popen(processed_command,"r");
if(fp==NULL)
@@ -949,3 +987,230 @@
return retval;
}
+
+
+/* execute this command with given timeout */
+int execute_safe_command(gm_job_t * exec_job, int fork_exec, char * hostname) {
+ int pdes[2];
+ int return_code;
+ int pclose_result;
+ char *plugin_output;
+ char buffer[GM_BUFFERSIZE];
+ sigset_t mask;
+ struct timeval start_time,end_time;
+ pid_t pid = 0;
+
+ gm_log( GM_LOG_TRACE, "execute_safe_command()\n" );
+
+ if(exec_job->start_time.tv_sec == 0) {
+ gettimeofday(&start_time,NULL);
+ exec_job->start_time = start_time;
+ }
+
+ /* fork a child process */
+ if(fork_exec == GM_ENABLED) {
+ if(pipe(pdes) != 0)
+ perror("pipe");
+
+ pid=fork();
+
+ /*fork error */
+ if( pid == -1 ) {
+ exec_job->output = strdup("(Error On Fork)");
+ exec_job->return_code = 3;
+ return(GM_ERROR);
+ }
+ }
+
+ /* we are in the child process */
+ if( fork_exec == GM_DISABLED || pid == 0 ) {
+
+ /* become the process group leader */
+ setpgid(0,0);
+ pid = getpid();
+
+ /* remove all customn signal handler */
+ sigfillset(&mask);
+ sigprocmask(SIG_UNBLOCK, &mask, NULL);
+
+ if( fork_exec == GM_ENABLED )
+ close(pdes[0]);
+ signal(SIGALRM, check_alarm_handler);
+ alarm(exec_job->timeout);
+
+ /* run the plugin check command */
+ pclose_result = run_check(exec_job->command_line, &plugin_output);
+ return_code = pclose_result;
+
+ if(fork_exec == GM_ENABLED) {
+ if(write(pdes[1], plugin_output, strlen(plugin_output)+1) <= 0)
+ perror("write");
+
+ if(pclose_result == -1) {
+ char error[GM_BUFFERSIZE];
+ snprintf(error, sizeof(error), "error on %s: %s", hostname, strerror(errno));
+ if(write(pdes[1], error, strlen(error)+1) <= 0)
+ perror("write");
+ }
+
+ return_code = real_exit_code(pclose_result);
+ exit(return_code);
+ }
+ else {
+ snprintf( buffer, sizeof( buffer )-1, "%s", plugin_output );
+ }
+ }
+
+ /* we are the parent */
+ if( fork_exec == GM_DISABLED || pid > 0 ){
+
+ gm_log( GM_LOG_TRACE, "started check with pid: %d\n", pid);
+
+ if( fork_exec == GM_ENABLED) {
+ close(pdes[1]);
+
+ waitpid(pid, &return_code, 0);
+ gm_log( GM_LOG_TRACE, "finished check from pid: %d with status: %d\n", pid, return_code);
+ /* get all lines of plugin output */
+ if(read(pdes[0], buffer, sizeof(buffer)-1) < 0)
+ perror("read");
+ }
+ return_code = real_exit_code(return_code);
+
+ /* file not executable? */
+ if(return_code == 126) {
+ return_code = STATE_CRITICAL;
+ snprintf( buffer, sizeof( buffer )-1, "CRITICAL: Return code of 126 is out of bounds. Make sure the plugin you're trying to run is executable. (worker: %s)", hostname);
+ }
+ /* file not found errors? */
+ else if(return_code == 127) {
+ return_code = STATE_CRITICAL;
+ snprintf( buffer, sizeof( buffer )-1, "CRITICAL: Return code of 127 is out of bounds. Make sure the plugin you're trying to run actually exists. (worker: %s)", hostname);
+ }
+ /* signaled */
+ else if(return_code >= 128 && return_code < 256) {
+ char * signame = nr2signal((int)(return_code-128));
+ snprintf( buffer, sizeof( buffer )-1, "CRITICAL: Return code of %d is out of bounds. Plugin exited by signal %s. (worker: %s)", (int)(return_code), signame, hostname);
+ return_code = STATE_CRITICAL;
+ free(signame);
+ }
+ /* other error codes > 3 */
+ else if(return_code > 3) {
+ snprintf( buffer, sizeof( buffer )-1, "CRITICAL: Return code of %d is out of bounds. (worker: %s)", (int)(return_code), hostname);
+ return_code = STATE_CRITICAL;
+ }
+
+ exec_job->output = strdup(buffer);
+ exec_job->return_code = return_code;
+ if( fork_exec == GM_ENABLED) {
+ close(pdes[0]);
+ }
+ }
+ alarm(0);
+ current_child_pid = 0;
+ pid = 0;
+
+ /* record check result info */
+ gettimeofday(&end_time, NULL);
+ exec_job->finish_time = end_time;
+
+ /* did we have a timeout? */
+ if(exec_job->timeout < ((int)end_time.tv_sec - (int)exec_job->start_time.tv_sec)) {
+ exec_job->return_code = 2;
+ exec_job->early_timeout = 1;
+ if ( !strcmp( exec_job->type, "service" ) )
+ snprintf( buffer, sizeof( buffer ) -1, "(Service Check Timed Out On Worker: %s)", hostname);
+ if ( !strcmp( exec_job->type, "host" ) )
+ snprintf( buffer, sizeof( buffer ) -1, "(Host Check Timed Out On Worker: %s)", hostname);
+ exec_job->output = strdup( buffer );
+ }
+
+ return(GM_OK);
+}
+
+
+/* set empty default job */
+int set_default_job(gm_job_t *job, mod_gm_opt_t *mod_gm_opt) {
+
+ job->type = NULL;
+ job->host_name = NULL;
+ job->service_description = NULL;
+ job->result_queue = NULL;
+ job->command_line = NULL;
+ job->output = NULL;
+ job->exited_ok = TRUE;
+ job->scheduled_check = TRUE;
+ job->reschedule_check = TRUE;
+ job->return_code = STATE_OK;
+ job->latency = 0.0;
+ job->timeout = mod_gm_opt->job_timeout;
+ job->start_time.tv_sec = 0L;
+ job->start_time.tv_usec = 0L;
+
+ return(GM_OK);
+}
+
+
+/* free the job structure */
+int free_job(gm_job_t *job) {
+
+ free(job->type);
+ free(job->host_name);
+ free(job->service_description);
+ free(job->result_queue);
+ free(job->command_line);
+ free(job->output);
+ free(job);
+
+ return(GM_OK);
+}
+
+
+
+/* called when check runs into timeout */
+void check_alarm_handler(int sig) {
+ int retval;
+ pid_t pid = getpid();
+
+ gm_log( GM_LOG_TRACE, "check_alarm_handler(%i)\n", sig );
+
+ if(current_child_pid > 0) {
+ gm_log( GM_LOG_TRACE, "send SIGINT to %d\n", current_child_pid);
+ signal(SIGINT, SIG_IGN);
+ kill(-current_child_pid, SIGINT);
+ sleep(1);
+ if(waitpid(pid,&retval,0)!=pid)
+ return;
+ if(pid_alive(current_child_pid)) {
+ gm_log( GM_LOG_TRACE, "send SIGKILL to %d\n", current_child_pid);
+ kill(-current_child_pid, SIGKILL);
+ }
+ } else {
+ signal(SIGINT, SIG_IGN);
+ gm_log( GM_LOG_TRACE, "send SIGINT to %d\n", pid);
+ kill(-pid, SIGINT);
+ signal(SIGINT, SIG_DFL);
+ sleep(1);
+ gm_log( GM_LOG_TRACE, "send SIGKILL to %d\n", pid);
+ kill(-pid, SIGKILL);
+ }
+
+ return;
+}
+
+
+/* verify if a pid is alive */
+int pid_alive(int pid) {
+ if(pid < 0) { pid = -pid; }
+
+ /* 1/-1 are undefined pids in our case */
+ if(pid == 1)
+ return TRUE;
+
+ /* send kill 0 to verify the proc is alive */
+ if(kill(pid, 0) == 0) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/configure
^
|
@@ -1,8 +1,8 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.65 for mod_gearman 0.8.
+# Generated by GNU Autoconf 2.65 for mod_gearman 1.0.
#
-# Report bugs to <sven@consol.de>.
+# Report bugs to <sven.nierlein@consol.de>.
#
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -230,11 +230,11 @@
$as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
$as_echo "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org and sven@consol.de
-$0: about your system, including any error possibly output
-$0: before this message. Then install a modern shell, or
-$0: manually run the script under such a shell if you do
-$0: have one."
+ $as_echo "$0: Please tell bug-autoconf@gnu.org and
+$0: sven.nierlein@consol.de about your system, including
+$0: any error possibly output before this message. Then
+$0: install a modern shell, or manually run the script
+$0: under such a shell if you do have one."
fi
exit 1
fi
@@ -552,9 +552,9 @@
# Identity of this package.
PACKAGE_NAME='mod_gearman'
PACKAGE_TARNAME='mod_gearman'
-PACKAGE_VERSION='0.8'
-PACKAGE_STRING='mod_gearman 0.8'
-PACKAGE_BUGREPORT='sven@consol.de'
+PACKAGE_VERSION='1.0'
+PACKAGE_STRING='mod_gearman 1.0'
+PACKAGE_BUGREPORT='sven.nierlein@consol.de'
PACKAGE_URL=''
ac_unique_file="neb_module/mod_gearman.c"
@@ -1249,7 +1249,7 @@
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures mod_gearman 0.8 to adapt to many kinds of systems.
+\`configure' configures mod_gearman 1.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1315,7 +1315,7 @@
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of mod_gearman 0.8:";;
+ short | recursive ) echo "Configuration of mod_gearman 1.0:";;
esac
cat <<\_ACEOF
@@ -1329,7 +1329,7 @@
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --with-gearman=DIR Specify the path to you gearman library
+ --with-gearman=DIR Specify the path to your gearman library
--with-init-dir specify the system init script directory
[default="${sysconfdir}/init.d"]
--with-user specify the user [default="nagios"]
@@ -1349,7 +1349,7 @@
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
-Report bugs to <sven@consol.de>.
+Report bugs to <sven.nierlein@consol.de>.
_ACEOF
ac_status=$?
fi
@@ -1412,7 +1412,7 @@
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-mod_gearman configure 0.8
+mod_gearman configure 1.0
generated by GNU Autoconf 2.65
Copyright (C) 2009 Free Software Foundation, Inc.
@@ -1652,9 +1652,9 @@
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
( cat <<\_ASBOX
-## ----------------------------- ##
-## Report this to sven@consol.de ##
-## ----------------------------- ##
+## -------------------------------------- ##
+## Report this to sven.nierlein@consol.de ##
+## -------------------------------------- ##
_ASBOX
) | sed "s/^/$as_me: WARNING: /" >&2
;;
@@ -1875,7 +1875,7 @@
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by mod_gearman $as_me 0.8, which was
+It was created by mod_gearman $as_me 1.0, which was
generated by GNU Autoconf 2.65. Invocation command line was
$ $0 $@
@@ -2683,7 +2683,7 @@
# Define the identity of the package.
PACKAGE='mod_gearman'
- VERSION='0.8'
+ VERSION='1.0'
cat >>confdefs.h <<_ACEOF
@@ -5935,7 +5935,7 @@
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by mod_gearman $as_me 0.8, which was
+This file was extended by mod_gearman $as_me 1.0, which was
generated by GNU Autoconf 2.65. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -5995,13 +5995,13 @@
Configuration commands:
$config_commands
-Report bugs to <sven@consol.de>."
+Report bugs to <sven.nierlein@consol.de>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-mod_gearman config.status 0.8
+mod_gearman config.status 1.0
configured by $0, generated by GNU Autoconf 2.65,
with options \\"\$ac_cs_config\\"
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/configure.ac
^
|
@@ -3,7 +3,7 @@
##############################################
AC_PREREQ([2.59])
-AC_INIT([mod_gearman], [0.8], [sven@consol.de])
+AC_INIT([mod_gearman], [1.0], [sven.nierlein@consol.de])
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
AC_CONFIG_SRCDIR([neb_module/mod_gearman.c],[worker/worker.c],[tools/send_gearman.c],[tools/check_gearman.c],[tools/gearman_top.c])
AC_CONFIG_HEADER([config.h])
@@ -33,7 +33,7 @@
AC_CHECK_HEADERS([curses.h],,AC_MSG_ERROR([Compiling mod_gearman requires curses.h]))
AC_ARG_WITH(gearman,
- [ --with-gearman=DIR Specify the path to you gearman library],
+ [ --with-gearman=DIR Specify the path to your gearman library],
[ LDFLAGS="$LDFLAGS -L$withval/lib"
CFLAGS="$CFLAGS -I$withval/include"
])
@@ -60,7 +60,7 @@
id -a $user > /dev/null 2>&1
if test "$?" != "0" ; then
AC_MSG_RESULT(no)
- AC_MSG_ERROR(user $user does not exist)
+ AC_MSG_ERROR(user $user does not exist)
else
AC_MSG_RESULT(yes)
fi
|
[-]
[+]
|
Added |
mod_gearman-1.0.tar.bz2/docs
^
|
+(directory)
|
[-]
[+]
|
Added |
mod_gearman-1.0.tar.bz2/docs/QUICKSTART
^
|
@@ -0,0 +1,181 @@
+Mod-Gearman Quickstart Guide
+============================
+
+This quickstart guide was written for Debian Lenny (5.0) but probably works with
+different Linux systems too. As there are currently no packages for Gearman
+and Mod-Gearman, we have to install them from source.
+
+This guide assumes you have a basic nagios system running.
+
+All commands have to be executed as root.
+
+
+Build Preparation
+-----------------
+We need a couple of packages for building Gearman and Mod-Gearman:
+======
+ #> apt-get install autoconf automake make gcc g++ wget tar file netcat uuid-dev libltdl3-dev libncurses5-dev
+======
+
+We will install Gearman in '/opt' to make later removal easier. For example if
+there will be a Debian package sometimes. This keeps your base system clean from
+non-packaged software, but in order to make that work, we have to add '/opt/lib' to
+the ld lib path.
+
+======
+ #> echo "/opt/lib" > /etc/ld.so.conf.d/opt_lib.conf
+ #> ldconfig
+======
+
+
+Install Libevent
+---------------
+Debian 5.0 ships libevent 1.3, but Gearman requires at least 1.4. So we have to
+install the 'libevent-dev' from the debian backports.
+======
+ #> echo "deb http://backports.debian.org/debian-backports lenny-backports main" >> /etc/apt/sources.list
+ #> apt-get update
+ #> apt-get -t lenny-backports install libevent-dev
+======
+
+
+
+
+Install Gearman
+---------------
+We need at least Gearman version >= 0.14. Execute the following steps to
+install Gearman from source.
+======
+ #> cd /tmp
+ #> wget "http://launchpad.net/gearmand/trunk/0.14/+download/gearmand-0.14.tar.gz"
+ #> tar zxf gearmand-0.14.tar.gz
+ #> cd gearmand-0.14
+ #> ./configure --prefix=/opt
+ #> make
+ #> make install
+======
+
+
+Mod-Gearman
+-----------
+
+Half way done, the next step installs Mod-Gearman.
+======
+ #> cd /tmp
+ #> wget "http://labs.consol.de/wp-content/uploads/2010/09/mod_gearman-1.0.tar.gz"
+ #> tar zxf mod_gearman-1.0.tar.gz
+ #> cd mod_gearman-1.0
+ #> ./configure --prefix=/opt --with-gearman=/opt --with-user=nagios --with-init-dir=/etc/init.d
+ #> make
+ #> make install
+ #> make install-config
+ #> cp ./extras/gearmand-init /etc/init.d/gearmand
+======
+
+
+Gearman runs as user nagios which needs a valid shell:
+======
+ #> chsh nagios
+Changing the login shell for nagios
+Enter the new value, or press ENTER for the default
+ Login Shell [/bin/false]: /bin/bash
+======
+
+
+Starting Up
+-----------
+Now we can start the Gearman daemon and our Mod-Gearman worker:
+======
+ #> /etc/init.d/gearmand start
+Starting gearmand done
+ #> /etc/init.d/gearmand status
+gearmand is running with pid 31869
+ #> /etc/init.d/mod_gearman_worker start
+Starting mod_gm_worker done
+ #> /etc/init.d/mod_gearman_worker status
+mod_gm_worker is running with pid 31939
+======
+
+
+Nagios Configuration
+--------------------
+Open your nagios.cfg and enable eventbroker. When using the packaged nagios3
+from Debian the file is located at /etc/nagios3/nagios.cfg.
+-----
+ event_broker_options=-1
+ broker_module=/opt/lib/mod_gearman/mod_gearman.o config=/opt/etc/mod_gearman.conf
+-----
+
+and finally restart nagios:
+======
+ #> /etc/init.d/nagios3 restart
+Restarting nagios3 monitoring daemon: nagios3
+.
+======
+
+Your nagios.log should contain a line:
+======
+ #> grep mod_gearman /var/log/nagios3/nagios.log
+ [1295003042] mod_gearman: Version 1.0
+ [1295003042] Event broker module '/opt/lib/mod_gearman/mod_gearman.o' initialized successfully.
+======
+
+
+
+
+Testing
+-------
+We can perform a few tests to see if everything is up and running.
+
+Gearman-Top
+~~~~~~~~~~~
+
+First we have a look at '/opt/bin/gearman_top'. You should have at least one
+worker for each queue.
+
+-----
+ 2011-01-07 23:23:24 - localhost:4730 - v0.14
+
+ Queue Name | Worker Available | Jobs Waiting | Jobs Running
+ ------------------------------------------------------------------
+ check_results | 1 | 0 | 0
+ eventhandler | 1 | 0 | 0
+ host | 1 | 0 | 0
+ service | 1 | 0 | 0
+ worker_debian64 | 1 | 0 | 0
+ ------------------------------------------------------------------
+-----
+
+Check-Gearman
+~~~~~~~~~~~~~
+
+Then we have a look at the shiped check plugin:
+
+======
+ #> /opt/bin/check_gearman -H localhost -q worker_`hostname` -t 10 -s check
+check_gearman OK - debian64 has 1 worker and is working on 0 jobs. Version: 1.0|worker=1 jobs=2c
+======
+The interesting number is the last one, '2c' in our case, which means there
+have been already 2 jobs executed by this worker.
+
+
+
+Troubleshooting
+---------------
+
+First check if everything is up and running:
+
+======
+ #> /etc/init.d/nagios3 status
+checking /usr/sbin/nagios3...done (running).
+ #> /etc/init.d/gearmand status
+gearmand is running with pid 31921
+ #> /etc/init.d/mod_gearman_worker status
+mod_gm_worker is running with pid 31939
+======
+
+If one of them is not running, try to start it or check the logfiles for possible error messages.
+
+ - Nagios: /var/log/nagios3/nagios.log
+ - Gearmand: /opt/var/mod_gearman/gearmand.log
+ - Mod-Gearman Worker: /opt/var/mod_gearman/mod_gearman_worker.log
|
[-]
[+]
|
Added |
mod_gearman-1.0.tar.bz2/docs/QUICKSTART.html
^
|
@@ -0,0 +1,777 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<meta name="generator" content="AsciiDoc 8.5.2" />
+<title>Mod-Gearman Quickstart Guide</title>
+<style type="text/css">
+/* Debug borders */
+p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
+/*
+ border: 1px solid red;
+*/
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: navy;
+}
+
+strong {
+ font-weight: bold;
+ color: #083194;
+}
+
+tt {
+ color: navy;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ font-family: sans-serif;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+
+div.sectionbody {
+ font-family: serif;
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+
+pre {
+ padding: 0;
+ margin: 0;
+}
+
+span#author {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+span#email {
+}
+span#revnumber, span#revdate, span#revremark {
+ font-family: sans-serif;
+}
+
+div#footer {
+ font-family: sans-serif;
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+div#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+div#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+div#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.0em;
+ margin-bottom: 2.0em;
+ margin-right: 10%;
+ color: #606060;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid silver;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid silver;
+ background: #f4f4f4;
+ padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+ padding-left: 1.0em;
+ margin-left: 1.0em;
+ margin-right: 10%;
+ border-left: 5px solid #dddddd;
+ color: #777777;
+}
+
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock > div.content {
+ white-space: pre;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: navy;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead, p.table.header {
+ font-family: sans-serif;
+ font-weight: bold;
+}
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overriden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ color: navy;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+.footnote, .footnoteref {
+ font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+ vertical-align: super;
+}
+
+#footnotes {
+ margin: 20px 0 20px 0;
+ padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+ margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+ border: none;
+ border-top: 1px solid silver;
+ height: 1px;
+ text-align: left;
+ margin-left: 0;
+ width: 20%;
+ min-width: 100px;
+}
+
+
+@media print {
+ div#footer-badges { display: none; }
+}
+
+div#toc {
+ margin-bottom: 2.5em;
+}
+
+div#toctitle {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+/* Workarounds for IE6's broken and incomplete CSS2. */
+
+div.sidebar-content {
+ background: #ffffee;
+ border: 1px solid silver;
+ padding: 0.5em;
+}
+div.sidebar-title, div.image-title {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ margin-top: 0.0em;
+ margin-bottom: 0.5em;
+}
+
+div.listingblock div.content {
+ border: 1px solid silver;
+ background: #f4f4f4;
+ padding: 0.5em;
+}
+
+div.quoteblock-attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock-content {
+ white-space: pre;
+}
+div.verseblock-attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+
+div.exampleblock-content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+/* IE6 sets dynamically generated links as visited. */
+div#toc a:visited { color: blue; }
+</style>
+<script type="text/javascript">
+/*<![CDATA[*/
+window.onload = function(){asciidoc.footnotes(); asciidoc.toc(2);}
+var asciidoc = { // Namespace.
+
+/////////////////////////////////////////////////////////////////////
+// Table Of Contents generator
+/////////////////////////////////////////////////////////////////////
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
+
+// toclevels = 1..4.
+toc: function (toclevels) {
+
+ function getText(el) {
+ var text = "";
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
+ text += i.data;
+ else if (i.firstChild != null)
+ text += getText(i);
+ }
+ return text;
+ }
+
+ function TocEntry(el, text, toclevel) {
+ this.element = el;
+ this.text = text;
+ this.toclevel = toclevel;
+ }
+
+ function tocEntries(el, toclevels) {
+ var result = new Array;
+ var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
+ // Function that scans the DOM tree for header elements (the DOM2
+ // nodeIterator API would be a better technique but not supported by all
+ // browsers).
+ var iterate = function (el) {
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+ var mo = re.exec(i.tagName);
+ if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
+ result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
+ }
+ iterate(i);
+ }
+ }
+ }
+ iterate(el);
+ return result;
+ }
+
+ var toc = document.getElementById("toc");
+ var entries = tocEntries(document.getElementById("content"), toclevels);
+ for (var i = 0; i < entries.length; ++i) {
+ var entry = entries[i];
+ if (entry.element.id == "")
+ entry.element.id = "_toc_" + i;
+ var a = document.createElement("a");
+ a.href = "#" + entry.element.id;
+ a.appendChild(document.createTextNode(entry.text));
+ var div = document.createElement("div");
+ div.appendChild(a);
+ div.className = "toclevel" + entry.toclevel;
+ toc.appendChild(div);
+ }
+ if (entries.length == 0)
+ toc.parentNode.removeChild(toc);
+},
+
+
+/////////////////////////////////////////////////////////////////////
+// Footnotes generator
+/////////////////////////////////////////////////////////////////////
+
+/* Based on footnote generation code from:
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
+ */
+
+footnotes: function () {
+ var cont = document.getElementById("content");
+ var noteholder = document.getElementById("footnotes");
+ var spans = cont.getElementsByTagName("span");
+ var refs = {};
+ var n = 0;
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnote") {
+ n++;
+ // Use [\s\S] in place of . so multi-line matches work.
+ // Because JavaScript has no s (dotall) regex flag.
+ note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
+ noteholder.innerHTML +=
+ "<div class='footnote' id='_footnote_" + n + "'>" +
+ "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
+ n + "</a>. " + note + "</div>";
+ spans[i].innerHTML =
+ "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ var id =spans[i].getAttribute("id");
+ if (id != null) refs["#"+id] = n;
+ }
+ }
+ if (n == 0)
+ noteholder.parentNode.removeChild(noteholder);
+ else {
+ // Process footnoterefs.
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnoteref") {
+ var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
+ href = href.match(/#.*/)[0]; // Because IE return full URL.
+ n = refs[href];
+ spans[i].innerHTML =
+ "[<a href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ }
+ }
+ }
+}
+
+}
+/*]]>*/
+</script>
+</head>
+<body style="max-width:800">
+<div id="header">
+<h1>Mod-Gearman Quickstart Guide</h1>
+<div id="toc">
+ <div id="toctitle">Table of Contents</div>
+ <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
+</div>
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div class="paragraph"><p>This quickstart guide was written for Debian Lenny (5.0) but probably works with
+different Linux systems too. As there are currently no packages for Gearman
+and Mod-Gearman, we have to install them from source.</p></div>
+<div class="paragraph"><p>This guide assumes you have a basic nagios system running.</p></div>
+<div class="paragraph"><p>All commands have to be executed as root.</p></div>
+</div>
+</div>
+<h2 id="_build_preparation">Build Preparation</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>We need a couple of packages for building Gearman and Mod-Gearman:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt>#> apt-get install autoconf automake make gcc g++ wget tar file netcat uuid-dev libltdl3-dev libncurses5-dev</tt></pre>
+</div></div>
+</div></div>
+<div class="paragraph"><p>We will install Gearman in <em>/opt</em> to make later removal easier. For example if
+there will be a Debian package sometimes. This keeps your base system clean from
+non-packaged software, but in order to make that work, we have to add <em>/opt/lib</em> to
+the ld lib path.</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt>#> echo "/opt/lib" > /etc/ld.so.conf.d/opt_lib.conf
+#> ldconfig</tt></pre>
+</div></div>
+</div></div>
+</div>
+<h2 id="_install_libevent">Install Libevent</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Debian 5.0 ships libevent 1.3, but Gearman requires at least 1.4. So we have to
+install the <em>libevent-dev</em> from the debian backports.</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt>#> echo "deb http://backports.debian.org/debian-backports lenny-backports main" >> /etc/apt/sources.list
+#> apt-get update
+#> apt-get -t lenny-backports install libevent-dev</tt></pre>
+</div></div>
+</div></div>
+</div>
+<h2 id="_install_gearman">Install Gearman</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>We need at least Gearman version >= 0.14. Execute the following steps to
+install Gearman from source.</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt>#> cd /tmp
+#> wget "http://launchpad.net/gearmand/trunk/0.14/+download/gearmand-0.14.tar.gz"
+#> tar zxf gearmand-0.14.tar.gz
+#> cd gearmand-0.14
+#> ./configure --prefix=/opt
+#> make
+#> make install</tt></pre>
+</div></div>
+</div></div>
+</div>
+<h2 id="_mod_gearman">Mod-Gearman</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Half way done, the next step installs Mod-Gearman.</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt>#> cd /tmp
+#> wget "http://labs.consol.de/wp-content/uploads/2010/09/mod_gearman-1.0.tar.gz"
+#> tar zxf mod_gearman-1.0.tar.gz
+#> cd mod_gearman-1.0
+#> ./configure --prefix=/opt --with-gearman=/opt --with-user=nagios --with-init-dir=/etc/init.d
+#> make
+#> make install
+#> make install-config
+#> cp ./extras/gearmand-init /etc/init.d/gearmand</tt></pre>
+</div></div>
+</div></div>
+<div class="paragraph"><p>Gearman runs as user nagios which needs a valid shell:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt> #> chsh nagios
+Changing the login shell for nagios
+Enter the new value, or press ENTER for the default
+ Login Shell [/bin/false]: /bin/bash</tt></pre>
+</div></div>
+</div></div>
+</div>
+<h2 id="_starting_up">Starting Up</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Now we can start the Gearman daemon and our Mod-Gearman worker:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt> #> /etc/init.d/gearmand start
+Starting gearmand done
+ #> /etc/init.d/gearmand status
+gearmand is running with pid 31869
+ #> /etc/init.d/mod_gearman_worker start
+Starting mod_gm_worker done
+ #> /etc/init.d/mod_gearman_worker status
+mod_gm_worker is running with pid 31939</tt></pre>
+</div></div>
+</div></div>
+</div>
+<h2 id="_nagios_configuration">Nagios Configuration</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Open your nagios.cfg and enable eventbroker. When using the packaged nagios3
+from Debian the file is located at /etc/nagios3/nagios.cfg.</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt> event_broker_options=-1
+ broker_module=/opt/lib/mod_gearman/mod_gearman.o config=/opt/etc/mod_gearman.conf</tt></pre>
+</div></div>
+<div class="paragraph"><p>and finally restart nagios:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt> #> /etc/init.d/nagios3 restart
+Restarting nagios3 monitoring daemon: nagios3
+.</tt></pre>
+</div></div>
+</div></div>
+<div class="paragraph"><p>Your nagios.log should contain a line:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt>#> grep mod_gearman /var/log/nagios3/nagios.log
+[1295003042] mod_gearman: Version 1.0
+[1295003042] Event broker module '/opt/lib/mod_gearman/mod_gearman.o' initialized successfully.</tt></pre>
+</div></div>
+</div></div>
+</div>
+<h2 id="_testing">Testing</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>We can perform a few tests to see if everything is up and running.</p></div>
+<h3 id="_gearman_top">Gearman-Top</h3><div style="clear:left"></div>
+<div class="paragraph"><p>First we have a look at <em>/opt/bin/gearman_top</em>. You should have at least one
+worker for each queue.</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt> 2011-01-07 23:23:24 - localhost:4730 - v0.14
+
+ Queue Name | Worker Available | Jobs Waiting | Jobs Running
+ ------------------------------------------------------------------
+ check_results | 1 | 0 | 0
+ eventhandler | 1 | 0 | 0
+ host | 1 | 0 | 0
+ service | 1 | 0 | 0
+ worker_debian64 | 1 | 0 | 0
+ ------------------------------------------------------------------</tt></pre>
+</div></div>
+<h3 id="_check_gearman">Check-Gearman</h3><div style="clear:left"></div>
+<div class="paragraph"><p>Then we have a look at the shiped check plugin:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt> #> /opt/bin/check_gearman -H localhost -q worker_`hostname` -t 10 -s check
+check_gearman OK - debian64 has 1 worker and is working on 0 jobs. Version: 1.0|worker=1 jobs=2c</tt></pre>
+</div></div>
+</div></div>
+<div class="paragraph"><p>The interesting number is the last one, <em>2c</em> in our case, which means there
+have been already 2 jobs executed by this worker.</p></div>
+</div>
+<h2 id="_troubleshooting">Troubleshooting</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>First check if everything is up and running:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt> #> /etc/init.d/nagios3 status
+checking /usr/sbin/nagios3...done (running).
+ #> /etc/init.d/gearmand status
+gearmand is running with pid 31921
+ #> /etc/init.d/mod_gearman_worker status
+mod_gm_worker is running with pid 31939</tt></pre>
+</div></div>
+</div></div>
+<div class="paragraph"><p>If one of them is not running, try to start it or check the logfiles for possible error messages.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Nagios: /var/log/nagios3/nagios.log
+</p>
+</li>
+<li>
+<p>
+Gearmand: /opt/var/mod_gearman/gearmand.log
+</p>
+</li>
+<li>
+<p>
+Mod-Gearman Worker: /opt/var/mod_gearman/mod_gearman_worker.log
+</p>
+</li>
+</ul></div>
+</div>
+</div>
+<div id="footnotes"><hr /></div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2011-02-02 00:21:45 CEST
+</div>
+</div>
+</body>
+</html>
|
[-]
[+]
|
Added |
mod_gearman-1.0.tar.bz2/docs/README.html
^
|
@@ -0,0 +1,2208 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<meta name="generator" content="AsciiDoc 8.5.2" />
+<title>Gearman Module for Nagios</title>
+<style type="text/css">
+/* Debug borders */
+p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
+/*
+ border: 1px solid red;
+*/
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: navy;
+}
+
+strong {
+ font-weight: bold;
+ color: #083194;
+}
+
+tt {
+ color: navy;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ font-family: sans-serif;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+
+div.sectionbody {
+ font-family: serif;
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+
+pre {
+ padding: 0;
+ margin: 0;
+}
+
+span#author {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+span#email {
+}
+span#revnumber, span#revdate, span#revremark {
+ font-family: sans-serif;
+}
+
+div#footer {
+ font-family: sans-serif;
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+div#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+div#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+div#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.0em;
+ margin-bottom: 2.0em;
+ margin-right: 10%;
+ color: #606060;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid silver;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid silver;
+ background: #f4f4f4;
+ padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+ padding-left: 1.0em;
+ margin-left: 1.0em;
+ margin-right: 10%;
+ border-left: 5px solid #dddddd;
+ color: #777777;
+}
+
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock > div.content {
+ white-space: pre;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: navy;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead, p.table.header {
+ font-family: sans-serif;
+ font-weight: bold;
+}
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overriden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ color: navy;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+.footnote, .footnoteref {
+ font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+ vertical-align: super;
+}
+
+#footnotes {
+ margin: 20px 0 20px 0;
+ padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+ margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+ border: none;
+ border-top: 1px solid silver;
+ height: 1px;
+ text-align: left;
+ margin-left: 0;
+ width: 20%;
+ min-width: 100px;
+}
+
+
+@media print {
+ div#footer-badges { display: none; }
+}
+
+div#toc {
+ margin-bottom: 2.5em;
+}
+
+div#toctitle {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+/* Workarounds for IE6's broken and incomplete CSS2. */
+
+div.sidebar-content {
+ background: #ffffee;
+ border: 1px solid silver;
+ padding: 0.5em;
+}
+div.sidebar-title, div.image-title {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ margin-top: 0.0em;
+ margin-bottom: 0.5em;
+}
+
+div.listingblock div.content {
+ border: 1px solid silver;
+ background: #f4f4f4;
+ padding: 0.5em;
+}
+
+div.quoteblock-attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock-content {
+ white-space: pre;
+}
+div.verseblock-attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+
+div.exampleblock-content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+/* IE6 sets dynamically generated links as visited. */
+div#toc a:visited { color: blue; }
+</style>
+<script type="text/javascript">
+/*<![CDATA[*/
+window.onload = function(){asciidoc.footnotes(); asciidoc.toc(2);}
+var asciidoc = { // Namespace.
+
+/////////////////////////////////////////////////////////////////////
+// Table Of Contents generator
+/////////////////////////////////////////////////////////////////////
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
+
+// toclevels = 1..4.
+toc: function (toclevels) {
+
+ function getText(el) {
+ var text = "";
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
+ text += i.data;
+ else if (i.firstChild != null)
+ text += getText(i);
+ }
+ return text;
+ }
+
+ function TocEntry(el, text, toclevel) {
+ this.element = el;
+ this.text = text;
+ this.toclevel = toclevel;
+ }
+
+ function tocEntries(el, toclevels) {
+ var result = new Array;
+ var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
+ // Function that scans the DOM tree for header elements (the DOM2
+ // nodeIterator API would be a better technique but not supported by all
+ // browsers).
+ var iterate = function (el) {
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+ var mo = re.exec(i.tagName);
+ if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
+ result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
+ }
+ iterate(i);
+ }
+ }
+ }
+ iterate(el);
+ return result;
+ }
+
+ var toc = document.getElementById("toc");
+ var entries = tocEntries(document.getElementById("content"), toclevels);
+ for (var i = 0; i < entries.length; ++i) {
+ var entry = entries[i];
+ if (entry.element.id == "")
+ entry.element.id = "_toc_" + i;
+ var a = document.createElement("a");
+ a.href = "#" + entry.element.id;
+ a.appendChild(document.createTextNode(entry.text));
+ var div = document.createElement("div");
+ div.appendChild(a);
+ div.className = "toclevel" + entry.toclevel;
+ toc.appendChild(div);
+ }
+ if (entries.length == 0)
+ toc.parentNode.removeChild(toc);
+},
+
+
+/////////////////////////////////////////////////////////////////////
+// Footnotes generator
+/////////////////////////////////////////////////////////////////////
+
+/* Based on footnote generation code from:
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
+ */
+
+footnotes: function () {
+ var cont = document.getElementById("content");
+ var noteholder = document.getElementById("footnotes");
+ var spans = cont.getElementsByTagName("span");
+ var refs = {};
+ var n = 0;
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnote") {
+ n++;
+ // Use [\s\S] in place of . so multi-line matches work.
+ // Because JavaScript has no s (dotall) regex flag.
+ note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
+ noteholder.innerHTML +=
+ "<div class='footnote' id='_footnote_" + n + "'>" +
+ "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
+ n + "</a>. " + note + "</div>";
+ spans[i].innerHTML =
+ "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ var id =spans[i].getAttribute("id");
+ if (id != null) refs["#"+id] = n;
+ }
+ }
+ if (n == 0)
+ noteholder.parentNode.removeChild(noteholder);
+ else {
+ // Process footnoterefs.
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnoteref") {
+ var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
+ href = href.match(/#.*/)[0]; // Because IE return full URL.
+ n = refs[href];
+ spans[i].innerHTML =
+ "[<a href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ }
+ }
+ }
+}
+
+}
+/*]]>*/
+</script>
+</head>
+<body style="max-width:800">
+<div id="header">
+<h1>Gearman Module for Nagios</h1>
+<div id="toc">
+ <div id="toctitle">Table of Contents</div>
+ <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
+</div>
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div class="paragraph"><p>Mod_Gearman (<a href="http://labs.consol.de/nagios/mod-gearman">http://labs.consol.de/nagios/mod-gearman</a>) is a new
+way of distributing active Nagios checks across your network. It
+consists of two parts: There is a NEB module which resides in the
+Nagios core and adds servicechecks, hostchecks and eventhandler to a
+Gearman (<a href="http://gearman.org">http://gearman.org</a>) queue. There can be multiple equal
+gearman servers. The counterpart is one or more worker clients for
+the checks itself. They can be bound to host and servicegroups.</p></div>
+</div>
+</div>
+<h2 id="_support_amp_questions">Support & Questions</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Please use the following google groups mailinglist for support or
+questions: <a href="https://groups.google.com/group/mod_gearman">https://groups.google.com/group/mod_gearman</a></p></div>
+</div>
+<h2 id="_how_does_it_work">How does it work</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>When the broker module is loaded, it captures all servicecheck,
+hostcheck and the eventhandler events. Eventhandler are sent to a
+generic <em>eventhandler</em> queue. Checks for hosts which are in one of the
+specified hostgroups, are sent into a seperate hostgroup queue. All
+non matching hosts are sent to a generic <em>hosts</em> queue. Checks for
+services are first checked against the list of servicegroups, then
+against the hostgroups and if none matches they will be sent into a
+generic <em>service</em> queue.
+The NEB module starts a single thread, which monitors the
+<em>check_results</em> where all results come in.</p></div>
+<div class="paragraph"><p><span class="image">
+<img alt="Workflow" src="data:image/png;base64,
+iVBORw0KGgoAAAANSUhEUgAAA8AAAAJYCAMAAACaSn8zAAAAAXNSR0IArs4c6QAAAitQTFRFAAAA
+OF2KOF6MOl+NOV6NOmCPPmaXPWSUPmeYPmKOO2KSO2GRPWWWOmCNPmKPP2mcPWeYPGSVP2ibPGOU
+OmCOP2qdTU1NUXGZQGqcQWudS2yVQGiaV3acQGWSQWyfRWqYQ2iVS3GeRWeRXnygQ2+jSHatSXix
+S3qzTH22RnKoTHy1Tn+6Q22hSnmxTX64RHClRnOqSXevRXGmQ26iWH6rUHajR3SrVHimVnupSn67
+Sn25RnavRXWvRXKsSXmzQm2iSny5TH69Q2+mT4G9T4C7XoOyW4CvToG9V4G2ToHDUorOVY7VVI3S
+UYjLToPEUITHTYDAVIvRaGhofHx8aoaocIurfZWzd5CvZIGkaY67a5G+Y4m2YYa0eJ7NbpPCc5nH
+eJ/MYY7Ee6DPfqPSjIyMmpqag5q2iZ+6kKS+m67ElqnBl7TYia/egafVhqzbg6nYjq/VjrTjjLHg
+mrzmvb29srKyp6enqLjLobPIrr3Ppb7dpL7dusfWtMLTvMrbsMbhuc3lvNPuu87lsszsqMXpvNLu
+wcza2dnZ0NDQx8fHx9He09vlzdbi0d7uwtToytnrzN3yxdjx0t/uxNjx2uDp2OPx3+jz3ej32OX1
+0uH02ub20+L05uvw4Obt+fr77PD08PDw4eHh6enp8/X4+vz96vD39fj75ez18PT58vb8/P3+4uz4
+9fn9+Pv95u/56vH67vT76O/26/L6+vz+8PX74Or35u759fj9////L4QIjwAAAAFiS0dEAIgFHUgA
+AAAJcEhZcwAADsQAAA7EAZUrDhsAAAAHdElNRQfaCQ4JAhpSOyDcAAAgAElEQVR42u2d+WMc5Znn
+q+xBYJzZYzLbBoclu7YQ5owDs9llM8lkVt7ZJUomG7UN7DE5diQHodmdMGq1iQLbIpKRBJYsMBZg
+G6OWJVs+wETn++fte9TVrVbf1V3H5/uDuqrft0vP877vp96z6rUEQii2skgChAAYIQTACCEARgiA
+EUIAjBACYIQQACMEwAghAEYIATBCAIwQAmCEEAAjhAAYIQBGCAEwQgiAEUIAjBAAI4QAGCEEwAgB
+MEIIgBFCAIwQAuB6de3cyNnTCJXpzMhbnwNw1PX5yHEboX105PWPATjKle8rlFFUXac/AOCI6vrr
+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
+SPly1XmHYgAAAABJRU5ErkJggg==" />
+</span></p></div>
+<div class="paragraph"><p>A simple example queue would look like:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt>+---------------+------------------+--------------+--------------+
+| Queue Name | Worker Available | Jobs Waiting | Jobs Running |
++---------------+------------------+--------------+--------------+
+| check_results | 1 | 0 | 0 |
+| host | 50 | 0 | 1 |
+| service | 50 | 0 | 13 |
+| eventhandler | 50 | 0 | 0 |
++---------------+------------------+--------------+--------------+</tt></pre>
+</div></div>
+</div></div>
+<div class="paragraph"><p>There is one queue for the results and two for the checks plus the
+eventhandler.</p></div>
+<div class="paragraph"><p>The workflow is simple:</p></div>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+Nagios wants to execute a service check.
+</p>
+</li>
+<li>
+<p>
+The check is intercepted by the mod_gearman neb module.
+</p>
+</li>
+<li>
+<p>
+mod_gearman puts the job into the <em>service</em> queue.
+</p>
+</li>
+<li>
+<p>
+a worker grabs the job and puts back the result into the
+ <em>check_results</em> queue
+</p>
+</li>
+<li>
+<p>
+mod_gearman grabs the result job and puts back the result onto the
+ check result list
+</p>
+</li>
+<li>
+<p>
+The reaper reads all checks from the result list and updates hosts / services
+</p>
+</li>
+</ol></div>
+<div class="paragraph"><p>You can set some host or servicegroups for special worker. This
+example uses a seperate hostgroup for Japan and a seperate
+servicegroup for jmx4perl.</p></div>
+<div class="paragraph"><p>It would look like this:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt>+-----------------------+------------------+--------------+--------------+
+| Queue Name | Worker Available | Jobs Waiting | Jobs Running |
++-----------------------+------------------+--------------+--------------+
+| check_results | 1 | 0 | 0 |
+| host | 50 | 0 | 1 |
+| service | 50 | 0 | 13 |
+| servicegroup_jmx4perl | 3 | 0 | 3 |
+| hostgroup_japan | 3 | 1 | 3 |
+| eventhandler | 50 | 0 | 0 |
++-----------------------+------------------+--------------+--------------+</tt></pre>
+</div></div>
+</div></div>
+<div class="paragraph"><p>You still have the generic queues and in addition there are two queues
+for the specific groups.</p></div>
+<div class="paragraph"><p>The worker processes will take jobs from the queues and put the result
+back into the check_result queue which will then be taken back by the
+neb module and put back into the nagios core. A worker can work on one
+or more queues. So you could start a worker which only handles the
+<em>hostgroup_japan</em> group. One worker for the <em>jmx4perl</em> checks and one
+worker which covers the other queues. There can be more than one
+worker on each queue to share the load.</p></div>
+</div>
+<h2 id="_installation">Installation</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Pre Requirements:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+gcc / g++
+</p>
+</li>
+<li>
+<p>
+autoconf / automake / autoheader
+</p>
+</li>
+<li>
+<p>
+libtool
+</p>
+</li>
+<li>
+<p>
+libgearman (>= 0.14)
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>Download the tarball and perform the following steps:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt> #> ./configure
+ #> make
+ #> make install</tt></pre>
+</div></div>
+<div class="paragraph"><p>Then add the mod_gearman.o to your nagios installation and add a
+broker line to your nagios.cfg:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt>broker_module=.../mod_gearman.o server=localhost:4730 eventhandler=yes services=yes hosts=yes</tt></pre>
+</div></div>
+</div></div>
+<div class="paragraph"><p>see <a href="#_configuration">Configuration</a> for details on all parameters</p></div>
+<div class="paragraph"><p>The last step is to start one or more worker. You may use the same
+configuration file as for the neb module.</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt>./mod_gearman_worker --server=localhost:4730 --services --hosts</tt></pre>
+</div></div>
+</div></div>
+<div class="paragraph"><p>or use the supplied init script.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img alt="Note" src="data:image/png;base64,
+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" />
+</td>
+<td class="content">Make sure you have started your gearmand job server. Usually
+it can be started with</td>
+</tr></table>
+</div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt>/usr/sbin/gearmand -t 10 -j 0</tt></pre>
+</div></div>
+</div></div>
+<div class="paragraph"><p>or a supplied init script (extras/gearmand-init).</p></div>
+<h3 id="_patch_nagios">Patch Nagios</h3><div style="clear:left"></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img alt="Note" src="data:image/png;base64,
+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" />
+</td>
+<td class="content">The needed patch is already included since Nagios 3.2.2. Use the patch if you
+use an older version.</td>
+</tr></table>
+</div>
+<div class="paragraph"><p>It is not possible to distribute eventhandler with Nagios versions
+prior 3.2.2. Just apply the patch from the patches directory to your
+Nagios sources and build Nagios again if you want to use an older
+version. You only need to replace the nagios binary. Nothing else has
+changed. If you plan to distribute only Host/Servicechecks, no patch
+is needed.</p></div>
+</div>
+<h2 id="_configuration">Configuration</h2>
+<div class="sectionbody">
+<h3 id="_neb_module">NEB Module</h3><div style="clear:left"></div>
+<div class="paragraph"><p>A sample broker in your nagios.cfg could look like:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt>broker_module=/usr/local/share/nagios/mod_gearman.o keyfile=/usr/local/share/nagios/secret.txt server=localhost eventhandler=yes hosts=yes services=yes</tt></pre>
+</div></div>
+</div></div>
+<div class="paragraph"><p>See the following list for a detailed explaination of available
+options:</p></div>
+<div class="paragraph"><p>Shared options for worker and the NEB module:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>config: read config from this file. Options are the same
+ like described here.
+
+ Example: config=/etc/nagios3/mod_gm_worker.conf
+
+
+debug: use debug to increase the verbosity of the module.
+ Possible values are:
+ 0 = only errors
+ 1 = debug messages
+ 2 = trace messages
+ 3 = trace and all gearman related logs are going to stdout.
+ Default is 0.
+
+ Example: debug=1
+
+
+server: sets the address of your gearman job server. Can be specified
+ more than once to add more server. Gearman uses
+ the first one available.
+
+ Example: server=localhost:4730,remote_host:4730
+
+
+eventhandler: defines if the module should distribute execution of
+ eventhandlers.
+
+ Example: eventhandler=yes
+
+
+services: defines if the module should distribute execution of
+ service checks.
+
+ Example: services=yes
+
+
+hosts: defines if the module should distribute execution of
+ host checks.
+
+ Example: hosts=yes
+
+
+hostgroups: sets a list of hostgroups which will go into seperate
+ queues.
+
+ Example: hostgroups=name1,name2,name3
+
+
+servicegroups: sets a list of servicegroups which will go into seperate
+ queues.
+
+ Example: servicegroups=name1,name2,name3
+
+
+encryption: enables or disables encryption. It is strongly
+ advised to not disable encryption. Anybody will be
+ able to inject packages to your worker.
+ Encryption is enabled by default and you have to
+ explicitly disable it.
+ When using encryption, you will either have to
+ specify a shared password with key=... or a
+ keyfile with keyfile=...
+ Default is On.
+
+ Example: encryption=yes
+
+
+key: A shared password which will be used for
+ encryption of data pakets. Should be at least 8
+ bytes long. Maximum length is 32 characters.
+
+ Example: key=secret
+
+
+keyfile: The shared password will be read from this file.
+ Use either key or keyfile. Only the first 32
+ characters will be used.
+
+ Example: keyfile=/path/to/secret.file</tt></pre>
+</div></div>
+<div class="paragraph"><p>Additional options for the NEB module:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>localhostgroups: sets a list of hostgroups which will not be executed
+ by gearman. They are just passed through.
+
+ Example: localhostgroups=name1,name2,name3
+
+
+localservicegroups: sets a list of servicegroups which will not be executed
+ by gearman. They are just passed through.
+
+ Example: localservicegroups=name1,name2,name3
+
+
+result_workers Number of result worker threads. Usually one is
+ enough. You may increase the value if your
+ result queue is not processed fast enough.
+
+ Example: result_workers=3
+
+
+perfdata: defines if the module should distribute perfdata
+ to gearman.
+ Note: processing of perfdata is not part of
+ mod_gearman. You will need additional worker for
+ handling performance data. For example: pnp4nagios
+ Performance data is just written to the gearman
+ queue.
+
+ Example: perfdata=yes
+
+result_queue: sets the result queue. Necessary when putting jobs
+ from several nagios instances into the same
+ gearman queues.
+ Default: check_results
+
+ Example: result_queue=check_results_nagios1</tt></pre>
+</div></div>
+<div class="paragraph"><p>Additional options for worker:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>identifier: Identifier for this worker. Will be used for the
+ 'worker_identifier' queue for status requests. You
+ may want to change it if you are using more than
+ one worker on a single host.
+ Default: current hostname
+
+ Example: identifier=hostname_test
+
+
+pidfile: Path to the pidfile.
+
+ Example: pidfile=/path/to/pid.file
+
+
+logfile: Path to the logfile.
+
+ Example: logfile=/path/to/log.file
+
+
+min-worker: Minimum number of worker processes which should
+ run at any time.
+ Default: 1
+
+ Example: min-worker=1
+
+
+max-worker: Maximum number of worker processes which should
+ run at any time. You may set this equal to
+ min-worker setting to disable dynamic starting of
+ workers. When setting this to 1, all services from
+ this worker will be executed one after another.
+ Default: 20
+
+ Example: max-worker=20
+
+
+idle-timeout: Time after which an idling worker exists. This
+ parameter controls how fast your waiting workers
+ will exit if there are no jobs waiting. Set to 0
+ to disable the idle timeout.
+ Default: 10
+
+ Example: idle-timeout=30
+
+
+max-jobs: Controls the amount of jobs a worker will do
+ before he exits. Use this to control how fast the
+ amount of workers will go down after high load
+ times. Disabled when set to 0.
+ Default: 1000
+
+ Example: max-jobs=500
+
+fork_on_exec: Use this option to disable an extra fork for each
+ plugin execution. This option will reduce the load
+ on the worker host.
+ Default: yes
+
+ Example: fork_on_exec=no
+
+dup_server: sets the address of gearman job server where
+ duplicated result will be sent to. Can be specified
+ more than once to add more server.
+ Useful for duplicating results for a reporting
+ installation or remote gui.
+
+ Example: dup_server=logserver:4730,logserver2:4730</tt></pre>
+</div></div>
+</div>
+<h2 id="_queue_names">Queue Names</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>You may want to watch your gearman server job queue. The shipped
+tools/queue_top.pl does this. It polls the gearman server every second
+and displays the current queue statistics.</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content">
+<div class="literalblock">
+<div class="content">
+<pre><tt>+-----------------------+--------+-------+-------+---------+
+| Name | Worker | Avail | Queue | Running |
++-----------------------+--------+-------+-------+---------+
+| check_results | 1 | 1 | 0 | 0 |
+| host | 3 | 3 | 0 | 0 |
+| service | 3 | 3 | 0 | 0 |
+| eventhandler | 3 | 3 | 0 | 0 |
+| servicegroup_jmx4perl | 3 | 3 | 0 | 0 |
+| hostgroup_japan | 3 | 3 | 0 | 0 |
++-----------------------+--------+-------+-------+---------+</tt></pre>
+</div></div>
+</div></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>check_results this queue is monitored by the neb module to
+ fetch results from the worker.
+ You don't need an extra worker for this queue.
+ The number of result workers can be set to a
+ maximum of 256, but usually one is enough.
+ One worker is capable of processing several
+ thousand results per second.
+
+
+host This is the queue for generic host checks. If
+ you enable host checks with the hosts=yes switch.
+ Before a host goes into this queue, it is
+ checked if any of the local groups matches or a
+ seperate hostgroup machtes. If nothing matches,
+ then this queue is used.
+
+
+service This is the queue for generic service checks. If
+ you enable service checks with the services=yes
+ switch. Before a service goes into this queue
+ it is checked against the local host- and
+ service-groups. Then the normal host- and
+ servicegroups are checked and if none matches,
+ this queue is used.
+
+
+hostgroup_<name> This queue is created for every hostgroup which
+ has been defined by the hostgroups=... option.
+ Make sure you have at least one worker for every
+ hostgroup you specify. Start the worker with
+ --hostgroups=... to work on hostgroup queues.
+ Note that this queue may also contain service
+ checks if the hostgroup of a service matches.
+
+
+servicegroup_<name> This queue is created for every servicegroup
+ which has been defined by the servicegroup=...
+ option.
+
+
+eventhandler This is the generic queue for all eventhandler.
+ Make sure you have a worker for this queue if
+ you have eventhandler enabled. Start the worker
+ with --events to work on this queue.
+
+
+perfdata This is the generic queue for all performance
+ data. It is created and used if you switch on
+ --perfdata=yes.
+ Performance data cannot be processed by the
+ gearman worker itself. You will need pnp4nagios
+ (http://www.pnp4nagios.org) therefor.</tt></pre>
+</div></div>
+</div>
+<h2 id="_performance">Performance</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>While the main motivation was to ease distributed configuration, this
+plugin also helps to spread the load on multiple worker. Throughput is
+mainly limited by the amount of jobs a single nagios instance can put
+onto the Gearman job server. Keep the Gearman job server close to the
+nagios box. Best practice is to put both on the same machine. Both
+processes will utilize one core. Some testing with my workstation
+(Dual Core 2.50GHz) and two worker boxes gave me these results. I used
+a sample Nagios installation with 20.000 Services at a 1 minute
+interval and a sample plugin which returns just a single line of
+output. I got over 300 Servicechecks per second, which means you could
+easily setup 100.000 services at a 5 minute interval with a single
+nagios box. The amount of worker boxes depends on your check types.</p></div>
+<div class="paragraph"><p><span class="image">
+<img alt="Performance 1" src="data:image/png;base64,
+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
+rkJggg==" />
+</span>
+<span class="image">
+<img alt="Performance 2" src="data:image/png;base64,
+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" />
+</span></p></div>
+</div>
+<h2 id="_how_to_monitor_job_server_and_worker">How to Monitor Job Server and Worker</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Use the supplied check_gearman to monitor your worker and job server.
+Worker have a own queue for status requests.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt> %> ./check_gearman -H <job server hostname> -q worker_<worker hostname> -t 10 -s check
+ check_gearman OK - localhost has 10 worker and is working on 1 jobs|worker=10 running=1 total_jobs_done=1508</tt></pre>
+</div></div>
+<div class="paragraph"><p>This will send a test job to the given job server and the worker will
+respond with some statistical data.</p></div>
+<div class="paragraph"><p>Job server can be monitored with:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt> %> ./check_gearman -H localhost -t 20
+ check_gearman OK - 6 jobs running and 0 jobs waiting.|check_results=0;0;1;10;100 host=0;0;9;10;100 service=0;6;9;10;100</tt></pre>
+</div></div>
+</div>
+<h2 id="_how_to_submit_passive_checks">How to Submit Passive Checks</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>You can use send_gearman to submit active and passive checks to a
+gearman job server where they will be processed just like a finished
+check would do.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt> %> ./send_gearman --server=<job server> --encryption=no --host="<hostname>" --service="<service>" --message="message"</tt></pre>
+</div></div>
+</div>
+<h2 id="_how_to_submit_check_multi_results">How to Submit check_multi Results</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>check_multi is a plugin which executes multiple child checks.
+See more details about the feed_passive mode at:
+<a href="http://www.my-plugin.de/wiki/projects/check_multi/feed_passive">http://www.my-plugin.de/wiki/projects/check_multi/feed_passive</a></p></div>
+<div class="paragraph"><p>You can pass such child checks to Nagios via the mod_gearman
+neb module:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt> %> check_multi -f multi.cmd -r 256 | ./send_multi --server=<job server> --encryption=no --host="<hostname>" --service="<service>"</tt></pre>
+</div></div>
+<div class="paragraph"><p>If you want to use only check_multi and no other workers, you can
+achieve this with the following neb module settings:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>broker_module=/usr/local/share/nagios/mod_gearman.o server=localhost encryption=no eventhandler=no hosts=no services=no hostgroups=does_not_exist</tt></pre>
+</div></div>
+<div class="paragraph"><p>Note: encryption is not necessary if you both run the check_multi checks
+and the nagios check_results queue on the same server.</p></div>
+</div>
+<h2 id="_what_about_notifications">What About Notifications</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Notifications are very difficult to distribute. And i think its not
+very useful too. So this feature will not be implemented.</p></div>
+</div>
+<h2 id="_hints">Hints</h2>
+<div class="sectionbody">
+<div class="ulist"><ul>
+<li>
+<p>
+Make sure you have at least one worker for every queue. You should
+ monitor that (check_gearman).
+</p>
+</li>
+<li>
+<p>
+Add Logfile checks for your gearmand server and mod_gearman
+ worker.
+</p>
+</li>
+<li>
+<p>
+Make sure all gearman checks are in local groups. Gearman self
+ checks should not be monitored through gearman.
+</p>
+</li>
+<li>
+<p>
+Keep the gearmand server close to Nagios for better performance.
+</p>
+</li>
+<li>
+<p>
+If you have some checks which should not run parallel, just setup a
+ single worker with --max-worker=1 and they will be executed one
+ after another. For example for cpu intesive checks with selenium.
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_download">Download</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Mod Gearman is available for download at: <a href="http://labs.consol.de/nagios/mod-gearman">http://labs.consol.de/nagios/mod-gearman</a></p></div>
+<div class="paragraph"><p>The source is available at GitHub: <a href="http://github.com/sni/mod_gearman">http://github.com/sni/mod_gearman</a></p></div>
+</div>
+</div>
+<div id="footnotes"><hr /></div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2011-02-07 11:03:18 CEST
+</div>
+</div>
+</body>
+</html>
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/etc/mod_gearman.conf.in
^
|
@@ -23,6 +23,11 @@
server=localhost:4730
+# sets the address of your 2nd (duplicate) gearman job server. Can
+# be specified more than once o add more servers.
+#dupserver=<host>:<port>
+
+
# defines if the module should distribute execution of
# eventhandlers.
eventhandler=yes
@@ -146,4 +151,4 @@
# Controls the amount of jobs a worker will do before he exits
# Use this to control how fast the amount of workers will go down
# after high load times
-max-jobs=50
\ No newline at end of file
+max-jobs=50
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/extras/gearmand-init
^
|
@@ -12,25 +12,24 @@
### END INIT INFO
NAME=gearmand
-DAEMON="/usr/sbin/gearmand"
+DAEMON="/tmp/gearman/sbin/gearmand"
OPTIONS="-d -t 10 -j 0"
PORT=4730
LISTEN=0.0.0.0
-PIDFILE=/var/run/gearmand.pid
-LOGFILE=/var/log/gearmand.log
-USER=nagios
+PIDFILE=/tmp/gm/var/mod_gearman/gearmand.pid
+LOGFILE=/tmp/gm/var/mod_gearman/gearmand.log
+USER=sven
GRACEFUL_SHUTDOWN_TIME=30
-for f in /usr/bin/netcat /usr/bin/nc; do
- if [ -x $f ]; then
+for f in $( which netcat nc ) ; do
+ if [ -x "$f" ]; then
NC=$f
fi
done
-function get_status() {
- pid=`cat $PIDFILE 2>/dev/null`
- if [ "$pid" != "" ]; then
- ps -p $pid > /dev/null 2>&1
- if [ $? -eq 0 ]; then
+get_status() {
+ pid=$( cat $PIDFILE 2>/dev/null )
+ if [ -n "$pid" ]; then
+ if ps -p $pid > /dev/null 2>&1 ; then
echo "$NAME is running with pid $pid"
return 0;
fi
@@ -39,20 +38,19 @@
return 1;
}
-function kill_gearmand() {
- echo -n "Killing $NAME"
- pid=`cat $PIDFILE 2>/dev/null`
- if [ -z $pid ]; then
+kill_gearmand() {
+ printf '%s' "Killing $NAME"
+ pid=$( cat $PIDFILE 2>/dev/null )
+ if [ -z "$pid" ]; then
echo ". Not running."
else
# do a kill if still now down
ps -p $pid > /dev/null 2>&1 && kill $pid
for x in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5; do
- echo -n "."
+ printf "."
ps -p $pid > /dev/null 2>&1 && sleep 1;
done
- ps -p $pid > /dev/null 2>&1;
- if [ $? -ne 0 ]; then
+ if ! ps -p $pid > /dev/null 2>&1 ; then
echo "done"
exit 0;
else
@@ -62,22 +60,31 @@
fi
}
-WHO=`whoami`
+WHO=$( whoami )
case "$1" in
start)
- echo -n "Starting $NAME "
- get_status > /dev/null;
- if [ $? = 0 ]; then
+ printf '%s' "Starting $NAME "
+ if get_status > /dev/null ; then
echo "failed"
echo "$NAME already running"
exit 0;
fi
+ if [ ! -x "$DAEMON" ]; then
+ echo "Cannot start. Make sure $DAEMON exists and is executable"
+ exit 1;
+ fi
CMD="$DAEMON -p $PORT -P $PIDFILE $OPTIONS --log-file=$LOGFILE -v -v --listen=$LISTEN"
if [ "$WHO" = "root" ]; then
- su - $USER -c "$CMD"
+ # try to exec commands as user
+ su - $USER -c /bin/true
+ if [ $? -ne 0 ]; then
+ echo "cannot exec commands as user $USER, make sure user has a valid shell"
+ exit 1;
+ fi
+ su - $USER -c "$CMD > $LOGFILE 2>&1"
else
- $CMD
+ $CMD > $LOGFILE 2>&1
fi
if [ $? -eq 0 ]; then
echo "done"
@@ -88,24 +95,23 @@
fi
;;
stop)
- echo -n "Stopping $NAME"
- pid=`cat $PIDFILE 2>/dev/null`
- if [ -z $pid ]; then
+ printf '%s' "Stopping $NAME"
+ pid=$( cat $PIDFILE 2>/dev/null )
+ if [ -z "$pid" ]; then
echo ". Not running."
else
# do a graceful shutdown
if [ ! -z $NC ]; then
- echo -n " gracefully "
- echo "shutdown graceful" | $NC -w 1 $LISTEN $PORT
+ printf '%s' " gracefully "
+ echo "shutdown graceful" | $NC -w 1 -i 1 $LISTEN $PORT
x=$GRACEFUL_SHUTDOWN_TIME
while [ $x -gt 0 ]; do
- echo -n "."
+ printf "."
ps -p $pid > /dev/null 2>&1 && sleep 1 || x=0;
- let "x=x-1"
+ x=$( expr $x - 1 )
done
- ps -p $pid > /dev/null 2>&1;
- if [ $? -ne 0 ]; then
+ if ! ps -p $pid > /dev/null 2>&1 ; then
echo "done"
exit 0;
else
@@ -121,10 +127,10 @@
kill_gearmand;
;;
reload|force-reload)
- echo -n "Reloading $NAME configuration files "
- pid=`cat $PIDFILE 2>/dev/null`
- if [ "$pid" != "" ]; then
- kill -HUP $pid
+ printf '%s' "Reloading $NAME configuration files "
+ pid=$( cat $PIDFILE 2>/dev/null )
+ if [ -n "$pid" ]; then
+ kill -HUP "$pid"
echo "OK"
exit 0;
else
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/extras/gearmand-init.in
^
|
@@ -12,25 +12,24 @@
### END INIT INFO
NAME=gearmand
-DAEMON="/usr/sbin/gearmand"
+DAEMON="%GEARMAND%"
OPTIONS="-d -t 10 -j 0"
PORT=4730
LISTEN=0.0.0.0
-PIDFILE=/var/run/gearmand.pid
-LOGFILE=/var/log/gearmand.log
+PIDFILE=%GPIDFILE%
+LOGFILE=%GLOGFILE%
USER=%USER%
GRACEFUL_SHUTDOWN_TIME=30
-for f in /usr/bin/netcat /usr/bin/nc; do
- if [ -x $f ]; then
+for f in $( which netcat nc ) ; do
+ if [ -x "$f" ]; then
NC=$f
fi
done
-function get_status() {
- pid=`cat $PIDFILE 2>/dev/null`
- if [ "$pid" != "" ]; then
- ps -p $pid > /dev/null 2>&1
- if [ $? -eq 0 ]; then
+get_status() {
+ pid=$( cat $PIDFILE 2>/dev/null )
+ if [ -n "$pid" ]; then
+ if ps -p $pid > /dev/null 2>&1 ; then
echo "$NAME is running with pid $pid"
return 0;
fi
@@ -39,20 +38,19 @@
return 1;
}
-function kill_gearmand() {
- echo -n "Killing $NAME"
- pid=`cat $PIDFILE 2>/dev/null`
- if [ -z $pid ]; then
+kill_gearmand() {
+ printf '%s' "Killing $NAME"
+ pid=$( cat $PIDFILE 2>/dev/null )
+ if [ -z "$pid" ]; then
echo ". Not running."
else
# do a kill if still now down
ps -p $pid > /dev/null 2>&1 && kill $pid
for x in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5; do
- echo -n "."
+ printf "."
ps -p $pid > /dev/null 2>&1 && sleep 1;
done
- ps -p $pid > /dev/null 2>&1;
- if [ $? -ne 0 ]; then
+ if ! ps -p $pid > /dev/null 2>&1 ; then
echo "done"
exit 0;
else
@@ -62,22 +60,31 @@
fi
}
-WHO=`whoami`
+WHO=$( whoami )
case "$1" in
start)
- echo -n "Starting $NAME "
- get_status > /dev/null;
- if [ $? = 0 ]; then
+ printf '%s' "Starting $NAME "
+ if get_status > /dev/null ; then
echo "failed"
echo "$NAME already running"
exit 0;
fi
+ if [ ! -x "$DAEMON" ]; then
+ echo "Cannot start. Make sure $DAEMON exists and is executable"
+ exit 1;
+ fi
CMD="$DAEMON -p $PORT -P $PIDFILE $OPTIONS --log-file=$LOGFILE -v -v --listen=$LISTEN"
if [ "$WHO" = "root" ]; then
- su - $USER -c "$CMD"
+ # try to exec commands as user
+ su - $USER -c /bin/true
+ if [ $? -ne 0 ]; then
+ echo "cannot exec commands as user $USER, make sure user has a valid shell"
+ exit 1;
+ fi
+ su - $USER -c "$CMD > $LOGFILE 2>&1"
else
- $CMD
+ $CMD > $LOGFILE 2>&1
fi
if [ $? -eq 0 ]; then
echo "done"
@@ -88,24 +95,23 @@
fi
;;
stop)
- echo -n "Stopping $NAME"
- pid=`cat $PIDFILE 2>/dev/null`
- if [ -z $pid ]; then
+ printf '%s' "Stopping $NAME"
+ pid=$( cat $PIDFILE 2>/dev/null )
+ if [ -z "$pid" ]; then
echo ". Not running."
else
# do a graceful shutdown
if [ ! -z $NC ]; then
- echo -n " gracefully "
- echo "shutdown graceful" | $NC -w 1 $LISTEN $PORT
+ printf '%s' " gracefully "
+ echo "shutdown graceful" | $NC -w 1 -i 1 $LISTEN $PORT
x=$GRACEFUL_SHUTDOWN_TIME
while [ $x -gt 0 ]; do
- echo -n "."
+ printf "."
ps -p $pid > /dev/null 2>&1 && sleep 1 || x=0;
- let "x=x-1"
+ x=$( expr $x - 1 )
done
- ps -p $pid > /dev/null 2>&1;
- if [ $? -ne 0 ]; then
+ if ! ps -p $pid > /dev/null 2>&1 ; then
echo "done"
exit 0;
else
@@ -121,10 +127,10 @@
kill_gearmand;
;;
reload|force-reload)
- echo -n "Reloading $NAME configuration files "
- pid=`cat $PIDFILE 2>/dev/null`
- if [ "$pid" != "" ]; then
- kill -HUP $pid
+ printf '%s' "Reloading $NAME configuration files "
+ pid=$( cat $PIDFILE 2>/dev/null )
+ if [ -n "$pid" ]; then
+ kill -HUP "$pid"
echo "OK"
exit 0;
else
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/extras/patches/0001-use_return_values_from_eventhandler_broker.patch
^
|
(renamed to extras/patches/0001-use_return_values_from_eventhandler_broker.patch)
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/extras/patches/0001-use_return_values_from_eventhandler_broker.patch
^
|
(renamed to extras/patches/0001-use_return_values_from_eventhandler_broker.patch)
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/base64.h
^
|
@@ -1,7 +1,15 @@
#include <string.h>
-/*
- * http://freecode-freecode.blogspot.com/2008/02/base64c.html
+/** @file
+ * @brief utilities for base64 encoding
+ *
+ * contains all function used for encoding and decoding of
+ * base64.
+ *
+ * see
+ * http://freecode-freecode.blogspot.com/2008/02/base64c.html
+ * for more.
+ * @{
*/
@@ -51,3 +59,6 @@
*/
size_t base64_decode(char *source, unsigned char *target, size_t targetlen);
+/**
+ * @}
+ */
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/check_gearman.h
^
|
@@ -21,19 +21,87 @@
*
*****************************************************************************/
-#define MOD_GM_CHECK_GEARMAN
+/**
+ * @file
+ * @brief check_gearman nagios plugin
+ * @addtogroup mod_gearman_check_gearman check_gearman
+ *
+ * check_gearman can be used as a nagios plugin to verify gearman server and worker.
+ * It is part of the Mod-Gearman package but not limited to Mod-Gearman.
+ *
+ * @{
+ */
-#define PLUGIN_NAME "check_gearman"
+#define MOD_GM_CHECK_GEARMAN /**< set check_gearman mode */
+
+#define PLUGIN_NAME "check_gearman" /**< set the name of the plugin */
#include <stdlib.h>
#include <signal.h>
#include "common.h"
-mod_gm_opt_t *mod_gm_opt;
+mod_gm_opt_t *mod_gm_opt; /**< global options structure */
+
+/** check_gearman
+ *
+ * main function of check_gearman
+ *
+ * @param[in] argc - number of arguments
+ * @param[in] argv - list of arguments
+ *
+ * @return exits with a nagios compatible exit code
+ */
int main (int argc, char **argv);
+
+/**
+ *
+ * print the usage and exit
+ *
+ * @return exits with a nagios compatible exit code
+ */
void print_usage(void);
+
+/**
+ *
+ * print the version and exit
+ *
+ * @return exits with a nagios compatible exit code
+ */
void print_version(void);
+
+/**
+ *
+ * signal handler for sig alarm
+ *
+ * @param[in] sig - signal number
+ *
+ * @return exits with a nagios compatible exit code
+ */
void alarm_sighandler(int sig);
+
+/**
+ *
+ * check a gearmand server
+ *
+ * @param[in] server - server to check
+ *
+ * @return returns a nagios compatible exit code
+ */
int check_server(char * server);
+
+/**
+ *
+ * check a gearman worker
+ *
+ * @param[in] queue - queue name (function)
+ * @param[in] send - put this text as job into the queue
+ * @param[in] expect - returning text to expect
+ *
+ * @return returns a nagios compatible exit code
+ */
int check_worker(char * queue, char * send, char * expect);
+
+/**
+ * @}
+ */
\ No newline at end of file
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/common.h
^
|
@@ -21,6 +21,30 @@
*
*****************************************************************************/
+/** \mainpage Mod-Gearman
+ *
+ * \section intro_sec Introduction
+ *
+ * Mod-Gearman (http://labs.consol.de/nagios/mod-gearman) is a new
+ * way of distributing active Nagios checks (http://www.nagios.org) across your network. It
+ * consists of two parts: There is a NEB module which resides in the
+ * Nagios core and adds servicechecks, hostchecks and eventhandler to a
+ * Gearman (http://gearman.org) queue. There can be multiple equal
+ * gearman servers. The counterpart is one or more worker clients for
+ * the checks itself. They can be bound to host and servicegroups.
+ *
+ * @attention Please submit bugreports or patches on https://github.com/sni/mod_gearman
+ * @author Sven Nierlein <sven.nierlein@consol.de>
+ *
+ */
+
+
+/** @file
+ * @brief common header for all components
+ *
+ * @{
+ */
+
#include <stdio.h>
#include <sys/time.h>
@@ -28,11 +52,11 @@
#define MOD_GM_COMMON_H
/* constants */
-#define GM_VERSION "0.8"
+#define GM_VERSION "1.0"
#define GM_ENABLED 1
#define GM_DISABLED 0
-#define GM_BUFFERSIZE 16384
-#define GM_MAX_OUTPUT 11000 /* must be ~30% below GM_BUFFERSIZE for base64/encryption */
+#define GM_BUFFERSIZE 98304
+#define GM_MAX_OUTPUT 65536 /* must be ~30% below GM_BUFFERSIZE for base64/encryption */
#define GM_LISTSIZE 512
#define GM_MIN_LIB_GEARMAN_VERSION 0.14
@@ -55,16 +79,16 @@
#define GM_DEFAULT_JOB_TIMEOUT 60
#define GM_DEFAULT_JOB_RETRIES 1
-#define GM_CHILD_SHUTDOWN_TIMEOUT 5
+#define GM_CHILD_SHUTDOWN_TIMEOUT 30
#define GM_DEFAULT_RESULT_QUEUE "check_results"
#define GM_DEFAULT_IDLE_TIMEOUT 10
-#define GM_DEFAULT_MAX_JOBS 20
+#define GM_DEFAULT_MAX_JOBS 1000
#define MAX_CMD_ARGS 4096
/* worker */
-#define GM_DEFAULT_MIN_WORKER 1 /* minumum number of worker */
-#define GM_DEFAULT_MAX_WORKER 20 /* maximum number of concurrent worker */
-#define GM_DEFAULT_JOB_MAX_AGE 600 /* discard jobs older than that */
+#define GM_DEFAULT_MIN_WORKER 1 /**< minumum number of worker */
+#define GM_DEFAULT_MAX_WORKER 20 /**< maximum number of concurrent worker */
+#define GM_DEFAULT_JOB_MAX_AGE 600 /**< discard jobs older than that */
/* transport modes */
#define GM_ENCODE_AND_ENCRYPT 1
@@ -91,72 +115,111 @@
#define FALSE 0
#endif
-#define STATE_OK 0
-#define STATE_WARNING 1
-#define STATE_CRITICAL 2
-#define STATE_UNKNOWN 3
+#define STATE_OK 0 /**< core exit code for ok */
+#define STATE_WARNING 1 /**< core exit code for warning */
+#define STATE_CRITICAL 2 /**< core exit code for critical */
+#define STATE_UNKNOWN 3 /**< core exit code for unknown */
-/* size of the shared memory segment */
-#define GM_SHM_SIZE 300
+#define GM_SHM_SIZE 4096 /**< size of the shared memory segment */
-/* options structure */
+/** options structure
+ *
+ * structure union for all components
+ * all config files and commandline arguments are parsed
+ * into this structure
+ */
typedef struct mod_gm_opt_struct {
- int set_queues_by_hand;
+ int set_queues_by_hand; /**< flag whether there has been queues configured by hand */
- char * crypt_key;
- char * keyfile;
- char * server_list[GM_LISTSIZE];
- int server_num;
- char * hostgroups_list[GM_LISTSIZE];
- int hostgroups_num;
- char * servicegroups_list[GM_LISTSIZE];
- int servicegroups_num;
- int debug_level;
- int hosts;
- int services;
- int events;
- int job_timeout;
- int encryption;
- int transportmode;
+ char * crypt_key; /**< encryption key used for securing the messages sent over gearman */
+ char * keyfile; /**< path to a file where the crypt_key is read from */
+ char * server_list[GM_LISTSIZE]; /**< list of gearmand servers */
+ int server_num; /**< number of gearmand servers */
+ char * dupserver_list[GM_LISTSIZE]; /**< list of gearmand servers to duplicate results */
+ int dupserver_num; /**< number of duplicate gearmand servers */
+ char * hostgroups_list[GM_LISTSIZE]; /**< list of hostgroups which get own queues */
+ int hostgroups_num; /**< number of elements in hostgroups_list */
+ char * servicegroups_list[GM_LISTSIZE]; /**< list of servicegroups which get own queues */
+ int servicegroups_num; /**< number of elements in servicegroups_list */
+ int debug_level; /**< level of debug output */
+ int hosts; /**< flag wheter host checks are distributed or not */
+ int services; /**< flag wheter service checks are distributed or not */
+ int events; /**< flag wheter eventhandlers are distributed or not */
+ int job_timeout; /**< override job timeout */
+ int encryption; /**< flag wheter messages are encrypted */
+ int transportmode; /**< flag for the transportmode, base64 only or base64 and encrypted */
/* neb module */
- char * result_queue;
- int result_workers;
- int perfdata;
- char * local_hostgroups_list[GM_LISTSIZE];
- int local_hostgroups_num;
- char * local_servicegroups_list[GM_LISTSIZE];
- int local_servicegroups_num;
+ char * result_queue; /**< name of the result queue used by the neb module */
+ int result_workers; /**< number of result worker threads started */
+ int perfdata; /**< flag whether perfdata are distributed or not */
+ char * local_hostgroups_list[GM_LISTSIZE]; /**< list of hostgroups which will not be distributed */
+ int local_hostgroups_num; /**< number of elements in local_hostgroups_list */
+ char * local_servicegroups_list[GM_LISTSIZE]; /**< list of group which will not be distributed */
+ int local_servicegroups_num; /**< number of elements in local_servicegroups_list */
/* worker */
- char * identifier;
- char * pidfile;
- char * logfile;
- FILE * logfile_fp;
- int daemon_mode;
- int debug_result;
- int max_age;
- int min_worker;
- int max_worker;
- int fork_on_exec;
- int idle_timeout;
- int max_jobs;
+ char * identifier; /**< identifier for this worker */
+ char * pidfile; /**< path to a pidfile */
+ char * logfile; /**< path for the logfile */
+ FILE * logfile_fp; /**< filedescriptor for the logfile */
+ int daemon_mode; /**< running as daemon ot not? */
+ int debug_result; /**< flag to write a debug file for each result */
+ int max_age; /**< max age in seconds for new jobs */
+ int min_worker; /**< minimum number of workers */
+ int max_worker; /**< maximum number of workers */
+ int fork_on_exec; /**< flag to disable additional forks for each job */
+ int idle_timeout; /**< number of seconds till a idle worker exits */
+ int max_jobs; /**< maximum number of jobs done after a worker exits */
/* send_gearman */
- int timeout;
- int return_code;
- char * message;
- char * host;
- char * service;
- int active;
- struct timeval starttime;
- struct timeval finishtime;
- struct timeval latency;
+ int timeout; /**< timeout for waiting reading on stdin */
+ int return_code; /**< return code */
+ char * message; /**< message output */
+ char * host; /**< hostname for this check */
+ char * service; /**< service description for this check */
+ int active; /**< flag wheter the result is a active or a passive check */
+ struct timeval starttime; /**< time when the check started */
+ struct timeval finishtime; /**< time when the check finished */
+ struct timeval latency; /**< latency for this result */
} mod_gm_opt_t;
-/*
+/** structure for jobs to execute */
+typedef struct gm_job_struct {
+ char * host_name; /**< hostname for this job */
+ char * service_description; /**< service description for this job or NULL */
+ char * command_line; /**< command line to execute */
+ char * type; /**< type of this job */
+ char * result_queue; /**< name of the result queue */
+ char * output; /**< output from the executed command line */
+ int return_code; /**< return code for this job */
+ int early_timeout; /**< did the check run into a timeout */
+ int check_options; /**< check_options given from the core */
+ int scheduled_check; /**< normal scheduled check? */
+ int reschedule_check; /**< rescheduled check? */
+ int exited_ok; /**< did the plugin exit normally? */
+ int timeout; /**< timeout for this job */
+ double latency; /**< latency for from this job */
+ struct timeval core_start_time; /**< time when the core started the job */
+ struct timeval start_time; /**< time when the job really started */
+ struct timeval finish_time; /**< time when the job was finished */
+} gm_job_t;
+
+
+/**
+ * general logger
+ *
* logger is then defined in worker_logger.c
* and the neb logger in logger.c
+ * tools logger is in the tools_logger.c
+ *
+ * @param[in] lvl - debug level for this message
+ * @param[in] text - text to log
+ *
+ * @return nothing
*/
void gm_log( int lvl, const char *text, ... );
+/*
+ * @}
+ */
#endif
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/crypt.h
^
|
@@ -21,15 +21,51 @@
*
*****************************************************************************/
+/** @file
+ * @brief crypt module
+ *
+ * contains the utility functions for en/decryption
+ *
+ * @{
+ */
#include <stdio.h>
#include <string.h>
#include "rijndael.h"
-#define KEYBITS 256
-#define BLOCKSIZE 16
+#define KEYBITS 256 /**< key size */
+#define BLOCKSIZE 16 /**< block size for encryption */
+/**
+ * initialize crypto module
+ *
+ * @param[in] password - encryption key
+ *
+ * @return nothing
+ */
void mod_gm_aes_init(char * password);
+
+/**
+ * encrypt text
+ *
+ * @param[out] encrypted - pointer to encrypted text
+ * @param[in] text - text which should be encrypted
+ *
+ * @return size of encrypted text
+ */
int mod_gm_aes_encrypt(unsigned char ** encrypted, char * text);
+
+/**
+ * decrypt text
+ *
+ * @param[out] decrypted - pointer to decrypted text
+ * @param[in] encrypted - text which should be decrypted
+ * @param[in] size - size of encrypted text
+ *
+ * @return nothing
+ */
void mod_gm_aes_decrypt(char ** decrypted, unsigned char * encrypted, int size);
+/*
+ * @}
+ */
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/gearman.h
^
|
@@ -21,6 +21,12 @@
*
*****************************************************************************/
+/** @file
+ * @brief header for the gearman module
+ *
+ * @{
+ */
+
#include <stdio.h>
#include <string.h>
#include <unistd.h>
@@ -32,6 +38,7 @@
typedef void*( mod_gm_worker_fn)(gearman_job_st *job, void *context, size_t *result_size, gearman_return_t *ret_ptr);
int create_client( char ** server_list, gearman_client_st * client);
+int create_client_dup( char ** server_list, gearman_client_st * client);
int create_worker( char ** server_list, gearman_worker_st * worker);
int add_job_to_queue( gearman_client_st *client, char ** server_list, char * queue, char * uniq, char * data, int priority, int retries, int transport_mode );
int worker_add_function( gearman_worker_st * worker, char * queue, gearman_worker_fn *function);
@@ -39,3 +46,6 @@
void free_client(gearman_client_st *client);
void free_worker(gearman_worker_st *worker);
+/**
+ * @}
+ */
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/gearman_top.h
^
|
@@ -21,16 +21,72 @@
*
*****************************************************************************/
+/**
+ * @file
+ * @brief gearman_top command line utility
+ * @addtogroup mod_gearman_gearman_top gearman_top
+ *
+ * Command line utility which connects to the admin interface of a gearman daemon.
+ * displays current worker and queue utilization.
+ *
+ * @{
+ */
+
#include <stdlib.h>
#include <signal.h>
#include <curses.h>
#include <time.h>
#include "common.h"
-mod_gm_opt_t *mod_gm_opt;
+mod_gm_opt_t *mod_gm_opt; /**< global options structure */
+/** gearman_top
+ *
+ * main function of gearman_top
+ *
+ * @param[in] argc - number of arguments
+ * @param[in] argv - list of arguments
+ *
+ * @return just exits
+ */
int main (int argc, char **argv);
+
+/**
+ *
+ * close all connections and exit
+ *
+ * @param[in] sig - signal number received
+ *
+ * @return just exits
+ */
void clean_exit(int sig);
+
+/**
+ *
+ * print the usage and exit
+ *
+ * @return just exits
+ */
void print_usage(void);
+
+/**
+ *
+ * print the version and exit
+ *
+ * @return exits with a nagios compatible exit code
+ */
void print_version(void);
+
+/**
+ *
+ * print the statistics for a given hostname
+ *
+ * @param[in] hostname - hostname to connect to
+ *
+ * @return nothing
+ */
void print_stats(char * hostname);
+
+/**
+ * @}
+ */
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/gearman_utils.h
^
|
@@ -21,6 +21,12 @@
*
*****************************************************************************/
+/** @file
+ * @brief gearman specific utils
+ *
+ * @{
+ */
+
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
@@ -30,33 +36,73 @@
#include <unistd.h>
-/* function status structure */
+/** function status structure */
typedef struct mod_gm_status_function {
- char * queue;
- int total;
- int running;
- int waiting;
- int worker;
+ char * queue; /**< name of the queue (function name) */
+ int total; /**< total number of workers */
+ int running; /**< number of running worker */
+ int waiting; /**< number of waiting jobs */
+ int worker; /**< number of workers */
} mod_gm_status_function_t;
-/* worker status structure */
+/** worker status structure
+ *
+ * not used at the moment
+ */
typedef struct mod_gm_status_worker {
- int fd;
- char * ip;
- char * id;
- char * function[GM_LISTSIZE];
+ int fd; /**< file descriptor */
+ char * ip; /**< ip from this worker */
+ char * id; /**< id of the worker */
+ char * function[GM_LISTSIZE]; /**< list of functions returned from gearmand */
} mod_gm_status_worker_t;
-/* server status structure */
+/** server status structure */
typedef struct mod_gm_status_server {
- mod_gm_status_worker_t * worker[GM_LISTSIZE];
- int worker_num;
- mod_gm_status_function_t * function[GM_LISTSIZE];
- int function_num;
+ mod_gm_status_worker_t * worker[GM_LISTSIZE]; /**< list of worker */
+ int worker_num; /**< number of worker */
+ mod_gm_status_function_t * function[GM_LISTSIZE]; /**< number of functions */
+ int function_num; /**< number of functions */
} mod_gm_server_status_t;
-
+/**
+ * get_gearman_server_data
+ *
+ * return admin statistics from gearmand
+ *
+ * @param[out] stats - stats structure
+ * @param[out] message - info/error message
+ * @param[out] version - version string from server
+ * @param[in] hostname - hostname to connect to
+ * @param[in] port - port to connect
+ *
+ * @return true on success
+ */
int get_gearman_server_data(mod_gm_server_status_t *stats, char ** message, char **version, char * hostname, int port);
+
+/**
+ * free_mod_gm_status_server
+ *
+ * free status structure
+ *
+ * @param[in] stats - structure to free
+ *
+ * @return nothing
+ */
void free_mod_gm_status_server(mod_gm_server_status_t *stats);
+
+/**
+ * struct_cmp_by_queue
+ *
+ * sort gearman queues by name
+ *
+ * @param[in] a - structure a
+ * @param[in] b - structure b
+ *
+ * @return true on success
+ */
int struct_cmp_by_queue(const void *a, const void *b);
+
+/**
+ * @}
+ */
\ No newline at end of file
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/gm_log.h
^
|
@@ -21,5 +21,9 @@
*
*****************************************************************************/
+/** @file
+ * @brief header for the log module
+ */
+
#include "nagios/nagios.h"
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/mod_gearman.h
^
|
@@ -21,7 +21,7 @@
*
*****************************************************************************/
-#define MOD_GM_NEB
+#define MOD_GM_NEB /**< set mod_gearman neb features */
#include <common.h>
@@ -31,9 +31,23 @@
#include <unistd.h>
#include <pthread.h>
-#define GM_PERFDATA_QUEUE "perfdata"
+#define GM_PERFDATA_QUEUE "perfdata" /**< default performance data queue */
+#define NSCORE /**< enable core features */
-#define NSCORE
+/** @file
+ * @brief Mod-Gearman NEB Module
+ * @addtogroup mod_gearman_neb_module NEB Module
+ *
+ * The Mod-Gearman NEB module loads into the core and intercepts scheduled host
+ * and service checks as well as eventhander jobs.
+ * The module start a single new thread which acts as gearman client and worker.
+ * The client is used to send new jobs into the gearman queues (functions). The
+ * worker listens on the result queue and puts back the finished results.
+ * Before the core reaps the result they will be merged together with the ones
+ * from gearman.
+ *
+ * @{
+ */
/* include some Nagios stuff as well */
#include "nagios/nagios.h"
@@ -46,11 +60,40 @@
/* include the gearman libs */
#include <libgearman/gearman.h>
-/* functions */
-int nebmodule_init( int, char *, nebmodule * );
-int nebmodule_deinit( int, int );
-void mod_gm_add_result_to_list(check_result * newcr);
+/** main NEB module init function
+ *
+ * this function gets initally called when loading the module
+ *
+ * @param[in] flags - module flags
+ * @param[in] args - module arguments from the core config
+ * @param[in] handle - our module handle
+ *
+ * @return Zero on success, or a non-zero error value.
+ */
+int nebmodule_init( int flags, char * args, nebmodule * handle);
+
+/** NEB module deinit function
+ *
+ * this function gets called before unloading the module from the core
+ *
+ * @param[in] flags - module flags
+ * @param[in] reason - reason for unloading the module
+ *
+ * @return nothing
+ */
+int nebmodule_deinit( int flags, int reason );
+
+/** adds check result to result list
+ *
+ * @param[in] newcheckresult - new checkresult structure to add to list
+ *
+ * @return nothing
+ */
+void mod_gm_add_result_to_list(check_result * newcheckresult);
-/* global variables */
+/** options structure */
mod_gm_opt_t *mod_gm_opt;
+/**
+ * @}
+ */
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/result_thread.h
^
|
@@ -21,6 +21,12 @@
*
*****************************************************************************/
+/** @file
+ * @brief header for the neb result thread
+ *
+ * @{
+ */
+
#include "mod_gearman.h"
#include <libgearman/gearman.h>
@@ -33,3 +39,6 @@
void write_debug_file(char ** text);
#endif
+/**
+ * @}
+ */
\ No newline at end of file
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/rijndael.h
^
|
@@ -1,18 +1,18 @@
-/*
+/** @file
+ * @brief header for the aes encryption component
+ *
* http://www.efgh.com/software/rijndael.htm
+ *
+ * @{
*/
#ifndef H__RIJNDAEL
#define H__RIJNDAEL
-int rijndaelSetupEncrypt(unsigned long *rk, const unsigned char *key,
- int keybits);
-int rijndaelSetupDecrypt(unsigned long *rk, const unsigned char *key,
- int keybits);
-void rijndaelEncrypt(const unsigned long *rk, int nrounds,
- const unsigned char plaintext[16], unsigned char ciphertext[16]);
-void rijndaelDecrypt(const unsigned long *rk, int nrounds,
- const unsigned char ciphertext[16], unsigned char plaintext[16]);
+int rijndaelSetupEncrypt(unsigned long *rk, const unsigned char *key, int keybits);
+int rijndaelSetupDecrypt(unsigned long *rk, const unsigned char *key, int keybits);
+void rijndaelEncrypt(const unsigned long *rk, int nrounds, const unsigned char plaintext[16], unsigned char ciphertext[16]);
+void rijndaelDecrypt(const unsigned long *rk, int nrounds, const unsigned char ciphertext[16], unsigned char plaintext[16]);
#define KEYLENGTH(keybits) ((keybits)/8)
#define RKLENGTH(keybits) ((keybits)/8+28)
@@ -20,3 +20,6 @@
#endif
+/**
+ * @}
+ */
\ No newline at end of file
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/send_gearman.h
^
|
@@ -21,6 +21,16 @@
*
*****************************************************************************/
+/**
+ * @file
+ * @brief send_gearman command line utility
+ * @addtogroup mod_gearman_send_gearman send_gearman
+ *
+ * command line utility to send results back to core. Replacement for send_nsca.
+ *
+ * @{
+ */
+
#define MOD_GM_SEND_GEARMAN
#include <stdlib.h>
@@ -32,13 +42,76 @@
#include <libgearman/gearman.h>
#include "common.h"
-mod_gm_opt_t *mod_gm_opt;
+mod_gm_opt_t *mod_gm_opt; /**< global options structure */
+
+/** send_gearman
+ *
+ * main function of gearman_top
+ *
+ * @param[in] argc - number of arguments
+ * @param[in] argv - list of arguments
+ *
+ * @return just exits
+ */
int main (int argc, char **argv);
+
+/**
+ * parse the arguments into the global options structure
+ *
+ * @param[in] argc - number of arguments
+ * @param[in] argv - list of arguments
+ *
+ * @return TRUE on success or FALSE if not
+ */
int parse_arguments(int argc, char **argv);
+
+/**
+ *
+ * print the usage and exit
+ *
+ * @return exits with a nagios compatible exit code
+ */
void print_usage(void);
+
+/**
+ *
+ * print the version and exit
+ *
+ * @return exits with a nagios compatible exit code
+ */
void print_version(void);
+
+/**
+ * verify options structure and check for missing options
+ *
+ * @param[in] opt - options structure to verify
+ *
+ * @return TRUE on success or FALSE if something went wrong
+ */
int verify_options(mod_gm_opt_t *opt);
+
+/**
+ * send_result
+ *
+ * create and send back the gearman jobs
+ *
+ * @return TRUE on success or FALSE if something went wrong
+ */
int send_result(void);
+
+/**
+ * alarm_sighandler
+ *
+ * handles sig alarms
+ *
+ * @param[in] sig - signal number
+ *
+ * @return nothing
+ */
void alarm_sighandler(int sig);
+
+/**
+ * @}
+ */
\ No newline at end of file
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/send_multi.h
^
|
@@ -22,6 +22,14 @@
*
*****************************************************************************/
+/**
+ * @file
+ * @brief send_multi command line utility
+ * @addtogroup mod_gearman_send_multi send_multi
+ *
+ * @{
+ */
+
#define MOD_GM_SEND_MULTI
#define _GNU_SOURCE
@@ -35,18 +43,115 @@
#include <libgearman/gearman.h>
#include "common.h"
-mod_gm_opt_t *mod_gm_opt;
+mod_gm_opt_t *mod_gm_opt; /**< options structure */
+/** send_multi
+ *
+ * main function of send_multi
+ *
+ * @param[in] argc - number of arguments
+ * @param[in] argv - list of arguments
+ *
+ * @return exits with a nagios compatible exit code
+ */
int main (int argc, char **argv);
+
+/**
+ * parse the arguments into the global options structure
+ *
+ * @param[in] argc - number of arguments
+ * @param[in] argv - list of arguments
+ *
+ * @return TRUE on success or FALSE if not
+ */
int parse_arguments(int argc, char **argv);
+
+/**
+ *
+ * print the usage and exit
+ *
+ * @return exits with a nagios compatible exit code
+ */
void print_usage(void);
+
+/**
+ *
+ * print the version and exit
+ *
+ * @return exits with a nagios compatible exit code
+ */
void print_version(void);
+
+/**
+ * verify options structure and check for missing options
+ *
+ * @param[in] opt - options structure to verify
+ *
+ * @return TRUE on success or FALSE if something went wrong
+ */
int verify_options(mod_gm_opt_t *opt);
+
+/**
+ * send_result
+ *
+ * create and send back the gearman jobs
+ *
+ * @return TRUE on success or FALSE if something went wrong
+ */
int send_result(void);
+
+/**
+ * alarm_sighandler
+ *
+ * handles sig alarms
+ *
+ * @param[in] sig - signal number
+ *
+ * @return nothing
+ */
void alarm_sighandler(int sig);
+
+/**
+ * read_multi_stream
+ *
+ * read xml data from stream
+ *
+ * @param[in] stream - file pointer to read xml data from
+ *
+ * @return TRUE on success or FALSE if something went wrong
+ */
int read_multi_stream(FILE *stream);
+
+/**
+ * read_child_check
+ *
+ * @param[in] bufstart - start of buffer
+ * @param[in] bufend - end of buffer
+ *
+ * @return TRUE on success or FALSE if something went wrong
+ */
int read_child_check(char *bufstart, char *bufend);
-char *read_multi_attribute(char *bufstart, char *bufend, char *attname);
-char *decode_xml(char *);
+/**
+ * read_multi_attribute
+ *
+ * @param[in] bufstart - start of buffer
+ * @param[in] bufend - end of buffer
+ * @param[in] attname - name of attribute to read
+ *
+ * @return value for this attribute
+ */
+char *read_multi_attribute(char *bufstart, char *bufend, char *attname);
+/**
+ * decode_xml
+ *
+ * @param[in] xml - xml to decode
+ *
+ * @return decoded string
+ */
+char *decode_xml(char * xml);
+
+/**
+ * @}
+ */
\ No newline at end of file
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/tools_logger.h
^
|
@@ -21,6 +21,10 @@
*
*****************************************************************************/
+/** @file
+ * @brief header for the tools logger component
+ */
+
#include <stdio.h>
#include <string.h>
#include <time.h>
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/utils.h
^
|
@@ -21,30 +21,348 @@
*
*****************************************************************************/
+/** @file
+ * @brief utility components for all parts of mod_gearman
+ *
+ * @{
+ */
+
#include "common.h"
+/**
+ * escpae newlines
+ *
+ * @param[in] rawbuf - text to escape
+ *
+ * @return a text with all newlines escaped
+ */
char *escape_newlines(char *rawbuf);
+
+/**
+ * real_exit_code
+ *
+ * converts a exit from wait() into real number
+ *
+ * @param[in] code - exit code
+ *
+ * @return real exit code
+ */
int real_exit_code(int code);
+
+/**
+ * mod_gm_crypt_init
+ *
+ * wrapper to initialze mod_gearman crypt module
+ *
+ * @param[in] key - password for encryption
+ *
+ * @return nothing
+ */
void mod_gm_crypt_init(char * key);
+
+/**
+ * mod_gm_encrypt
+ *
+ * wrapper to encrypt text
+ *
+ * @param[out] encrypted - pointer to encrypted text
+ * @param[in] text - text to encrypt
+ * @param[in] mode - encryption mode (base64 or aes64 with base64)
+ *
+ * @return base64 encoded text or aes encrypted text based on mode
+ */
int mod_gm_encrypt(char ** encrypted, char * text, int mode);
+
+/**
+ * mod_gm_decrypt
+ *
+ * @param[out] decrypted - pointer to decrypted text
+ * @param[in] text - text to decrypt
+ * @param[in] mode - do only base64 decoding or decryption too
+ *
+ * @return decrypted text
+ */
void mod_gm_decrypt(char ** decrypted, char * text, int mode);
+
+/**
+ * file_exists
+ *
+ * @param[in] fileName - path to file
+ *
+ * @return true if file exists
+ */
int file_exists (char * fileName);
+
+/**
+ * ltrim
+ *
+ * trim whitespace to the left
+ *
+ * @param[in] s - text to trim
+ *
+ * @return trimmed text
+ */
char *ltrim(char *s);
+
+/**
+ * rtrim
+ *
+ * trim whitespace to the right
+ *
+ * @param[in] s - text to trim
+ *
+ * @return trimmed text
+ */
char *rtrim(char *s);
+
+/**
+ * trim
+ *
+ * trim whitespace from left and right
+ *
+ * @param[in] s - text to trim
+ *
+ * @return trimmed text
+ */
char *trim(char *s);
+
+/**
+ * set_default_options
+ *
+ * fill in default options
+ *
+ * @param[in] opt - option structure
+ *
+ * @return true on success
+ */
int set_default_options(mod_gm_opt_t *opt);
+
+/**
+ * lc
+ *
+ * lowercase given text
+ *
+ * @param[in] str - text to lowercase
+ *
+ * @return lowercased text
+ */
char *lc(char * str);
+
+/**
+ * parse_args_line
+ *
+ * parse the command line arguments in our options structure
+ *
+ * @param[in] opt - options structure
+ * @param[in] arg - arguments
+ * @param[in] recursion_level - counter for the recursion level
+ *
+ * @return true on success
+ */
int parse_args_line(mod_gm_opt_t *opt, char * arg, int recursion_level);
+
+/**
+ * parse_yes_or_no
+ *
+ * parse a string for yes/no, on/off
+ *
+ * @param[in] value - string to parse
+ * @param[in] dfl - default value if none matches
+ *
+ * @return parsed value
+ */
int parse_yes_or_no(char*value, int dfl);
+
+/**
+ * read_config_file
+ *
+ * read config options from a file
+ *
+ * @param[in] opt - options structure
+ * @param[in] filename - file to parse
+ * @param[in] recursion_level - counter for the recursion level
+ *
+ * @return true on success
+ */
int read_config_file(mod_gm_opt_t *opt, char*filename, int recursion_level);
+
+/**
+ * dumpconfig
+ *
+ * dumps config with logger
+ *
+ * @param[in] opt - options structure
+ * @param[in] mode - display mode
+ *
+ * @return nothing
+ */
void dumpconfig(mod_gm_opt_t *opt, int mode);
+
+/**
+ * mod_gm_free_opt
+ *
+ * free options structure
+ *
+ * @param[in] opt - options structure
+ *
+ * @return nothing
+ */
void mod_gm_free_opt(mod_gm_opt_t *opt);
+
+/**
+ * read_keyfile
+ *
+ * read keyfile into options structure
+ *
+ * @param[in] opt - options structure
+ *
+ * @return true on success
+ */
int read_keyfile(mod_gm_opt_t *opt);
+
+/**
+ * nr2signal
+ *
+ * get name for a signal number
+ *
+ * @param[in] sig - signal number
+ *
+ * @return name for this signal
+ */
char * nr2signal(int sig);
+
+/**
+ * string2timeval
+ *
+ * parse string into timeval
+ *
+ * @param[in] value - string to parse
+ * @param[out] t - pointer to timeval structure
+ *
+ * @return nothing
+ */
void string2timeval(char * value, struct timeval * t);
+
+/**
+ * timeval2double
+ *
+ * convert timeval into double
+ *
+ * @param[in] t - timeval structure
+ *
+ * @return double value for this timeval structure
+ */
double timeval2double(struct timeval * t);
+
+/**
+ * mod_gm_time_compare
+ *
+ * get difference between two timeval
+ *
+ * @param[in] tv1 - first timeval
+ * @param[in] tv2 - second timeval
+ *
+ * @return difference in seconds
+ */
long mod_gm_time_compare(struct timeval * tv1, struct timeval * tv2);
+
+/**
+ * extract_check_result
+ *
+ * get result from a file pointer
+ *
+ * @param[in] fp - file pointer to executed command
+ *
+ * @return check result
+ */
char *extract_check_result(FILE *fp);
+
+/**
+ * parse_command_line
+ *
+ * parse command line into argv array
+ *
+ * @param[in] cmd - command line
+ * @param[out] argv - argv array
+ *
+ * @return true on success
+ */
int parse_command_line(char *cmd, char *argv[GM_LISTSIZE]);
+
+/**
+ * run_check
+ *
+ * run a command
+ *
+ * @param[in] processed_command - command line
+ * @param[out] plugin_output - pointer to plugin output
+ *
+ * @return true on success
+ */
int run_check(char *processed_command, char **plugin_output);
+/**
+ *
+ * execute_safe_command
+ *
+ * execute command and fill the exec job structure
+ *
+ * @param[in] exec_job - job structure
+ * @param[in] fork_exec - fork or not before exec
+ * @param[in] hostname - current worker hostname
+ *
+ * @return true on success
+ */
+int execute_safe_command(gm_job_t * exec_job, int fork_exec, char * hostname);
+
+/**
+ *
+ * check_alarm_handler
+ *
+ * called when a check runs into the timeout
+ *
+ * @param[in] sig - signal number
+ *
+ * @return nothing
+ */
+void check_alarm_handler(int sig);
+
+/**
+ *
+ * set_default_job
+ *
+ * fill defaults into job structure
+ *
+ * @param[in] job - job structure to be filled
+ * @param[in] mod_gm_opt - options structure
+ *
+ * @return true on success
+ */
+int set_default_job(gm_job_t *job, mod_gm_opt_t *mod_gm_opt);
+
+/**
+ *
+ * free_job
+ *
+ * free job structure
+ *
+ * @param[in] job - job structure to be freed
+ *
+ * @return true on success
+ */
+int free_job(gm_job_t *job);
+
+/**
+ * pid_alive
+ *
+ * check if a pid is alive
+ *
+ * @param[in] pid - pid to check
+ *
+ * @return true if pid is alive
+ */
+int pid_alive(int pid);
+
+/**
+ * @}
+ */
\ No newline at end of file
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/worker.h
^
|
@@ -21,7 +21,7 @@
*
*****************************************************************************/
-#define MOD_GM_WORKER
+#define MOD_GM_WORKER /**< set mod_gearman worker features */
#include <stdlib.h>
#include <signal.h>
@@ -34,22 +34,162 @@
#include <libgearman/gearman.h>
#include "common.h"
-int mod_gm_shm_key;
-mod_gm_opt_t *mod_gm_opt;
+/** @file
+ * @brief Mod-Gearman Worker Client
+ * @addtogroup mod_gearman_worker Worker
+ *
+ * Worker command line utility which executes the checks or eventhandler.
+ *
+ * @{
+ */
+
+int mod_gm_shm_key; /**< key for the shared memory segment */
+mod_gm_opt_t *mod_gm_opt; /**< global options structure */
+/** Mod-Gearman Worker
+ *
+ * main function of the worker
+ *
+ * @param[in] argc - number of arguments
+ * @param[in] argv - list of arguments
+ *
+ * @return when worker exits, returns exit code of worker
+ */
int main (int argc, char **argv);
+
+/**
+ * store the commandline to parse it again on reloading the worker
+ *
+ * @param[in] argc - number of arguments
+ * @param[in] argv - list of arguments
+ *
+ * @return TRUE on success or FALSE if not
+ */
int store_original_comandline(int argc, char **argv);
+
+/**
+ * parse the arguments into the global options structure
+ *
+ * @param[in] argc - number of arguments
+ * @param[in] argv - list of arguments
+ *
+ * @return TRUE on success or FALSE if not
+ */
int parse_arguments(int argc, char **argv);
+
+/**
+ * create a new child process
+ *
+ * @param[in] mode - mode for the new child
+ *
+ * @return TRUE on success or FALSE if not
+ */
int make_new_child(int mode);
+
+/**
+ * print the usage and exit
+ *
+ * @return nothing and exits
+ */
void print_usage(void);
+
+/**
+ * print the version and exit
+ *
+ * @return nothing and exits
+ */
void print_version(void);
+
+/**
+ * calculate the new number of child worker
+ *
+ * @param[in] min - minimum number of worker
+ * @param[in] max - maximum number of worker
+ * @param[in] cur_workers - current number of worker
+ * @param[in] cur_jobs - current number of running jobs
+ *
+ * @return new target number of workers
+ */
int adjust_number_of_worker(int min, int max, int cur_workers, int cur_jobs);
-void check_signal(int sig);
+
+/**
+ * creates the shared memory segments for the child communication
+ *
+ * @return nothing
+ */
void setup_child_communicator(void);
+
+/**
+ * finish and clean all childs and shared memory segments, then exit.
+ *
+ * @param[in] sig - signal which caused the exit
+ *
+ * @return nothing
+ */
void clean_exit(int sig);
+
+/**
+ * write the current pid into the pidfile
+ *
+ * @return TRUE on success or FALSE if something went wrong
+ */
int write_pid_file(void);
+
+/**
+ * verify options structure and check for missing options
+ *
+ * @param[in] opt - options structure to verify
+ *
+ * @return TRUE on success or FALSE if something went wrong
+ */
int verify_options(mod_gm_opt_t *opt);
+
+/**
+ * signal handler for the HUP signal
+ *
+ * @param[in] sig - signal
+ *
+ * @return nothing
+ */
void reload_config(int sig);
+
+/**
+ * stop all child
+ *
+ * @param[in] mode - could be stop or restart
+ *
+ * @return nothing
+ */
void stop_childs(int mode);
-void update_runtime_data(void);
+/**
+ * main loop to maintain the child population
+ *
+ * @return nothing
+ */
+void monitor_loop(void);
+
+/**
+ * check and start new worker childs if level is too low
+ *
+ * @return nothing
+ */
+void check_worker_population(void);
+
+/**
+ * returns next number of the shared memory segment for a new child
+ *
+ * @return nothing
+ */
+int get_next_shm_index(void);
+
+/**
+ * count and set the current number of worker
+ *
+ * @return nothing
+ */
+void count_current_worker(void);
+
+/**
+ * @}
+ */
\ No newline at end of file
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/worker_client.h
^
|
@@ -21,6 +21,11 @@
*
*****************************************************************************/
+/** @file
+ * @brief header for mod-gearman worker client component
+ *
+ * @{
+ */
#include <sys/time.h>
#include <signal.h>
@@ -39,40 +44,21 @@
#define GM_WORKER_STANDALONE 1
#define GM_WORKER_STATUS 2
-typedef struct gm_job_struct {
- char * host_name;
- char * service_description;
- char * command_line;
- char * type;
- char * result_queue;
- char * output;
- int return_code;
- int early_timeout;
- int check_options;
- int scheduled_check;
- int reschedule_check;
- int exited_ok;
- int timeout;
- double latency;
- struct timeval core_start_time;
- struct timeval start_time;
- struct timeval finish_time;
-} gm_job_t;
-
-void worker_client(int worker_mode);
+void worker_client(int worker_mode, int indx, int shid);
void worker_loop(void);
void *get_job( gearman_job_st *, void *, size_t *, gearman_return_t * );
void do_exec_job(void);
int set_worker( gearman_worker_st *worker );
void send_result_back(void);
-void alarm_sighandler(int sig);
-void send_state_to_parent(int status);
-void execute_safe_command(void);
+void idle_sighandler(int sig);
+void set_state(int status);
void clean_worker_exit(int sig);
void *return_status( gearman_job_st *, void *, size_t *, gearman_return_t *);
-int set_default_job(gm_job_t *job);
-int free_job(gm_job_t *job);
#ifdef GM_DEBUG
void write_debug_file(char ** text);
#endif
+
+/**
+ * @}
+ */
\ No newline at end of file
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/include/worker_logger.h
^
|
@@ -21,6 +21,10 @@
*
*****************************************************************************/
+/** @file
+ * @brief header for mod-gearman worker logger
+ */
+
#include <stdio.h>
#include <string.h>
#include <time.h>
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/neb_module/mod_gearman.c
^
|
@@ -69,8 +69,6 @@
static check_result * merge_result_lists(check_result * lista, check_result * listb);
static void move_results_to_core(void);
-
-/* this function gets initally called when loading the module */
int nebmodule_init( int flags, char *args, nebmodule *handle ) {
/* save our handle */
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/t/01-utils.c
^
|
@@ -9,52 +9,54 @@
#include <utils.h>
int main(void) {
- plan_tests(37);
+ plan(37);
/* lowercase */
char test[100];
- ok1(lc(NULL) == NULL);
- strcpy(test, "Yes"); ok1(strcmp(lc(test), "yes") == 0);
- strcpy(test, "YES"); ok1(strcmp(lc(test), "yes") == 0);
- strcpy(test, "yeS"); ok1(strcmp(lc(test), "yes") == 0);
+ ok(lc(NULL) == NULL, "lc(NULL)");
+ strcpy(test, "Yes"); ok(strcmp(lc(test), "yes") == 0, "lc(yes)");
+ strcpy(test, "YES"); ok(strcmp(lc(test), "yes") == 0, "lc(YES)");
+ strcpy(test, "yeS"); ok(strcmp(lc(test), "yes") == 0, "lc(yeS)");
/* parse_yes_or_no */
- ok1(parse_yes_or_no(NULL, GM_ENABLED) == GM_ENABLED);
- ok1(parse_yes_or_no(NULL, GM_DISABLED) == GM_DISABLED);
- strcpy(test, ""); ok1(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED);
- strcpy(test, ""); ok1(parse_yes_or_no(test, GM_DISABLED) == GM_DISABLED);
- strcpy(test, "yes"); ok1(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED);
- strcpy(test, "true"); ok1(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED);
- strcpy(test, "Yes"); ok1(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED);
- strcpy(test, "1"); ok1(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED);
- strcpy(test, "On"); ok1(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED);
- strcpy(test, "Off"); ok1(parse_yes_or_no(test, GM_ENABLED) == GM_DISABLED);
- strcpy(test, "false"); ok1(parse_yes_or_no(test, GM_ENABLED) == GM_DISABLED);
- strcpy(test, "no"); ok1(parse_yes_or_no(test, GM_ENABLED) == GM_DISABLED);
- strcpy(test, "0"); ok1(parse_yes_or_no(test, GM_ENABLED) == GM_DISABLED);
+ ok(parse_yes_or_no(NULL, GM_ENABLED) == GM_ENABLED, "parse_yes_or_no 1");
+ ok(parse_yes_or_no(NULL, GM_DISABLED) == GM_DISABLED, "parse_yes_or_no 2");
+ strcpy(test, ""); ok(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED, "parse_yes_or_no 3");
+ strcpy(test, ""); ok(parse_yes_or_no(test, GM_DISABLED) == GM_DISABLED, "parse_yes_or_no 4");
+ strcpy(test, "yes"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED, "parse_yes_or_no 5");
+ strcpy(test, "true"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED, "parse_yes_or_no 6");
+ strcpy(test, "Yes"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED, "parse_yes_or_no 7");
+ strcpy(test, "1"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED, "parse_yes_or_no 8");
+ strcpy(test, "On"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED, "parse_yes_or_no 9");
+ strcpy(test, "Off"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_DISABLED, "parse_yes_or_no 10");
+ strcpy(test, "false"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_DISABLED, "parse_yes_or_no 11");
+ strcpy(test, "no"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_DISABLED, "parse_yes_or_no 12");
+ strcpy(test, "0"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_DISABLED, "parse_yes_or_no 13");
/* trim */
- ok1(trim(NULL) == NULL);
- strcpy(test, " test "); ok1(strcmp(trim(test), "test") == 0);
+ ok(trim(NULL) == NULL, "trim(NULL)");
+ strcpy(test, " test "); ok(strcmp(trim(test), "test") == 0, "trim(' test ')");
/* encrypt */
- char * key = "test1234";
+ char * key = "test1234";
char * encrypted = malloc(GM_BUFFERSIZE);
- char * text = "test message";
+ char * text = "test message";
+ char * base = "a7HqhQEE8TQBde9uknpPYQ==";
mod_gm_crypt_init(key);
int len;
len = mod_gm_encrypt(&encrypted, text, GM_ENCODE_AND_ENCRYPT);
ok(len == 24, "length of encrypted only");
- ok(!strcmp(encrypted, "2atT3F70gNGcggA0dHVTRA=="), "encrypted string");
+ if(!ok(!strcmp(encrypted, base), "encrypted string"))
+ diag("expected: '%s' but got: '%s'", base, encrypted);
/* decrypt */
char * decrypted = malloc(GM_BUFFERSIZE);
mod_gm_decrypt(&decrypted, encrypted, GM_ENCODE_AND_ENCRYPT);
- if(!ok(!strcmp(trim(decrypted), text), "decrypted text"))
- diag("expected: '%s' but got: '%s'", text, trim(decrypted));
+ if(!ok(!strcmp(decrypted, text), "decrypted text"))
+ diag("expected: '%s' but got: '%s'", text, decrypted);
free(decrypted);
free(encrypted);
@@ -74,8 +76,8 @@
/* file_exists */
- ok1(file_exists("01_utils") == 1);
- ok1(file_exists("non-exist") == 0);
+ ok(file_exists("01_utils") == 1, "file_exists('01_utils')");
+ ok(file_exists("non-exist") == 0, "file_exists('non-exist')");
/* nr2signal */
char * signame1 = nr2signal(9);
@@ -92,20 +94,20 @@
/* string2timeval */
struct timeval t;
string2timeval("100.50", &t);
- ok1(t.tv_sec == 100);
- ok1(t.tv_usec == 50);
+ ok(t.tv_sec == 100, "string2timeval 1");
+ ok(t.tv_usec == 50, "string2timeval 2");
string2timeval("100", &t);
- ok1(t.tv_sec == 100);
- ok1(t.tv_usec == 0);
+ ok(t.tv_sec == 100, "string2timeval 3");
+ ok(t.tv_usec == 0, "string2timeval 4");
string2timeval("", &t);
- ok1(t.tv_sec == 0);
- ok1(t.tv_usec == 0);
+ ok(t.tv_sec == 0, "string2timeval 5");
+ ok(t.tv_usec == 0, "string2timeval 6");
string2timeval(NULL, &t);
- ok1(t.tv_sec == 0);
- ok1(t.tv_usec == 0);
+ ok(t.tv_sec == 0, "string2timeval 7");
+ ok(t.tv_usec == 0, "string2timeval 8");
return exit_status();
}
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/t/02-full.c
^
|
@@ -14,6 +14,7 @@
#define GEARMAND_TEST_PORT 54730
+char * worker_logfile;
int gearmand_pid;
int worker_pid;
gearman_worker_st worker;
@@ -22,6 +23,7 @@
/* start the gearmand server */
+void *start_gearmand(void*data);
void *start_gearmand(void*data) {
int sid;
data = data; // warning: unused parameter 'data'
@@ -30,7 +32,7 @@
sid = setsid();
char port[30];
snprintf(port, 30, "-p %d", GEARMAND_TEST_PORT);
- execlp("gearmand", "-t 10", "-j 0", port, (char *)NULL);
+ execlp("gearmand", "gearmand", "-t 10", "-j 0", port, (char *)NULL);
perror("gearmand");
exit(1);
}
@@ -42,6 +44,7 @@
/* start the test worker */
+void *start_worker(void*data);
void *start_worker(void*data) {
int sid;
char* key = (char*)data;
@@ -50,12 +53,14 @@
sid = setsid();
char options[150];
snprintf(options, 150, "server=localhost:%d", GEARMAND_TEST_PORT);
+ char logf[150];
+ snprintf(logf, 150, "logfile=%s", worker_logfile);
if(key != NULL) {
char encryption[150];
snprintf(encryption, 150, "key=%s", key);
- execl("./mod_gearman_worker", "debug=0", encryption, "logfile=/dev/null", "max-worker=1", options, (char *)NULL);
+ execl("./mod_gearman_worker", "./mod_gearman_worker", "debug=2", encryption, logf, "max-worker=1", options, (char *)NULL);
} else {
- execl("./mod_gearman_worker", "debug=0", "encryption=no", "logfile=/dev/null", "max-worker=1", options, (char *)NULL);
+ execl("./mod_gearman_worker", "./mod_gearman_worker", "debug=2", "encryption=no", logf, "max-worker=1", options, (char *)NULL);
}
perror("mod_gearman_worker");
exit(1);
@@ -68,6 +73,7 @@
/* test event handler over gearmand */
+void test_eventhandler(int transportmode);
void test_eventhandler(int transportmode) {
char * testdata = "type=eventhandler\ncommand_line=/bin/hostname\n\n\n";
int rt = add_job_to_queue( &client, mod_gm_opt->server_list, "eventhandler", NULL, testdata, GM_JOB_PRIO_NORMAL, 1, transportmode);
@@ -77,6 +83,7 @@
/* test service check handler over gearmand */
+void test_servicecheck(int transportmode);
void test_servicecheck(int transportmode) {
struct timeval start_time;
gettimeofday(&start_time,NULL);
@@ -111,11 +118,43 @@
}
+/* check logfile for errors */
+void check_logfile(void);
+void check_logfile() {
+ FILE * fp;
+ char *line;
+ int errors = 0;
+
+ fp = fopen(worker_logfile, "r");
+ if(fp == NULL) {
+ perror(worker_logfile);
+ return;
+ }
+ line = malloc(GM_BUFFERSIZE);
+ while(fgets(line, GM_BUFFERSIZE, fp) != NULL) {
+ trim(line);
+ if(strstr(line, "ERROR") != NULL) {
+ errors++;
+ diag("logfile: %s", line);
+ }
+ }
+ fclose(fp);
+
+ ok(errors == 0, "errors in logfile: %d", errors);
+
+ /* cleanup logfile */
+ ok(unlink(worker_logfile) == 0, "removed temporary logfile: %s", worker_logfile);
+
+ free(line);
+ return;
+}
+
+
/* main tests */
int main(void) {
- int status;
- int tests = 25;
- plan_tests(tests);
+ int status, chld;
+ int tests = 36;
+ plan(tests);
mod_gm_opt = malloc(sizeof(mod_gm_opt_t));
set_default_options(mod_gm_opt);
@@ -125,17 +164,36 @@
ok(parse_args_line(mod_gm_opt, options, 0) == 0, "parse_args_line()");
mod_gm_opt->debug_level = GM_LOG_ERROR;
+ worker_logfile = tmpnam(NULL);
+ if(!ok(worker_logfile != NULL, "created temp logile: %s", worker_logfile)) {
+ diag("could not create temp logfile");
+ exit( EXIT_FAILURE );
+ }
+
/* first fire up a gearmand server and one worker */
start_gearmand((void*)NULL);
start_worker((void*)NULL);
+ /* wait one second and catch died procs */
sleep(1);
- if(!ok(gearmand_pid > 0, "gearmand running with pid: %d", gearmand_pid))
- diag("make sure gearmand is in your PATH. Usuall locations are /usr/sbin or /usr/local/sbin");
+ while((chld = waitpid(-1, &status, WNOHANG)) != -1 && chld > 0) {
+ diag( "waitpid() %d exited with %d\n", chld, status);
+ }
+
+ if(!ok(gearmand_pid > 0, "'gearmand -t 10 -j 0 -p %d -v -v -v' started with pid: %d", GEARMAND_TEST_PORT, gearmand_pid)) {
+ diag("make sure gearmand is in your PATH. Common locations are /usr/sbin or /usr/local/sbin");
+ exit( EXIT_FAILURE );
+ }
+ if(!ok(pid_alive(gearmand_pid) == TRUE, "gearmand alive")) {
+ exit( EXIT_FAILURE );
+ }
if(!ok(worker_pid > 0, "worker running with pid: %d", worker_pid))
diag("could not start worker");
+ if(!ok(pid_alive(worker_pid) == TRUE, "worker alive")) {
+ exit( EXIT_FAILURE );
+ }
- skip_start(gearmand_pid <= 0 || worker_pid <= 0,
+ skip(gearmand_pid <= 0 || worker_pid <= 0,
tests-3, /* Number of tests to skip */
"Skipping all tests, no need to go on without gearmand or worker");
@@ -145,6 +203,7 @@
/* try to send some data with base64 only */
test_eventhandler(GM_ENCODE_ONLY);
test_servicecheck(GM_ENCODE_ONLY);
+ sleep(1);
char * test_keys[] = {
"12345",
@@ -161,6 +220,7 @@
kill(worker_pid, SIGTERM);
waitpid(worker_pid, &status, 0);
ok(status == 0, "worker exited with exit code %d", real_exit_code(status));
+ check_logfile();
start_worker((void *)test_keys[i]);
sleep(1);
@@ -169,6 +229,7 @@
test_eventhandler(GM_ENCODE_AND_ENCRYPT);
test_servicecheck(GM_ENCODE_AND_ENCRYPT);
+ sleep(1);
}
/* cleanup */
@@ -184,6 +245,6 @@
waitpid(worker_pid, &status, 0);
ok(status == 0, "worker exited with exit code %d", real_exit_code(status));
- skip_end;
+ endskip;
return exit_status();
}
|
[-]
[+]
|
Added |
mod_gearman-1.0.tar.bz2/t/03-exec_checks.c
^
|
@@ -0,0 +1,208 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <t/tap.h>
+#include <worker_logger.h>
+#include <common.h>
+#include <utils.h>
+
+mod_gm_opt_t *mod_gm_opt;
+
+int main(void) {
+ int rc, rrc;
+ char * result;
+ char cmd[100];
+ char hostname[GM_BUFFERSIZE];
+
+ plan(34);
+
+ /* set hostname */
+ gethostname(hostname, GM_BUFFERSIZE-1);
+
+ /* create options structure and set debug level */
+ mod_gm_opt = malloc(sizeof(mod_gm_opt_t));
+ set_default_options(mod_gm_opt);
+ mod_gm_opt->debug_level = 0;
+
+ /*****************************************
+ * arg parsing test 1
+ */
+ char *argv[MAX_CMD_ARGS];
+ strcpy(cmd, "/bin/true");
+ parse_command_line(cmd, argv);
+ if(!ok(argv[0] == cmd, "parsing args cmd 1"))
+ diag("expected '%s' but got '%s'", cmd, argv[0]);
+
+ /*****************************************
+ * arg parsing test 2
+ */
+ strcpy(cmd, "/bin/cmd blah blub foo");
+ parse_command_line(cmd,argv);
+ if(!ok(!strcmp(argv[0], "/bin/cmd"), "parsing args cmd 2"))
+ diag("expected '/bin/cmd' but got '%s'", argv[0]);
+ if(!ok(!strcmp(argv[1], "blah"), "parsing args cmd 2"))
+ diag("expected 'blah' but got '%s'", argv[1]);
+ if(!ok(!strcmp(argv[2], "blub"), "parsing args cmd 2"))
+ diag("expected 'blub' but got '%s'", argv[2]);
+ if(!ok(!strcmp(argv[3], "foo"), "parsing args cmd 2"))
+ diag("expected 'foo' but got '%s'", argv[3]);
+
+ /*****************************************
+ * simple test command 1
+ */
+ strcpy(cmd, "/bin/true");
+ rc = run_check(cmd, &result);
+ if(!ok(rc == 0, "pclose for cmd '%s' returned rc %d", cmd, rc))
+ diag("cmd: '%s' returned %d", cmd, rc);
+ rrc = real_exit_code(rc);
+ if(!ok(rrc == 0, "cmd '%s' returned rc %d", cmd, rrc))
+ diag("cmd: '%s' returned %d", cmd, rrc);
+
+ /*****************************************
+ * simple test command 2
+ */
+ strcpy(cmd, "/bin/true 2>&1");
+ rc = run_check(cmd, &result);
+ if(!ok(rc == 0, "pclose for cmd '%s' returned rc %d", cmd, rc))
+ diag("cmd: '%s' returned %d", cmd, rc);
+ rrc = real_exit_code(rc);
+ if(!ok(rrc == 0, "cmd '%s' returned rc %d", cmd, rrc))
+ diag("cmd: '%s' returned %d", cmd, rrc);
+
+ /*****************************************
+ * simple test command 3
+ */
+ strcpy(cmd, "/usr/lib/nagios/plugins/check_icmp -H 127.0.0.1");
+ rc = run_check(cmd, &result);
+ if(!ok(rc == 0, "pclose for cmd '%s' returned rc %d", cmd, rc))
+ diag("cmd: '%s' returned %d", cmd, rc);
+ rrc = real_exit_code(rc);
+ if(!ok(rrc == 0, "cmd '%s' returned rc %d", cmd, rrc))
+ diag("cmd: '%s' returned %d", cmd, rrc);
+
+ /*****************************************
+ * simple test command 4
+ */
+ strcpy(cmd, "echo -n 'test'; exit 2");
+ rc = run_check(cmd, &result);
+ rrc = real_exit_code(rc);
+ if(!ok(rrc == 2, "cmd '%s' returned rc %d", cmd, rrc))
+ diag("cmd: '%s' returned %d", cmd, rrc);
+ if(!ok(!strcmp(result, "test"), "returned result string"))
+ diag("expected 'test' but got '%s'", result);
+
+ gm_job_t * exec_job;
+ exec_job = ( gm_job_t * )malloc( sizeof *exec_job );
+ set_default_job(exec_job, mod_gm_opt);
+
+
+
+ /*****************************************
+ * non existing command 1
+ */
+ exec_job->command_line = strdup("/bin/doesntexist");
+ exec_job->type = strdup("service");
+ exec_job->timeout = 10;
+ int fork_on_exec = 0;
+
+ execute_safe_command(exec_job, fork_on_exec, hostname);
+ cmp_ok(exec_job->return_code, "==", 2, "cmd '%s' returns rc 2", exec_job->command_line);
+ like(exec_job->output, "CRITICAL: Return code of 127 is out of bounds. Make sure the plugin you're trying to run actually exists. \\(worker:", "returned result string");
+
+ fork_on_exec = 1;
+ lives_ok({execute_safe_command(exec_job, fork_on_exec, hostname);}, "executing command using fork on exec");
+
+ /* non existing command 2 */
+ exec_job->command_line = strdup("/bin/doesntexist 2>&1");
+ execute_safe_command(exec_job, fork_on_exec, hostname);
+ cmp_ok(exec_job->return_code, "==", 2, "cmd '%s' returns rc 2", exec_job->command_line);
+ like(exec_job->output, "CRITICAL: Return code of 127 is out of bounds. Make sure the plugin you're trying to run actually exists. \\(worker:", "returned result string");
+
+
+
+ /*****************************************
+ * non executable command 1
+ */
+ exec_job->command_line = strdup("./THANKS");
+ fork_on_exec = 0;
+
+ execute_safe_command(exec_job, fork_on_exec, hostname);
+ cmp_ok(exec_job->return_code, "==", 2, "cmd '%s' returns rc 2", exec_job->command_line);
+ like(exec_job->output, "CRITICAL: Return code of 126 is out of bounds. Make sure the plugin you're trying to run is executable. \\(worker:", "returned result string");
+
+ /* non existing command 2 */
+ fork_on_exec = 1;
+ exec_job->command_line = strdup("./THANKS 2>&1");
+ execute_safe_command(exec_job, fork_on_exec, hostname);
+ cmp_ok(exec_job->return_code, "==", 2, "cmd '%s' returns rc 2", exec_job->command_line);
+ like(exec_job->output, "CRITICAL: Return code of 126 is out of bounds. Make sure the plugin you're trying to run is executable. \\(worker:", "returned result string");
+
+
+
+ /*****************************************
+ * unknown exit code 1
+ */
+ exec_job->command_line = strdup("./t/rc 5");
+ fork_on_exec = 1;
+
+ execute_safe_command(exec_job, fork_on_exec, hostname);
+ cmp_ok(exec_job->return_code, "==", 2, "cmd '%s' returns rc 2", exec_job->command_line);
+ like(exec_job->output, "CRITICAL: Return code of 5 is out of bounds. \\(worker:", "returned result string");
+
+ /* unknown exit code 2 */
+ fork_on_exec = 0;
+ exec_job->command_line = strdup("./t/rc 5 2>&1");
+ execute_safe_command(exec_job, fork_on_exec, hostname);
+ cmp_ok(exec_job->return_code, "==", 2, "cmd '%s' returns rc 2", exec_job->command_line);
+ like(exec_job->output, "CRITICAL: Return code of 5 is out of bounds. \\(worker:", "returned result string");
+
+
+
+ /*****************************************
+ * signaled exit code SIGINT
+ */
+ exec_job->command_line = strdup("./t/killer INT");
+ fork_on_exec = 1;
+
+ execute_safe_command(exec_job, fork_on_exec, hostname);
+ cmp_ok(exec_job->return_code, "==", 2, "cmd '%s' returns rc 2", exec_job->command_line);
+ like(exec_job->output, "CRITICAL: Return code of 130 is out of bounds. Plugin exited by signal SIGINT. \\(worker:", "returned result string");
+
+ /* signaled exit code SIGINT 2 */
+ fork_on_exec = 0;
+ exec_job->command_line = strdup("./t/killer INT 2>&1");
+ execute_safe_command(exec_job, fork_on_exec, hostname);
+ cmp_ok(exec_job->return_code, "==", 2, "cmd '%s' returns rc 2", exec_job->command_line);
+ like(exec_job->output, "CRITICAL: Return code of 130 is out of bounds. Plugin exited by signal SIGINT. \\(worker:", "returned result string");
+
+
+
+ /*****************************************
+ * timed out check
+ */
+ exec_job->command_line = strdup("./t/sleep 30");
+ exec_job->timeout = 2;
+ fork_on_exec = 1;
+
+ execute_safe_command(exec_job, fork_on_exec, hostname);
+ cmp_ok(exec_job->return_code, "==", 2, "cmd '%s' returns rc 2", exec_job->command_line);
+ like(exec_job->output, "\\(Service Check Timed Out On Worker: ", "returned result string");
+
+ /* timed out check 2 */
+ fork_on_exec = 0;
+ exec_job->command_line = strdup("./t/sleep 30 2>&1");
+ execute_safe_command(exec_job, fork_on_exec, hostname);
+ cmp_ok(exec_job->return_code, "==", 2, "cmd '%s' returns rc 2", exec_job->command_line);
+ like(exec_job->output, "\\(Service Check Timed Out On Worker: ", "returned result string");
+
+ /* reset timeout */
+ exec_job->timeout = 30;
+
+
+ /* clean up */
+ free_job(exec_job);
+
+ return exit_status();
+}
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/t/tap.c
^
|
@@ -1,436 +1,294 @@
-/*-
- * Copyright (c) 2004 Nik Clayton
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#define _GNU_SOURCE
-#include <ctype.h>
-#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
-
+#include <stdarg.h>
+#include <string.h>
#include "tap.h"
-static int no_plan = 0;
-static int skip_all = 0;
-static int have_plan = 0;
-static unsigned int test_count = 0; /* Number of tests that have been run */
-static unsigned int e_tests = 0; /* Expected number of tests to run */
-static unsigned int failures = 0; /* Number of tests that failed */
-static char *todo_msg = NULL;
-static char *todo_msg_fixed = "libtap malloc issue";
-static int todo = 0;
-static int test_died = 0;
-
-/* Encapsulate the pthread code in a conditional. In the absence of
- libpthread the code does nothing */
-#ifdef HAVE_LIBPTHREAD
-#include <pthread.h>
-static pthread_mutex_t M = PTHREAD_MUTEX_INITIALIZER;
-# define LOCK pthread_mutex_lock(&M);
-# define UNLOCK pthread_mutex_unlock(&M);
-#else
-# define LOCK
-# define UNLOCK
-#endif
+static int expected_tests = NO_PLAN;
+static int failed_tests;
+static int current_test;
+static char *todo_mesg;
-static void _expected_tests(unsigned int);
-static void _tap_init(void);
-static void _cleanup(void);
-
-/*
- * Generate a test result.
- *
- * ok -- boolean, indicates whether or not the test passed.
- * test_name -- the name of the test, may be NULL
- * test_comment -- a comment to print afterwards, may be NULL
- */
-unsigned int
-_gen_result(int ok, const char *func, char *file, unsigned int line,
- char *test_name, ...)
-{
- va_list ap;
- char *local_test_name = NULL;
- char *c;
- int name_is_digits;
-
- LOCK;
-
- test_count++;
-
- /* Start by taking the test name and performing any printf()
- expansions on it */
- if(test_name != NULL) {
- va_start(ap, test_name);
- vasprintf(&local_test_name, test_name, ap);
- va_end(ap);
-
- /* Make sure the test name contains more than digits
- and spaces. Emit an error message and exit if it
- does */
- if(local_test_name) {
- name_is_digits = 1;
- for(c = local_test_name; *c != '\0'; c++) {
- if(!isdigit(*c) && !isspace(*c)) {
- name_is_digits = 0;
- break;
- }
- }
-
- if(name_is_digits) {
- diag(" You named your test '%s'. You shouldn't use numbers for your test names.", local_test_name);
- diag(" Very confusing.");
- }
- }
- }
-
- if(!ok) {
- printf("not ");
- failures++;
- }
-
- printf("ok %d", test_count);
-
- if(test_name != NULL) {
- printf(" - ");
-
- /* Print the test name, escaping any '#' characters it
- might contain */
- if(local_test_name != NULL) {
- flockfile(stdout);
- for(c = local_test_name; *c != '\0'; c++) {
- if(*c == '#')
- fputc('\\', stdout);
- fputc((int)*c, stdout);
- }
- funlockfile(stdout);
- } else { /* vasprintf() failed, use a fixed message */
- printf("%s", todo_msg_fixed);
- }
- }
-
- /* If we're in a todo_start() block then flag the test as being
- TODO. todo_msg should contain the message to print at this
- point. If it's NULL then asprintf() failed, and we should
- use the fixed message.
-
- This is not counted as a failure, so decrement the counter if
- the test failed. */
- if(todo) {
- printf(" # TODO %s", todo_msg ? todo_msg : todo_msg_fixed);
- if(!ok)
- failures--;
- }
-
- printf("\n");
-
- if(!ok)
- diag(" Failed %stest (%s:%s() at line %d)",
- todo ? "(TODO) " : "", file, func, line);
-
- free(local_test_name);
-
- UNLOCK;
-
- /* We only care (when testing) that ok is positive, but here we
- specifically only want to return 1 or 0 */
- return ok ? 1 : 0;
-}
-
-/*
- * Initialise the TAP library. Will only do so once, however many times it's
- * called.
- */
void
-_tap_init(void)
-{
- static int run_once = 0;
-
- LOCK;
-
- if(!run_once) {
- atexit(_cleanup);
-
- /* stdout needs to be unbuffered so that the output appears
- in the same place relative to stderr output as it does
- with Test::Harness */
- setbuf(stdout, 0);
- run_once = 1;
- }
-
- UNLOCK;
+plan (int tests) {
+ expected_tests = tests;
+ if (tests != NO_PLAN)
+ printf("1..%d\n", tests);
+}
+
+static char *
+vstrdupf (const char *fmt, va_list args) {
+ char *str;
+ int size;
+ va_list args2;
+ va_copy(args2, args);
+ if (!fmt)
+ fmt = "";
+ size = vsnprintf(NULL, 0, fmt, args2) + 2;
+ str = malloc(size);
+ vsprintf(str, fmt, args);
+ va_end(args2);
+ return str;
}
-/*
- * Note that there's no plan.
- */
int
-plan_no_plan(void)
+vok_at_loc (const char *file, int line, int test, const char *fmt,
+ va_list args)
{
-
- LOCK;
-
- _tap_init();
-
- if(have_plan != 0) {
- fprintf(stderr, "You tried to plan twice!\n");
- test_died = 1;
- UNLOCK;
- exit(255);
- }
-
- have_plan = 1;
- no_plan = 1;
-
- UNLOCK;
-
- return 0;
+ char *name = vstrdupf(fmt, args);
+ printf("%sok %d", test ? "" : "not ", ++current_test);
+ if (*name)
+ printf(" - %s", name);
+ if (todo_mesg) {
+ printf(" # TODO");
+ if (*todo_mesg)
+ printf(" %s", todo_mesg);
+ }
+ printf("\n");
+ if (!test) {
+ if (*name)
+ diag(" Failed%s test '%s'\n at %s line %d.",
+ todo_mesg ? " (TODO)" : "", name, file, line);
+ else
+ diag(" Failed%s test at %s line %d.",
+ todo_mesg ? " (TODO)" : "", file, line);
+ if (!todo_mesg)
+ failed_tests++;
+ }
+ free(name);
+ return test;
}
-/*
- * Note that the plan is to skip all tests
- */
int
-plan_skip_all(char *reason)
-{
-
- LOCK;
-
- _tap_init();
-
- skip_all = 1;
-
- printf("1..0");
-
- if(reason != NULL)
- printf(" # Skip %s", reason);
-
- printf("\n");
-
- UNLOCK;
+ok_at_loc (const char *file, int line, int test, const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ vok_at_loc(file, line, test, fmt, args);
+ va_end(args);
+ return test;
+}
- exit(0);
+static int
+mystrcmp (const char *a, const char *b) {
+ return a == b ? 0 : !a ? -1 : !b ? 1 : strcmp(a, b);
}
-/*
- * Note the number of tests that will be run.
- */
+#define eq(a, b) (!mystrcmp(a, b))
+#define ne(a, b) (mystrcmp(a, b))
+
int
-plan_tests(unsigned int tests)
+is_at_loc (const char *file, int line, const char *got, const char *expected,
+ const char *fmt, ...)
{
-
- LOCK;
-
- _tap_init();
-
- if(have_plan != 0) {
- fprintf(stderr, "You tried to plan twice!\n");
- test_died = 1;
- UNLOCK;
- exit(255);
- }
-
- if(tests == 0) {
- fprintf(stderr, "You said to run 0 tests! You've got to run something.\n");
- test_died = 1;
- UNLOCK;
- exit(255);
- }
-
- have_plan = 1;
-
- _expected_tests(tests);
-
- UNLOCK;
-
- return 0;
+ int test = eq(got, expected);
+ va_list args;
+ va_start(args, fmt);
+ vok_at_loc(file, line, test, fmt, args);
+ va_end(args);
+ if (!test) {
+ diag(" got: '%s'", got);
+ diag(" expected: '%s'", expected);
+ }
+ return test;
}
-unsigned int
-diag(char *fmt, ...)
+int
+isnt_at_loc (const char *file, int line, const char *got, const char *expected,
+ const char *fmt, ...)
{
- va_list ap;
-
- LOCK;
-
- fputs("# ", stderr);
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- fputs("\n", stderr);
-
- UNLOCK;
-
- return 0;
+ int test = ne(got, expected);
+ va_list args;
+ va_start(args, fmt);
+ vok_at_loc(file, line, test, fmt, args);
+ va_end(args);
+ if (!test) {
+ diag(" got: '%s'", got);
+ diag(" expected: anything else");
+ }
+ return test;
}
-void
-_expected_tests(unsigned int tests)
+int
+cmp_ok_at_loc (const char *file, int line, int a, const char *op, int b,
+ const char *fmt, ...)
{
-
- LOCK;
-
- printf("1..%d\n", tests);
- e_tests = tests;
-
- UNLOCK;
+ int test = eq(op, "||") ? a || b
+ : eq(op, "&&") ? a && b
+ : eq(op, "|") ? a | b
+ : eq(op, "^") ? a ^ b
+ : eq(op, "&") ? a & b
+ : eq(op, "==") ? a == b
+ : eq(op, "!=") ? a != b
+ : eq(op, "<") ? a < b
+ : eq(op, ">") ? a > b
+ : eq(op, "<=") ? a <= b
+ : eq(op, ">=") ? a >= b
+ : eq(op, "<<") ? a << b
+ : eq(op, ">>") ? a >> b
+ : eq(op, "+") ? a + b
+ : eq(op, "-") ? a - b
+ : eq(op, "*") ? a * b
+ : eq(op, "/") ? a / b
+ : eq(op, "%") ? a % b
+ : diag("unrecognized operator '%s'", op);
+ va_list args;
+ va_start(args, fmt);
+ vok_at_loc(file, line, test, fmt, args);
+ va_end(args);
+ if (!test) {
+ diag(" %d", a);
+ diag(" %s", op);
+ diag(" %d", b);
+ }
+ return test;
+}
+
+static void
+vdiag_to_fh (FILE *fh, const char *fmt, va_list args) {
+ char *mesg, *line;
+ int i;
+ if (!fmt)
+ return;
+ mesg = vstrdupf(fmt, args);
+ line = mesg;
+ for (i = 0; *line; i++) {
+ char c = mesg[i];
+ if (!c || c == '\n') {
+ mesg[i] = '\0';
+ fprintf(fh, "# %s\n", line);
+ if (!c) break;
+ mesg[i] = c;
+ line = &mesg[i+1];
+ }
+ }
+ free(mesg);
+ return;
}
int
-skip(unsigned int n, char *fmt, ...)
-{
- va_list ap;
- char *skip_msg;
-
- LOCK;
-
- va_start(ap, fmt);
- asprintf(&skip_msg, fmt, ap);
- va_end(ap);
-
- while(n-- > 0) {
- test_count++;
- printf("ok %d # skip %s\n", test_count,
- skip_msg != NULL ?
- skip_msg : "libtap():malloc() failed");
- }
-
- free(skip_msg);
+diag (const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ vdiag_to_fh(stderr, fmt, args);
+ va_end(args);
+ return 0;
+}
- UNLOCK;
+int
+note (const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ vdiag_to_fh(stdout, fmt, args);
+ va_end(args);
+ return 0;
+}
- return 1;
+int
+exit_status () {
+ int retval = 0;
+ if (expected_tests == NO_PLAN) {
+ printf("1..%d\n", current_test);
+ }
+ else if (current_test != expected_tests) {
+ diag("Looks like you planned %d test%s but ran %d.",
+ expected_tests, expected_tests > 1 ? "s" : "", current_test);
+ retval = 255;
+ }
+ if (failed_tests) {
+ diag("Looks like you failed %d test%s of %d run.",
+ failed_tests, failed_tests > 1 ? "s" : "", current_test);
+ if (expected_tests == NO_PLAN)
+ retval = failed_tests;
+ else
+ retval = expected_tests - current_test + failed_tests;
+ }
+ return retval;
}
void
-todo_start(char *fmt, ...)
-{
- va_list ap;
-
- LOCK;
-
- va_start(ap, fmt);
- vasprintf(&todo_msg, fmt, ap);
- va_end(ap);
-
- todo = 1;
+skippy (int n, const char *fmt, ...) {
+ char *why;
+ va_list args;
+ va_start(args, fmt);
+ why = vstrdupf(fmt, args);
+ va_end(args);
+ while (n --> 0) {
+ printf("ok %d ", ++current_test);
+ note("skip %s\n", why);
+ }
+ free(why);
+}
- UNLOCK;
+void
+ctodo (int ignore, const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ todo_mesg = vstrdupf(fmt, args);
+ va_end(args);
}
void
-todo_end(void)
-{
+cendtodo () {
+ free(todo_mesg);
+ todo_mesg = NULL;
+}
- LOCK;
+#ifndef _WIN32
+#include <sys/mman.h>
+#include <regex.h>
- todo = 0;
- free(todo_msg);
+#ifdef __APPLE__
+#define MAP_ANONYMOUS MAP_ANON
+#endif
- UNLOCK;
+/* Create a shared memory int to keep track of whether a piece of code executed
+dies. to be used in the dies_ok and lives_ok macros */
+int
+tap_test_died (int status) {
+ static int *test_died = NULL;
+ int prev;
+ if (!test_died) {
+ test_died = mmap(0, sizeof (int), PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+ *test_died = 0;
+ }
+ prev = *test_died;
+ *test_died = status;
+ return prev;
}
int
-exit_status(void)
+like_at_loc (int for_match, const char *file, int line, const char *got,
+ const char *expected, const char *fmt, ...)
{
- int r;
-
- LOCK;
-
- /* If there's no plan, just return the number of failures */
- if(no_plan || !have_plan) {
- UNLOCK;
- return failures;
- }
-
- /* Ran too many tests? Return the number of tests that were run
- that shouldn't have been */
- if(e_tests < test_count) {
- r = test_count - e_tests;
- UNLOCK;
- return r;
- }
-
- /* Return the number of tests that failed + the number of tests
- that weren't run */
- r = failures + e_tests - test_count;
- UNLOCK;
-
- return r;
-}
-
-/*
- * Cleanup at the end of the run, produce any final output that might be
- * required.
- */
-void
-_cleanup(void)
-{
-
- LOCK;
-
- /* If plan_no_plan() wasn't called, and we don't have a plan,
- and we're not skipping everything, then something happened
- before we could produce any output */
- if(!no_plan && !have_plan && !skip_all) {
- diag("Looks like your test died before it could output anything.");
- UNLOCK;
- return;
- }
-
- if(test_died) {
- diag("Looks like your test died just after %d.", test_count);
- UNLOCK;
- return;
- }
-
-
- /* No plan provided, but now we know how many tests were run, and can
- print the header at the end */
- if(!skip_all && (no_plan || !have_plan)) {
- printf("1..%d\n", test_count);
- }
-
- if((have_plan && !no_plan) && e_tests < test_count) {
- diag("Looks like you planned %d tests but ran %d extra.",
- e_tests, test_count - e_tests);
- UNLOCK;
- return;
- }
-
- if((have_plan || !no_plan) && e_tests > test_count) {
- diag("Looks like you planned %d tests but only ran %d.",
- e_tests, test_count);
- UNLOCK;
- return;
- }
-
- if(failures)
- diag("Looks like you failed %d tests of %d.",
- failures, test_count);
-
- UNLOCK;
+ int test;
+ regex_t re;
+ int err = regcomp(&re, expected, REG_EXTENDED);
+ if (err) {
+ char errbuf[256];
+ regerror(err, &re, errbuf, sizeof errbuf);
+ fprintf(stderr, "Unable to compile regex '%s': %s at %s line %d\n",
+ expected, errbuf, file, line);
+ exit(255);
+ }
+ err = regexec(&re, got, 0, NULL, 0);
+ regfree(&re);
+ test = for_match ? !err : err;
+ va_list args;
+ va_start(args, fmt);
+ vok_at_loc(file, line, test, fmt, args);
+ va_end(args);
+ if (!test) {
+ if (for_match) {
+ diag(" '%s'", got);
+ diag(" doesn't match: '%s'", expected);
+ }
+ else {
+ diag(" '%s'", got);
+ diag(" matches: '%s'", expected);
+ }
+ }
+ return test;
}
+#endif
+
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/t/tap.h
^
|
@@ -1,89 +1,85 @@
-/*-
- * Copyright (c) 2004 Nik Clayton
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* '## __VA_ARGS__' is a gcc'ism. C99 doesn't allow the token pasting
- and requires the caller to add the final comma if they've ommitted
- the optional arguments */
-#ifdef __GNUC__
-# define ok(e, test, ...) ((e) ? \
- _gen_result(1, __func__, __FILE__, __LINE__, \
- test, ## __VA_ARGS__) : \
- _gen_result(0, __func__, __FILE__, __LINE__, \
- test, ## __VA_ARGS__))
-
-# define ok1(e) ((e) ? \
- _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
- _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
-
-# define pass(test, ...) ok(1, test, ## __VA_ARGS__);
-# define fail(test, ...) ok(0, test, ## __VA_ARGS__);
-
-# define skip_start(test, n, fmt, ...) \
- do { \
- if((test)) { \
- skip(n, fmt, ## __VA_ARGS__); \
- continue; \
- }
-#elif __STDC_VERSION__ >= 199901L /* __GNUC__ */
-# define ok(e, ...) ((e) ? \
- _gen_result(1, __func__, __FILE__, __LINE__, \
- __VA_ARGS__) : \
- _gen_result(0, __func__, __FILE__, __LINE__, \
- __VA_ARGS__))
-
-# define ok1(e) ((e) ? \
- _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
- _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
-
-# define pass(...) ok(1, __VA_ARGS__);
-# define fail(...) ok(0, __VA_ARGS__);
-
-# define skip_start(test, n, ...) \
- do { \
- if((test)) { \
- skip(n, __VA_ARGS__); \
- continue; \
- }
-#else /* __STDC_VERSION__ */
-# error "Needs gcc or C99 compiler for variadic macros."
-#endif /* __STDC_VERSION__ */
-
-# define skip_end } while(0);
-
-unsigned int _gen_result(int, const char *, char *, unsigned int, char *, ...);
-
-int plan_no_plan(void);
-int plan_skip_all(char *);
-int plan_tests(unsigned int);
+#ifndef __TAP_H__
+#define __TAP_H__
-unsigned int diag(char *, ...);
-
-int skip(unsigned int, char *, ...);
-
-void todo_start(char *, ...);
-void todo_end(void);
-
-int exit_status(void);
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#define NO_PLAN -1
+#define ok(...) ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define pass(...) ok(1, ## __VA_ARGS__)
+#define fail(...) ok(0, ## __VA_ARGS__)
+#define is(...) is_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define isnt(...) isnt_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define cmp_ok(...) cmp_ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+
+int vok_at_loc (const char *file, int line, int test, const char *fmt,
+ va_list args);
+void plan (int tests);
+int ok_at_loc (const char *file, int line, int test, const char *fmt,
+ ...);
+int diag (const char *fmt, ...);
+int note (const char *fmt, ...);
+int exit_status (void);
+void skippy (int n, const char *fmt, ...);
+void ctodo (int ignore, const char *fmt, ...);
+void cendtodo (void);
+int is_at_loc (const char *file, int line, const char *got,
+ const char *expected, const char *fmt, ...);
+int isnt_at_loc (const char *file, int line, const char *got,
+ const char *expected, const char *fmt, ...);
+int cmp_ok_at_loc (const char *file, int line, int a, const char *op,
+ int b, const char *fmt, ...);
+
+#ifdef _WIN32
+#define like(...) skippy(1, "like is not implemented on MSWin32")
+#define unlike(...) like()
+#else
+#define like(...) like_at_loc(1, __FILE__, __LINE__, __VA_ARGS__, NULL)
+#define unlike(...) like_at_loc(0, __FILE__, __LINE__, __VA_ARGS__, NULL)
+int like_at_loc (int for_match, const char *file, int line,
+ const char *got, const char *expected,
+ const char *fmt, ...);
+#endif
+
+#define skip(test, ...) do {if (test) {skippy(__VA_ARGS__, NULL); break;}
+#define endskip } while (0)
+
+#define todo(...) ctodo(0, ## __VA_ARGS__, NULL)
+#define endtodo cendtodo()
+
+#define dies_ok(code, ...) dies_ok_common(code, 1, ## __VA_ARGS__)
+#define lives_ok(code, ...) dies_ok_common(code, 0, ## __VA_ARGS__)
+
+#ifdef _WIN32
+#define dies_ok_common(...) \
+ skippy(1, "Death detection is not supported on MSWin32")
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+int tap_test_died (int status);
+#define dies_ok_common(code, for_death, ...) \
+ do { \
+ tap_test_died(1); \
+ int cpid = fork(); \
+ switch (cpid) { \
+ case -1: \
+ perror("fork error"); \
+ exit(EXIT_FAILURE); \
+ case 0: /* child */ \
+ close(1); close(2); \
+ code \
+ tap_test_died(0); \
+ exit(EXIT_SUCCESS); \
+ } \
+ if (waitpid(cpid, NULL, 0) < 0) { \
+ perror("waitpid error"); \
+ exit(EXIT_FAILURE); \
+ } \
+ int it_died = tap_test_died(0); \
+ if (!it_died) {code} \
+ ok(for_death ? it_died : !it_died, ## __VA_ARGS__); \
+ } while (0)
+#endif
+#endif
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/tools/gearman_top.c
^
|
@@ -157,6 +157,7 @@
/* get stats */
stats = malloc(sizeof(mod_gm_server_status_t));
stats->function_num = 0;
+ stats->worker_num = 0;
rc = get_gearman_server_data(stats, &message, &version, server, port);
t = time(NULL);
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/tools/send_gearman.c
^
|
@@ -81,7 +81,6 @@
if ( !strcmp( arg, "help" ) || !strcmp( arg, "--help" ) || !strcmp( arg, "-h" ) ) {
print_usage();
}
- lc(arg);
if(parse_args_line(mod_gm_opt, arg, 0) != GM_OK) {
errors++;
free(arg_c);
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/tools/send_multi.c
^
|
@@ -40,7 +40,7 @@
*/
if(parse_arguments(argc, argv) != GM_OK) {
print_usage();
- exit( EXIT_FAILURE );
+ exit( 3 );
}
/* init crypto functions */
@@ -52,20 +52,24 @@
/* create client */
if ( create_client( mod_gm_opt->server_list, &client ) != GM_OK ) {
- printf( "cannot start client\n" );
- exit( EXIT_FAILURE );
+ printf( "send_multi CRITICAL: cannot start client\n" );
+ exit(2);
}
/* send result message */
signal(SIGALRM, alarm_sighandler);
rc = read_multi_stream(stdin);
- /* if rc > 0, it contains the number of checks being submitted,
+ /* if rc > 0, it contains the number of checks being submitted,
otherwise its an error code (-1 - WARNING, -2 - CRITICAL, -3 - UNKNOWN) */
- if (rc >= 0) {
- gm_log( GM_LOG_INFO, "%d check_multi child check%s submitted\n", rc, (rc>1)?"s":"" );
- rc=0; /* OK */
+ if (rc == 0) {
+ printf( "send_multi WARNING: %d check_multi child checks submitted\n", rc );
+ rc=1; /* WARNING */
+ }
+ else if (rc > 0) {
+ printf( "send_multi OK: %d check_multi child check%s submitted\n", rc, (rc>1)?"s":"" );
+ rc=0; /* OK */
} else {
- rc*=-1;
+ rc*=-2;
}
gearman_client_free( &client );
@@ -94,7 +98,6 @@
if ( !strcmp( arg, "help" ) || !strcmp( arg, "--help" ) || !strcmp( arg, "-h" ) ) {
print_usage();
}
- lc(arg);
if(parse_args_line(mod_gm_opt, arg, 0) != GM_OK) {
errors++;
free(arg_c);
@@ -124,8 +127,8 @@
/* no server specified? then default to localhost */
if(opt->server_num == 0) {
- opt->server_list[opt->server_num] = strdup("localhost");
- opt->server_num++;
+ opt->server_list[opt->server_num] = strdup("localhost");
+ opt->server_num++;
}
/* host is mandatory */
@@ -175,7 +178,7 @@
printf("http://my-plugin.de/wiki/projects/check_multi/feed_passive\n");
printf("\n");
- exit( EXIT_SUCCESS );
+ exit(3);
}
@@ -268,175 +271,194 @@
}
int read_multi_stream(FILE *stream) {
- char buffer[GM_BUFFERSIZE+1];
- unsigned long buflen=0L;
- unsigned long bytes_read=0L;
- char *bufstart=NULL;
- char *bufend=NULL;
- int count=0;
-
- //char outbuf[GM_BUFFERSIZE+1];
-
- do {
- /* opening tag <CHILD> found? read from buffer start with maximum buffer len */
- if ((bufstart=(char *)memmem(buffer,buflen,"<CHILD>",strlen("<CHILD>"))) != NULL) {
-
- /* closing tag </CHILD> found? read after <CHILD> with rest of buffer len */
- if ((bufend=(char *)memmem(bufstart,buflen-(bufstart-buffer),"</CHILD>",strlen("</CHILD>"))) != NULL) {
-
- gm_log( GM_LOG_TRACE, "\tXML chunk %d found: buffer position %3d-%3d length %d bytes\n", count, bufstart-buffer, bufend-buffer, bufend-bufstart);
- /* count valid chunks */
- count++;
-
- /* identify CHILD chunk */
- bufstart+=strlen("<CHILD>");
-
- /* if valid check_multi chunk found, send the result*/
- if (read_child_check(bufstart,bufend)) {
- if (send_result() == GM_ERROR) {
- count--;
- }
- } else {
- count--;
- }
-
- /* shift input rest to buffer start, create space for subsequent reads */
- memmove(buffer,bufend+strlen("</CHILD>"),buflen-(bufend+strlen("</CHILD>")-buffer));
- buflen-=bufend+strlen("</CHILD>")-buffer;
-
- /* start <CHILD> tag found, but no closing tag </CHILD>, buffer too small? */
- } else {
- buflen=0L;
- gm_log( GM_LOG_ERROR, "Error: no closing tag </CHILD> within buffer, buffer size too small? discarding buffer, %ld bytes now\n", buflen);
- return -1;
- }
- gm_log( GM_LOG_TRACE, "\tbuflen after XML chunk parsing:%ld\n", buflen);
-
- /* neither <CHILD> nor </CHILD> found, discard buffer */
- } else {
- /* discard whole buffer but continue */
- buflen=0L;
- gm_log( GM_LOG_TRACE, "Error: no starting tag <CHILD> within buffer - discarding buffer, buflen now %ld bytes\n", buflen);
- }
-
- gm_log( GM_LOG_TRACE, "\ttrying to fill up buffer with %ld bytes from offset %ld\n", GM_BUFFERSIZE-buflen, buflen);
-
- /* read one block of data, or less bytes, if there is still data left */
- alarm(mod_gm_opt->timeout);
- if ((bytes_read=fread(buffer+buflen, 1, GM_BUFFERSIZE-buflen, stream)) == 0L) {
-
- /* break if zero read was caused by an error */
- if (!feof(stream)) {
- perror("fread");
- return -2;
- }
- } else {
-
- /* adjust block len */
- buflen+=bytes_read;
- }
- gm_log( GM_LOG_TRACE, "\tread %ld bytes, %ld bytes remaining in buffer\n", bytes_read, buflen);
- } while (buflen > 0);
- return count;
+ char buffer[GM_BUFFERSIZE+1];
+ unsigned long buflen=0L;
+ unsigned long bytes_read=0L;
+ char *bufstart=NULL;
+ char *bufend=NULL;
+ int count=0;
+
+ do {
+ /* opening tag <CHILD> found? read from buffer start with maximum buffer len */
+ if ((bufstart=(char *)memmem(buffer,buflen,"<CHILD>",strlen("<CHILD>"))) != NULL) {
+
+ /* closing tag </CHILD> found? read after <CHILD> with rest of buffer len */
+ if ((bufend=(char *)memmem(bufstart,buflen-(bufstart-buffer),"</CHILD>",strlen("</CHILD>"))) != NULL) {
+
+ gm_log( GM_LOG_TRACE, "\tXML chunk %d found: buffer position %3d-%3d length %d bytes\n", count, bufstart-buffer, bufend-buffer, bufend-bufstart);
+ /* count valid chunks */
+ count++;
+
+ /* identify CHILD chunk */
+ bufstart+=strlen("<CHILD>");
+
+ /* if valid check_multi chunk found, send the result*/
+ if (read_child_check(bufstart,bufend)) {
+ if (send_result() == GM_ERROR) {
+ count--;
+ }
+ } else {
+ count--;
+ }
+
+ /* shift input rest to buffer start, create space for subsequent reads */
+ memmove(buffer,bufend+strlen("</CHILD>"),buflen-(bufend+strlen("</CHILD>")-buffer));
+ buflen-=bufend+strlen("</CHILD>")-buffer;
+
+ /* start <CHILD> tag found, but no closing tag </CHILD>, buffer too small? */
+ } else {
+ buflen=0L;
+ gm_log( GM_LOG_ERROR, "Error: no closing tag </CHILD> within buffer, buffer size too small? discarding buffer, %ld bytes now\n", buflen);
+ return -1;
+ }
+ gm_log( GM_LOG_TRACE, "\tbuflen after XML chunk parsing:%ld\n", buflen);
+
+ /* neither <CHILD> nor </CHILD> found, discard buffer */
+ } else {
+ /* discard whole buffer but continue */
+ buflen=0L;
+ gm_log( GM_LOG_TRACE, "Error: no starting tag <CHILD> within buffer - discarding buffer, buflen now %ld bytes\n", buflen);
+ }
+
+ gm_log( GM_LOG_TRACE, "\ttrying to fill up buffer with %ld bytes from offset %ld\n", GM_BUFFERSIZE-buflen, buflen);
+
+ /* read one block of data, or less bytes, if there is still data left */
+ alarm(mod_gm_opt->timeout);
+ if ((bytes_read=fread(buffer+buflen, 1, GM_BUFFERSIZE-buflen, stream)) == 0L) {
+
+ /* break if zero read was caused by an error */
+ if (!feof(stream)) {
+ perror("fread");
+ return -2;
+ }
+ } else {
+
+ /* adjust block len */
+ buflen+=bytes_read;
+ }
+ gm_log( GM_LOG_TRACE, "\tread %ld bytes, %ld bytes remaining in buffer\n", bytes_read, buflen);
+ } while (buflen > 0);
+ return count;
}
int read_child_check(char *bufstart, char *bufend) {
- char *attribute=NULL;
+ char *attribute = NULL;
+ char *attribute2 = NULL;
+ char *error = NULL;
+ char temp_buffer[GM_BUFFERSIZE];
+
+ /* child check number */
+ if ((attribute=read_multi_attribute(bufstart,bufend,"no")) == NULL) {
+ return 0;
+ } else {
+ /* skip parent check */
+ if (!strcmp(attribute,"0")) {
+ return 0;
+ }
+ gm_log( GM_LOG_TRACE, "child check: %d\n", atoi(attribute));
+ }
+
+ /* service description */
+ if ((attribute=read_multi_attribute(bufstart,bufend,"name")) == NULL)
+ return 0;
+ mod_gm_opt->service=strdup(attribute);
+ gm_log( GM_LOG_TRACE, "service_description: %s\n", mod_gm_opt->service);
+
+ /* return code */
+ if ((attribute=read_multi_attribute(bufstart,bufend,"rc")) == NULL)
+ return 0;
+ mod_gm_opt->return_code=atoi(attribute);
+ gm_log( GM_LOG_TRACE, "mod_gm_opt->return_code: %d\n", mod_gm_opt->return_code);
+
+ /* start time */
+ if ((attribute=read_multi_attribute(bufstart,bufend,"starttime")) == NULL)
+ return 0;
+ if (strchr(attribute, '.') != NULL) {
+ mod_gm_opt->starttime.tv_sec=atoi(strtok(attribute, "."));
+ mod_gm_opt->starttime.tv_usec=atoi(strtok(NULL, "."));
+ } else {
+ mod_gm_opt->starttime.tv_sec=atoi(attribute);
+ mod_gm_opt->starttime.tv_usec=0;
+ }
+ gm_log( GM_LOG_TRACE, "starttime: %d.%d\n", mod_gm_opt->starttime.tv_sec, mod_gm_opt->starttime.tv_usec);
+
+ /* end time */
+ if ((attribute=read_multi_attribute(bufstart,bufend,"endtime")) == NULL)
+ return 0;
+ if (strchr(attribute, '.') != NULL) {
+ mod_gm_opt->finishtime.tv_sec=atoi(strtok(attribute, "."));
+ mod_gm_opt->finishtime.tv_usec=atoi(strtok(NULL, "."));
+ } else {
+ mod_gm_opt->finishtime.tv_sec=atoi(attribute);
+ mod_gm_opt->finishtime.tv_usec=0;
+ }
+ gm_log( GM_LOG_TRACE, "endtime: %d.%d\n", mod_gm_opt->finishtime.tv_sec, mod_gm_opt->finishtime.tv_usec);
+
+ /* message */
+ if ((attribute=read_multi_attribute(bufstart,bufend,"output")) == NULL)
+ return 0;
+
+ /* stderr */
+ if ((error=read_multi_attribute(bufstart,bufend,"error")) == NULL) {
+ return 0;
+ /* if error found: 'error' -> ' [error]' */
+ } else if (*error) {
+ *(--error)='[';
+ *(--error)=' ';
+ strcat(error,"]");
+ }
+
+ /* performance data */
+ if ((attribute2=read_multi_attribute(bufstart,bufend,"performance")) == NULL) {
+ snprintf( temp_buffer, sizeof( temp_buffer )-1, "%s%s", decode_xml(attribute), decode_xml(error));
+ } else {
+ snprintf( temp_buffer, sizeof( temp_buffer )-1, "%s%s|%s", decode_xml(attribute), decode_xml(error), decode_xml(attribute2));
+ }
+ mod_gm_opt->message=strdup(temp_buffer);
+ gm_log( GM_LOG_TRACE, "mod_gm_opt->message: %s\n", mod_gm_opt->message);
- /* child check number */
- if ((attribute=read_multi_attribute(bufstart,bufend,"no")) == NULL) {
- return 0;
- } else {
- /* skip parent check */
- if (!strcmp(attribute,"0")) {
- return 0;
- }
- gm_log( GM_LOG_TRACE, "child check: %d\n", atoi(attribute));
- }
-
- /* service description */
- if ((attribute=read_multi_attribute(bufstart,bufend,"name")) == NULL) {
- return 0;
- } else {
- mod_gm_opt->service=strdup(attribute);
- gm_log( GM_LOG_TRACE, "service_description: %s\n", mod_gm_opt->service);
- }
-
- /* return code */
- if ((attribute=read_multi_attribute(bufstart,bufend,"rc")) == NULL) {
- return 0;
- } else {
- mod_gm_opt->return_code=atoi(attribute);
- gm_log( GM_LOG_TRACE, "mod_gm_opt->return_code: %d\n", mod_gm_opt->return_code);
- }
-
- /* start time */
- if ((attribute=read_multi_attribute(bufstart,bufend,"starttime")) == NULL) {
- return 0;
- } else {
- mod_gm_opt->starttime.tv_sec=atoi(strtok(attribute, "."));
- mod_gm_opt->starttime.tv_usec=atoi(strtok(NULL, "."));
- gm_log( GM_LOG_TRACE, "starttime: %d.%d\n", mod_gm_opt->starttime.tv_sec, mod_gm_opt->starttime.tv_usec);
- }
-
- /* end time */
- if ((attribute=read_multi_attribute(bufstart,bufend,"endtime")) == NULL) {
- return 0;
- } else {
- mod_gm_opt->finishtime.tv_sec=atoi(strtok(attribute, "."));
- mod_gm_opt->finishtime.tv_usec=atoi(strtok(NULL, "."));
- gm_log( GM_LOG_TRACE, "endtime: %d.%d\n", mod_gm_opt->finishtime.tv_sec, mod_gm_opt->finishtime.tv_usec);
- }
-
- /* message */
- if ((attribute=read_multi_attribute(bufstart,bufend,"output")) == NULL) {
- return 0;
- } else {
- mod_gm_opt->message=strdup(decode_xml(attribute));
- gm_log( GM_LOG_TRACE, "mod_gm_opt->message: %s\n", mod_gm_opt->message);
- }
- return 1;
+ return 1;
}
char *read_multi_attribute(char *bufstart, char *bufend, char *element) {
- char start_element[GM_BUFFERSIZE], end_element[GM_BUFFERSIZE];
- sprintf(start_element, "<%s>", element);
- sprintf(end_element, "</%s>", element);
-
- if ((bufstart=(char *)memmem(bufstart,bufend-bufstart,start_element,strlen(start_element))) == NULL) {
- gm_log( GM_LOG_TRACE, "\tread_multi_attribute: start element \'%s\' not found\n", start_element);
- return NULL;
- }
- bufstart+=strlen(start_element);
- if ((bufend=(char *)memmem(bufstart,bufend-bufstart,end_element,strlen(end_element))) == NULL) {
- gm_log( GM_LOG_TRACE, "\tread_multi_attribute: end element \'%s\' not found\n", end_element);
- return NULL;
- }
- *bufend='\0';
- return bufstart;
+ char start_element[GM_BUFFERSIZE], end_element[GM_BUFFERSIZE];
+ sprintf(start_element, "<%s>", element);
+ sprintf(end_element, "</%s>", element);
+
+ if ((bufstart=(char *)memmem(bufstart,bufend-bufstart,start_element,strlen(start_element))) == NULL) {
+ gm_log( GM_LOG_TRACE, "\tread_multi_attribute: start element \'%s\' not found\n", start_element);
+ return NULL;
+ }
+ bufstart+=strlen(start_element);
+ if ((bufend=(char *)memmem(bufstart,bufend-bufstart,end_element,strlen(end_element))) == NULL) {
+ gm_log( GM_LOG_TRACE, "\tread_multi_attribute: end element \'%s\' not found\n", end_element);
+ return NULL;
+ }
+ *bufend='\0';
+ return bufstart;
}
char *decode_xml(char *string) {
- struct decode{
- char c;
- char *enc_string;
- } dtab[] = {
- { '>', ">" },
- { '<', "<" },
- { '&', "&" },
- };
- int i;
- char *found;
-
- /* foreach XML decode pair */
- for (i=0; i<(int)(sizeof(dtab)/sizeof(struct decode)); i++) {
- /* while XML encoding strings found */
- while ((found=strstr(string, dtab[i].enc_string)) != NULL) {
- /* replace string with character */
- *found=dtab[i].c;
- /* shift rest of string after character */
- strcpy(found+1, found+strlen(dtab[i].enc_string));
- }
+ struct decode{
+ char c;
+ char *enc_string;
+ } dtab[] = {
+ { '>', ">" },
+ { '<', "<" },
+ { '&', "&" },
+ };
+ int i;
+ char *found;
+
+ /* foreach XML decode pair */
+ for (i=0; i<(int)(sizeof(dtab)/sizeof(struct decode)); i++) {
+ /* while XML encoding strings found */
+ while ((found=strstr(string, dtab[i].enc_string)) != NULL) {
+ /* replace string with character */
+ *found=dtab[i].c;
+ /* shift rest of string after character */
+ strcpy(found+1, found+strlen(dtab[i].enc_string));
}
- return string;
+ }
+ return string;
}
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/worker/worker.c
^
|
@@ -33,10 +33,15 @@
int orig_argc;
char ** orig_argv;
+int last_time_increased;
+volatile sig_atomic_t shmid;
+int * shm;
/* work starts here */
int main (int argc, char **argv) {
- int sid, x, status, now, last_time_checked, target_number_of_workers;
+ int sid, x;
+
+ last_time_increased = 0;
/* store the original command line for later reloads */
store_original_comandline(argc, argv);
@@ -99,7 +104,7 @@
/* check and write pid file */
if(write_pid_file() != GM_OK) {
- exit( EXIT_SUCCESS );
+ exit(EXIT_FAILURE);
}
/* init crypto functions */
@@ -111,6 +116,13 @@
gm_log( GM_LOG_DEBUG, "main process started\n");
+ /* start a single non forked standalone worker */
+ if(mod_gm_opt->debug_level >= 10) {
+ gm_log( GM_LOG_TRACE, "starting standalone worker\n");
+ worker_client(GM_WORKER_STANDALONE, 1, shmid);
+ exit(EXIT_SUCCESS);
+ }
+
/* setup shared memory */
setup_child_communicator();
@@ -122,52 +134,131 @@
make_new_child(GM_WORKER_MULTI);
}
+ /* maintain worker population */
+ monitor_loop();
+
+ clean_exit(15);
+ exit( EXIT_SUCCESS );
+}
+
+
+/* main loop for checking worker */
+void monitor_loop() {
+ int status;
+
/* maintain the population */
- now = (int)time(NULL);
- last_time_checked = now;
while (1) {
- /* check number of workers every 3 seconds
- * sleep gets canceled anyway when receiving signals
- */
- sleep(3);
+ /* check number of workers every second */
+ sleep(1);
/* collect finished workers */
- while(waitpid(-1, &status, WNOHANG) > 0) {
- current_number_of_workers--;
- gm_log( GM_LOG_TRACE, "waitpid() %d\n", status);
- update_runtime_data();
- }
+ while(waitpid(-1, &status, WNOHANG) > 0)
+ gm_log( GM_LOG_TRACE, "waitpid() worker exited with: %d\n", status);
- if(current_number_of_jobs < 0) { current_number_of_jobs = 0; }
- if(current_number_of_jobs > current_number_of_workers) { current_number_of_jobs = current_number_of_workers; }
+ check_worker_population();
+ }
+ return;
+}
- /* keep up minimum population */
- for (x = current_number_of_workers; x < mod_gm_opt->min_worker; x++) {
- make_new_child(GM_WORKER_MULTI);
- }
- now = (int)time(NULL);
- if(last_time_checked +2 > now)
- continue;
- last_time_checked = time(NULL);
+/* count current worker and jobs */
+void count_current_worker() {
+ int x;
+
+ gm_log( GM_LOG_TRACE, "count_current_worker()\n");
+ gm_log( GM_LOG_TRACE, "done jobs: shm[0] = %d\n", shm[0]);
+
+ /* shm states:
+ * 0 -> undefined
+ * -1 -> free
+ * <-1 -> used but idle
+ * > 1 -> used and working
+ */
- target_number_of_workers = adjust_number_of_worker(mod_gm_opt->min_worker, mod_gm_opt->max_worker, current_number_of_workers, current_number_of_jobs);
- for (x = current_number_of_workers; x < target_number_of_workers; x++) {
- /* top up the worker pool */
- make_new_child(GM_WORKER_MULTI);
+ /* check if status worker died */
+ if( shm[3] != -1 && pid_alive(shm[3]) == FALSE ) {
+ gm_log( GM_LOG_TRACE, "removed stale status worker, old pid: %d\n", shm[3] );
+ shm[3] = -1;
+ }
+ gm_log( GM_LOG_TRACE, "status worker: shm[3] = %d\n", shm[3]);
+
+ /* check all known worker */
+ current_number_of_workers = 0;
+ current_number_of_jobs = 0;
+ for(x=4; x < mod_gm_opt->max_worker+4; x++) {
+ /* verify worker is alive */
+ if( shm[x] != -1 && pid_alive(shm[x]) == FALSE ) {
+ gm_log( GM_LOG_TRACE, "removed stale worker %d, old pid: %d\n", x, shm[x]);
+ shm[x] = -1;
+ }
+ gm_log( GM_LOG_TRACE, "worker slot: shm[%d] = %d\n", x, shm[x]);
+ if(shm[x] != -1) {
+ current_number_of_workers++;
+ }
+ if(shm[x] > 0) {
+ current_number_of_jobs++;
}
}
- clean_exit(15);
- exit( EXIT_SUCCESS );
+ shm[1] = current_number_of_workers; /* total worker */
+ shm[2] = current_number_of_jobs; /* running worker */
+
+ gm_log( GM_LOG_TRACE, "worker: %d - running: %d\n", current_number_of_workers, current_number_of_jobs);
+
+ return;
+}
+
+/* start new worker if needed */
+void check_worker_population() {
+ int x, now, target_number_of_workers;
+
+ gm_log( GM_LOG_TRACE, "check_worker_population()\n");
+
+ /* set current worker number */
+ count_current_worker();
+
+ /* check if status worker died */
+ if( shm[3] == -1 ) {
+ make_new_child(GM_WORKER_STATUS);
+ }
+
+ /* keep up minimum population */
+ for (x = current_number_of_workers; x < mod_gm_opt->min_worker; x++) {
+ make_new_child(GM_WORKER_MULTI);
+ current_number_of_workers++;
+ }
+
+ now = (int)time(NULL);
+ if(last_time_increased +2 > now)
+ return;
+
+ target_number_of_workers = adjust_number_of_worker(mod_gm_opt->min_worker, mod_gm_opt->max_worker, current_number_of_workers, current_number_of_jobs);
+ for (x = current_number_of_workers; x < target_number_of_workers; x++) {
+ last_time_increased = now;
+ /* top up the worker pool */
+ make_new_child(GM_WORKER_MULTI);
+ }
+ return;
}
/* start up new worker */
int make_new_child(int mode) {
pid_t pid = 0;
+ int next_shm_index;
+
+ gm_log( GM_LOG_TRACE, "make_new_child(%d)\n", mode);
+
+ if(mode == GM_WORKER_STATUS) {
+ gm_log( GM_LOG_TRACE, "forking status worker\n");
+ next_shm_index = 3;
+ } else {
+ gm_log( GM_LOG_TRACE, "forking worker\n");
+ next_shm_index = get_next_shm_index();
+ }
- gm_log( GM_LOG_TRACE, "make_new_child()\n");
+ signal(SIGINT, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
/* fork a child process */
pid=fork();
@@ -181,23 +272,21 @@
/* we are in the child process */
else if(pid==0){
- gm_log( GM_LOG_DEBUG, "worker started with pid: %d\n", getpid() );
- signal(SIGUSR1, SIG_IGN);
- signal(SIGINT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
+ gm_log( GM_LOG_DEBUG, "child started with pid: %d\n", getpid() );
+ shm[next_shm_index] = -getpid();
/* do the real work */
- worker_client(mode);
+ worker_client(mode, next_shm_index, shmid);
exit(EXIT_SUCCESS);
}
/* parent */
else if(pid > 0){
- if(mode != GM_WORKER_STATUS)
- current_number_of_workers++;
- update_runtime_data();
+ signal(SIGINT, clean_exit);
+ signal(SIGTERM,clean_exit);
+ shm[next_shm_index] = -pid;
}
return GM_OK;
@@ -342,6 +431,8 @@
printf("\n");
printf(" [ --server=<server> ]\n");
printf("\n");
+ printf(" [ --dupserver=<server> ]\n");
+ printf("\n");
printf(" [ --hosts ]\n");
printf(" [ --services ]\n");
printf(" [ --events ]\n");
@@ -365,48 +456,31 @@
}
-/* check child signal pipe */
-void check_signal(int sig) {
- gm_log( GM_LOG_TRACE, "check_signal(%i)\n", sig);
- update_runtime_data();
- return;
-}
-
/* create shared memory segments */
void setup_child_communicator() {
- struct sigaction usr1_action;
- sigset_t block_mask;
- int shmid;
- int * shm;
+ int x;
gm_log( GM_LOG_TRACE, "setup_child_communicator()\n");
- /* setup signal handler */
- sigfillset (&block_mask); /* block all signals */
- usr1_action.sa_handler = check_signal;
- usr1_action.sa_mask = block_mask;
- usr1_action.sa_flags = 0;
- sigaction (SIGUSR1, &usr1_action, NULL);
-
/* Create the segment. */
mod_gm_shm_key = getpid(); /* use pid as shm key */
if ((shmid = shmget(mod_gm_shm_key, GM_SHM_SIZE, IPC_CREAT | 0600)) < 0) {
perror("shmget");
- exit(1);
+ exit( EXIT_FAILURE );
}
/* Now we attach the segment to our data space. */
if ((shm = shmat(shmid, NULL, 0)) == (int *) -1) {
perror("shmat");
- exit(1);
+ exit( EXIT_FAILURE );
+ }
+ shm[0] = 0; /* done jobs */
+ shm[1] = 0; /* total worker */
+ shm[2] = 0; /* running worker */
+ shm[3] = -1; /* status worker pid */
+ for(x = 0; x < mod_gm_opt->max_worker; x++) {
+ shm[x+4] = -1; /* status worker */
}
- shm[0] = 0; /* current jobs */
- shm[1] = 0; /* current worker */
- shm[2] = 0; /* done jobs */
-
- /* detach from shared memory */
- if(shmdt(shm) < 0)
- perror("shmdt");
return;
}
@@ -417,6 +491,12 @@
int perc_running;
int idle;
int target = min;
+
+ if(cur_workers == 0) {
+ gm_log( GM_LOG_TRACE, "adjust_number_of_worker(min %d, max %d, worker %d, jobs %d) -> %d\n", min, max, cur_workers, cur_jobs, mod_gm_opt->min_worker);
+ return mod_gm_opt->min_worker;
+ }
+
perc_running = (int)cur_jobs*100/cur_workers;
idle = (int)cur_workers - cur_jobs;
@@ -452,16 +532,12 @@
/* stop all childs */
stop_childs(GM_WORKER_STOP);
- /* kill remaining worker */
- if(current_number_of_workers > 0) {
- pid_t pid = getpid();
- kill(-pid, SIGKILL);
- }
+ /* detach shm */
+ if(shmdt(shm) < 0)
+ perror("shmdt");
gm_log( GM_LOG_INFO, "mod_gearman worker exited\n");
-
mod_gm_free_opt(mod_gm_opt);
-
exit( EXIT_SUCCESS );
}
@@ -470,8 +546,9 @@
void stop_childs(int mode) {
int status, chld;
int waited = 0;
- int shmid;
- int skipfirst = 0;
+ int x, curpid;
+
+ gm_log( GM_LOG_TRACE, "stop_childs(%d)\n", mode);
/* ignore some signals for now */
signal(SIGTERM, SIG_IGN);
@@ -481,56 +558,81 @@
* send term signal to our childs
* children will finish the current job and exit
*/
- gm_log( GM_LOG_TRACE, "send SIGTERM\n");
killpg(0, SIGTERM);
-
- gm_log( GM_LOG_TRACE, "waiting for childs to exit...\n");
while(current_number_of_workers > 0) {
+ gm_log( GM_LOG_TRACE, "send SIGTERM\n");
+ for(x=3; x < mod_gm_opt->max_worker+4; x++) {
+ curpid = shm[x];
+ if(curpid < 0) { curpid = -curpid; }
+ if( curpid != 0 ) {
+ kill(curpid, SIGTERM);
+ }
+ }
while((chld = waitpid(-1, &status, WNOHANG)) != -1 && chld > 0) {
- current_number_of_workers--;
gm_log( GM_LOG_TRACE, "wait() %d exited with %d\n", chld, status);
- /* start one worker less than exited, because of the status worker */
- if(skipfirst == 0 && mode == GM_WORKER_RESTART) {
- make_new_child(GM_WORKER_MULTI);
- }
- skipfirst = 1;
}
sleep(1);
waited++;
if(waited > GM_CHILD_SHUTDOWN_TIMEOUT) {
break;
}
- gm_log( GM_LOG_TRACE, "still waiting (%d)...\n", waited);
+ count_current_worker();
+ if(current_number_of_workers == 0)
+ return;
+ gm_log( GM_LOG_TRACE, "still waiting (%d) %d childs missing...\n", waited, current_number_of_workers);
}
if(mode == GM_WORKER_STOP) {
- if(current_number_of_workers > 0) {
- gm_log( GM_LOG_TRACE, "sending SIGINT...\n");
- killpg(0, SIGINT);
+ killpg(0, SIGINT);
+ count_current_worker();
+ if(current_number_of_workers == 0)
+ return;
+
+ gm_log( GM_LOG_TRACE, "sending SIGINT...\n");
+ for(x=3; x < mod_gm_opt->max_worker+4; x++) {
+ curpid = shm[x];
+ if(curpid < 0) { curpid = -curpid; }
+ if( curpid != 0 ) {
+ kill(curpid, SIGINT);
+ }
}
while((chld = waitpid(-1, &status, WNOHANG)) != -1 && chld > 0) {
- current_number_of_workers--;
gm_log( GM_LOG_TRACE, "wait() %d exited with %d\n", chld, status);
}
+ /* kill them the hard way */
+ count_current_worker();
+ if(current_number_of_workers == 0)
+ return;
+ for(x=3; x < mod_gm_opt->max_worker+4; x++) {
+ if( shm[x] != 0 ) {
+ curpid = shm[x];
+ if(curpid < 0) { curpid = -curpid; }
+ if( curpid != 0 ) {
+ kill(curpid, SIGKILL);
+ }
+ }
+ }
+
+ /* count childs a last time */
+ count_current_worker();
+ if(current_number_of_workers == 0)
+ return;
+
/*
* clean up shared memory
* will be removed when last client detaches
*/
- if ((shmid = shmget(mod_gm_shm_key, GM_SHM_SIZE, 0600)) < 0) {
- perror("shmget");
- }
if( shmctl( shmid, IPC_RMID, 0 ) == -1 ) {
perror("shmctl");
+ } else {
+ gm_log( GM_LOG_TRACE, "shared memory deleted\n");
}
- gm_log( GM_LOG_TRACE, "shared memory deleted\n");
- if(current_number_of_workers > 0) {
- /* this will kill us too */
- gm_log( GM_LOG_TRACE, "sending SIGKILL...\n");
- killpg(0, SIGKILL);
- }
+ /* this will kill us too */
+ gm_log( GM_LOG_ERROR, "exiting by SIGKILL...\n");
+ killpg(0, SIGKILL);
}
/* restore signal handlers for a clean exit */
@@ -621,34 +723,29 @@
}
-/* update the number of worker and jobs */
-void update_runtime_data() {
- int shmid;
- int *shm;
-
- gm_log( GM_LOG_TRACE, "update_worker_num()\n");
-
- /* Locate the segment. */
- if ((shmid = shmget(mod_gm_shm_key, GM_SHM_SIZE, 0600)) < 0) {
- perror("shmget");
- exit(1);
+/* return and reserve next shm index*/
+int get_next_shm_index() {
+ int x;
+ int next_index = 0;
+
+ gm_log( GM_LOG_TRACE, "get_next_shm_index()\n" );
+
+ for(x = 4; x < mod_gm_opt->max_worker+4; x++) {
+ if(shm[x] == -1) {
+ next_index = x;
+ shm[next_index] = 1;
+ break;
+ }
}
- /* Now we attach the segment to our data space. */
- if ((shm = shmat(shmid, NULL, 0)) == (int *) -1) {
- perror("shmat");
- exit(1);
+ if(next_index == 0) {
+ gm_log(GM_LOG_ERROR, "unable to get next shm id\n");
+ clean_exit(15);
+ exit(EXIT_FAILURE);
}
+ gm_log( GM_LOG_TRACE, "get_next_shm_index() -> %d\n", next_index );
- gm_log( GM_LOG_TRACE, "update_runtime_data: %i\n", shm[0]);
- current_number_of_jobs = shm[0];
- shm[1] = current_number_of_workers;
-
- /* detach from shared memory */
- if(shmdt(shm) < 0)
- perror("shmdt");
-
- return;
+ return next_index;
}
|
[-]
[+]
|
Changed |
mod_gearman-1.0.tar.bz2/worker/worker_client.c
^
|
@@ -35,38 +35,51 @@
gearman_worker_st worker;
gearman_client_st client;
+gearman_client_st client_dup;
gm_job_t * current_job;
-pid_t current_child_pid;
+pid_t current_pid;
gm_job_t * exec_job;
int jobs_done = 0;
int sleep_time_after_error = 1;
int worker_run_mode;
-
+int shm_index = 0;
+volatile sig_atomic_t shmid;
/* callback for task completed */
-void worker_client(int worker_mode) {
+void worker_client(int worker_mode, int indx, int shid) {
- gm_log( GM_LOG_TRACE, "worker client started\n" );
+ gm_log( GM_LOG_TRACE, "%s worker client started\n", (worker_mode == GM_WORKER_STATUS ? "status" : "job" ));
/* set signal handlers for a clean exit */
signal(SIGINT, clean_worker_exit);
signal(SIGTERM,clean_worker_exit);
worker_run_mode = worker_mode;
+ shm_index = indx;
+ shmid = shid;
+ current_pid = getpid();
gethostname(hostname, GM_BUFFERSIZE-1);
/* create worker */
if(set_worker(&worker) != GM_OK) {
gm_log( GM_LOG_ERROR, "cannot start worker\n" );
+ clean_worker_exit(0);
exit( EXIT_FAILURE );
}
/* create client */
if ( create_client( mod_gm_opt->server_list, &client ) != GM_OK ) {
gm_log( GM_LOG_ERROR, "cannot start client\n" );
+ clean_worker_exit(0);
+ exit( EXIT_FAILURE );
+ }
+
+ /* create duplicate client */
+ if ( create_client_dup( mod_gm_opt->dupserver_list, &client_dup ) != GM_OK ) {
+ gm_log( GM_LOG_ERROR, "cannot start client for duplicate server\n" );
exit( EXIT_FAILURE );
}
@@ -82,9 +95,11 @@
while ( 1 ) {
gearman_return_t ret;
- /* wait three minutes for a job, otherwise exit */
- if(worker_run_mode == GM_WORKER_MULTI)
+ /* wait for a job, otherwise exit when hit the idle timeout */
+ if(mod_gm_opt->idle_timeout > 0 && worker_run_mode == GM_WORKER_MULTI) {
+ signal(SIGALRM, idle_sighandler);
alarm(mod_gm_opt->idle_timeout);
+ }
signal(SIGPIPE, SIG_IGN);
ret = gearman_worker_work( &worker );
@@ -93,6 +108,8 @@
gearman_job_free_all( &worker );
gearman_worker_free( &worker );
gearman_client_free( &client );
+ if( mod_gm_opt->dupserver_num )
+ gearman_client_free( &client_dup );
/* sleep on error to avoid cpu intensive infinite loops */
sleep(sleep_time_after_error);
@@ -103,6 +120,8 @@
/* create new connections */
set_worker( &worker );
create_client( mod_gm_opt->server_list, &client );
+ if( mod_gm_opt->dupserver_num )
+ create_client_dup( mod_gm_opt->dupserver_list, &client_dup );
}
}
@@ -114,21 +133,21 @@
void *get_job( gearman_job_st *job, void *context, size_t *result_size, gearman_return_t *ret_ptr ) {
sigset_t block_mask;
sigset_t old_mask;
- int wsize;
+ int wsize, valid_lines;
char workload[GM_BUFFERSIZE];
char * decrypted_data;
char * decrypted_data_c;
char * decrypted_orig;
char *ptr;
- char command[GM_BUFFERSIZE];
+
+ /* reset timeout for now, will be set befor execution again */
+ alarm(0);
+ signal(SIGALRM, SIG_IGN);
jobs_done++;
/* send start signal to parent */
- send_state_to_parent(GM_JOB_START);
-
- /* reset timeout for now, will be set befor execution again */
- alarm(0);
+ set_state(GM_JOB_START);
gm_log( GM_LOG_TRACE, "get_job()\n" );
@@ -169,8 +188,9 @@
*ret_ptr= GEARMAN_SUCCESS;
exec_job = ( gm_job_t * )malloc( sizeof *exec_job );
- set_default_job(exec_job);
+ set_default_job(exec_job, mod_gm_opt);
+ valid_lines = 0;
while ( (ptr = strsep(&decrypted_data, "\n" )) != NULL ) {
char *key = strsep( &ptr, "=" );
char *value = strsep( &ptr, "\x0" );
@@ -183,31 +203,37 @@
if ( !strcmp( key, "host_name" ) ) {
exec_job->host_name = strdup(value);
+ valid_lines++;
} else if ( !strcmp( key, "service_description" ) ) {
exec_job->service_description = strdup(value);
+ valid_lines++;
} else if ( !strcmp( key, "type" ) ) {
exec_job->type = strdup(value);
+ valid_lines++;
} else if ( !strcmp( key, "result_queue" ) ) {
exec_job->result_queue = strdup(value);
+ valid_lines++;
} else if ( !strcmp( key, "check_options" ) ) {
exec_job->check_options = atoi(value);
+ valid_lines++;
} else if ( !strcmp( key, "scheduled_check" ) ) {
exec_job->scheduled_check = atoi(value);
+ valid_lines++;
} else if ( !strcmp( key, "reschedule_check" ) ) {
exec_job->reschedule_check = atoi(value);
+ valid_lines++;
} else if ( !strcmp( key, "latency" ) ) {
exec_job->latency = atof(value);
+ valid_lines++;
} else if ( !strcmp( key, "start_time" ) ) {
string2timeval(value, &exec_job->core_start_time);
+ valid_lines++;
} else if ( !strcmp( key, "timeout" ) ) {
exec_job->timeout = atoi(value);
+ valid_lines++;
} else if ( !strcmp( key, "command_line" ) ) {
- /* adding 2>&1 breaks the exec/popen check and everything will be checked by popen */
- /*
- snprintf(command, sizeof(command)+5, "%s 2>&1", value);
- exec_job->command_line = strdup(command);
- */
exec_job->command_line = strdup(value);
+ valid_lines++;
}
}
@@ -216,7 +242,14 @@
write_debug_file(&decrypted_orig);
#endif
- do_exec_job();
+ if(valid_lines == 0) {
+ gm_log( GM_LOG_ERROR, "discarded invalid job, check your encryption settings\n" );
+ } else {
+ do_exec_job();
+ }
+
+ /* send finish signal to parent */
+ set_state(GM_JOB_END);
/* start listening to SIGTERMs */
sigprocmask(SIG_SETMASK, &old_mask, NULL);
@@ -225,15 +258,9 @@
free(decrypted_data_c);
free_job(exec_job);
- /* send finish signal to parent */
- send_state_to_parent(GM_JOB_END);
-
- if(jobs_done >= mod_gm_opt->max_jobs) {
+ if(mod_gm_opt->max_jobs > 0 && jobs_done >= mod_gm_opt->max_jobs) {
gm_log( GM_LOG_TRACE, "jobs done: %i -> exiting...\n", jobs_done );
- gearman_worker_unregister_all(&worker);
- gearman_job_free_all( &worker );
- gearman_client_free( &client );
- mod_gm_free_opt(mod_gm_opt);
+ clean_worker_exit(0);
exit( EXIT_SUCCESS );
}
@@ -243,19 +270,17 @@
/* do some job */
void do_exec_job( ) {
- struct timeval start_time,end_time;
+ struct timeval start_time, end_time;
int latency;
- char plugin_output[GM_BUFFERSIZE];
- strcpy(plugin_output,"");
gm_log( GM_LOG_TRACE, "do_exec_job()\n" );
if(exec_job->type == NULL) {
- gm_log( GM_LOG_ERROR, "discarded invalid job\n" );
+ gm_log( GM_LOG_ERROR, "discarded invalid job, no type given\n" );
return;
}
if(exec_job->command_line == NULL) {
- gm_log( GM_LOG_ERROR, "discarded invalid job\n" );
+ gm_log( GM_LOG_ERROR, "discarded invalid job, no command line given\n" );
return;
}
@@ -302,22 +327,7 @@
/* run the command */
gm_log( GM_LOG_TRACE, "command: %s\n", exec_job->command_line);
- execute_safe_command();
-
- /* record check result info */
- gettimeofday(&end_time, NULL);
- exec_job->finish_time = end_time;
-
- /* did we have a timeout? */
- if(exec_job->timeout < ((int)end_time.tv_sec - (int)start_time.tv_sec)) {
- exec_job->return_code = 2;
- exec_job->early_timeout = 1;
- if ( !strcmp( exec_job->type, "service" ) )
- snprintf( plugin_output, sizeof( plugin_output ), "(Service Check Timed Out On Worker: %s)", hostname);
- if ( !strcmp( exec_job->type, "host" ) )
- snprintf( plugin_output, sizeof( plugin_output ), "(Host Check Timed Out On Worker: %s)", hostname);
- exec_job->output = strdup( plugin_output );
- }
+ execute_safe_command(exec_job, mod_gm_opt->fork_on_exec, hostname);
if ( !strcmp( exec_job->type, "service" ) || !strcmp( exec_job->type, "host" ) ) {
send_result_back();
@@ -327,117 +337,6 @@
}
-/* execute this command with given timeout */
-void execute_safe_command() {
- int pdes[2];
- int return_code;
- int pclose_result;
- int fork_exec = mod_gm_opt->fork_on_exec;
- char *plugin_output;
- char buffer[GM_BUFFERSIZE];
- sigset_t mask;
-
- gm_log( GM_LOG_TRACE, "execute_safe_command()\n" );
-
- /* fork a child process */
- if(fork_exec == GM_ENABLED) {
- if(pipe(pdes) != 0)
- perror("pipe");
-
- current_child_pid=fork();
-
- /*fork error */
- if( current_child_pid == -1 ) {
- exec_job->output = strdup("(Error On Fork)");
- exec_job->return_code = 3;
- return;
- }
- }
-
- /* we are in the child process */
- if( fork_exec == GM_DISABLED || current_child_pid == 0 ){
-
- /* become the process group leader */
- setpgid(0,0);
- current_child_pid = getpid();
-
- /* remove all customn signal handler */
- sigfillset(&mask);
- sigprocmask(SIG_UNBLOCK, &mask, NULL);
-
- if( fork_exec == GM_ENABLED )
- close(pdes[0]);
- signal(SIGALRM, alarm_sighandler);
- alarm(exec_job->timeout);
-
- /* run the plugin check command */
- pclose_result = run_check(exec_job->command_line, &plugin_output);
- return_code = real_exit_code(pclose_result);
-
- if(fork_exec == GM_ENABLED) {
- if(write(pdes[1], plugin_output, strlen(plugin_output)+1) <= 0)
- perror("write");
-
- if(pclose_result == -1) {
- char error[GM_BUFFERSIZE];
- snprintf(error, sizeof(error), "error on %s: %s", hostname, strerror(errno));
- if(write(pdes[1], error, strlen(error)+1) <= 0)
- perror("write");
- }
-
- exit(return_code);
- }
- else {
- snprintf( buffer, sizeof( buffer )-1, "%s", plugin_output );
- }
- }
-
- /* we are the parent */
- if( fork_exec == GM_DISABLED || current_child_pid > 0 ){
-
- gm_log( GM_LOG_TRACE, "started check with pid: %d\n", current_child_pid);
-
- if( fork_exec == GM_ENABLED) {
- close(pdes[1]);
-
- waitpid(current_child_pid, &return_code, 0);
- return_code = real_exit_code(return_code);
- gm_log( GM_LOG_TRACE, "finished check from pid: %d with status: %d\n", current_child_pid, return_code);
- /* get all lines of plugin output */
- if(read(pdes[0], buffer, sizeof(buffer)-1) < 0)
- perror("read");
- }
-
- /* file not executable? */
- if(return_code == 126) {
- return_code = STATE_CRITICAL;
- snprintf( buffer, sizeof( buffer )-1, "CRITICAL: Return code of 126 is out of bounds. Make sure the plugin you're trying to run is executable. (worker: %s)", hostname);
- }
- /* file not found errors? */
- else if(return_code == 127) {
- return_code = STATE_CRITICAL;
- snprintf( buffer, sizeof( buffer )-1, "CRITICAL: Return code of 127 is out of bounds. Make sure the plugin you're trying to run actually exists. (worker: %s)", hostname);
- }
- /* signaled */
- else if(return_code >= 128 && return_code < 256) {
- char * signame = nr2signal((int)(return_code-128));
- snprintf( buffer, sizeof( buffer )-1, "CRITICAL: Return code of %d is out of bounds. Plugin exited by signal %s. (worker: %s)", (int)(return_code), signame, hostname);
- return_code = STATE_CRITICAL;
- free(signame);
- }
- exec_job->output = strdup(buffer);
- exec_job->return_code = return_code;
- if( fork_exec == GM_ENABLED) {
- close(pdes[0]);
- }
- }
- alarm(0);
- current_child_pid = 0;
-
- return;
-}
-
-
/* send results back */
void send_result_back() {
gm_log( GM_LOG_TRACE, "send_result_back()\n" );
@@ -507,6 +406,29 @@
gm_log( GM_LOG_TRACE, "send_result_back() finished unsuccessfully\n" );
}
+ if( mod_gm_opt->dupserver_num ) {
+ strncpy(temp_buffer2, "type=passive\n", (sizeof(temp_buffer1)-2));
+ strncat(temp_buffer2, temp_buffer1, (sizeof(temp_buffer2)-2));
+ temp_buffer2[sizeof( temp_buffer2 )-1]='\x0';
+ if( add_job_to_queue( &client_dup,
+ mod_gm_opt->dupserver_list,
+ exec_job->result_queue,
+ NULL,
+ temp_buffer2,
+ GM_JOB_PRIO_NORMAL,
+ GM_DEFAULT_JOB_RETRIES,
+ mod_gm_opt->transportmode
+ ) == GM_OK) {
+ gm_log( GM_LOG_TRACE, "send_result_back() finished successfully for duplicate server.\n" );
+ }
+ else {
+ gm_log( GM_LOG_TRACE, "send_result_back() finished unsuccessfully for duplicate server\n" );
+ }
+ }
+ else {
+ gm_log( GM_LOG_TRACE, "send_result_back() has no duplicate servers to send to.\n" );
+ }
+
return;
}
@@ -559,81 +481,75 @@
}
-/* called when check runs into timeout */
-void alarm_sighandler(int sig) {
- pid_t pid = getpid();
-
- gm_log( GM_LOG_TRACE, "alarm_sighandler(%i)\n", sig );
-
- signal(SIGINT, SIG_IGN);
- gm_log( GM_LOG_TRACE, "send SIGINT to %d\n", pid);
- kill(-pid, SIGINT);
- signal(SIGINT, SIG_DFL);
- sleep(1);
- gm_log( GM_LOG_TRACE, "send SIGKILL to %d\n", pid);
- kill(-pid, SIGKILL);
-
- if(worker_run_mode != GM_WORKER_STANDALONE)
- exit(EXIT_SUCCESS);
-
- return;
+/* called when worker runs into idle timeout */
+void idle_sighandler(int sig) {
+ gm_log( GM_LOG_TRACE, "idle_sighandler(%i)\n", sig );
+ clean_worker_exit(0);
+ exit( EXIT_SUCCESS );
}
+
/* tell parent our state */
-void send_state_to_parent(int status) {
- int shmid;
+void set_state(int status) {
int *shm;
- gm_log( GM_LOG_TRACE, "send_state_to_parent(%d)\n", status );
-
- /* Locate the segment */
- if ((shmid = shmget(mod_gm_shm_key, GM_SHM_SIZE, 0600)) < 0) {
- perror("shmget");
- gm_log( GM_LOG_TRACE, "worker finished: %d\n", getpid() );
- exit( EXIT_FAILURE );
- }
+ gm_log( GM_LOG_TRACE, "set_state(%d)\n", status );
/* Now we attach the segment to our data space. */
if ((shm = shmat(shmid, NULL, 0)) == (int *) -1) {
perror("shmat");
gm_log( GM_LOG_TRACE, "worker finished: %d\n", getpid() );
+ clean_worker_exit(0);
exit( EXIT_FAILURE );
}
- /* set our counter */
if(status == GM_JOB_START)
- shm[0]++;
+ shm[shm_index] = current_pid;
if(status == GM_JOB_END) {
- shm[0]--;
- shm[2]++; /* increase jobs done */
+ shm[0]++; /* increase jobs done */
+ /* pid in our status slot changed, this should not happen -> exit */
+ if( shm[shm_index] != current_pid && shm[shm_index] != -current_pid ) {
+ gm_log( GM_LOG_ERROR, "double used worker slot: %d != %d\n", current_pid, shm[shm_index] );
+ clean_worker_exit(0);
+ exit( EXIT_FAILURE );
+ }
+ shm[shm_index] = -current_pid;
}
/* detach from shared memory */
if(shmdt(shm) < 0)
perror("shmdt");
- if(worker_run_mode != GM_WORKER_MULTI)
- return;
-
- /* wake up parent */
- kill(getppid(), SIGUSR1);
-
return;
}
/* do a clean exit */
void clean_worker_exit(int sig) {
- int shmid;
+ int *shm;
gm_log( GM_LOG_TRACE, "clean_worker_exit(%d)\n", sig);
+ gm_log( GM_LOG_TRACE, "cleaning worker\n");
gearman_worker_unregister_all(&worker);
gearman_job_free_all( &worker );
+ gm_log( GM_LOG_TRACE, "cleaning client\n");
gearman_client_free( &client );
-
mod_gm_free_opt(mod_gm_opt);
+ /* Now we attach the segment to our data space. */
+ if ((shm = shmat(shmid, NULL, 0)) == (int *) -1) {
+ perror("shmat");
+ gm_log( GM_LOG_TRACE, "worker finished: %d\n", getpid() );
+ clean_worker_exit(0);
+ exit( EXIT_FAILURE );
+ }
+ shm[shm_index] = -1;
+
+ /* detach from shared memory */
+ if(shmdt(shm) < 0)
+ perror("shmdt");
+
if(worker_run_mode != GM_WORKER_STANDALONE)
exit( EXIT_SUCCESS );
@@ -641,9 +557,6 @@
* clean up shared memory
* will be removed when last client detaches
*/
- if ((shmid = shmget(mod_gm_shm_key, GM_SHM_SIZE, 0600)) < 0) {
- perror("shmget");
- }
if( shmctl( shmid, IPC_RMID, 0 ) == -1 ) {
perror("shmctl");
}
@@ -656,7 +569,6 @@
void *return_status( gearman_job_st *job, void *context, size_t *result_size, gearman_return_t *ret_ptr ) {
int wsize;
char workload[GM_BUFFERSIZE];
- int shmid;
int *shm;
char * result;
@@ -679,13 +591,6 @@
result = malloc(GM_BUFFERSIZE);
*result_size = GM_BUFFERSIZE;
- /* Locate the segment */
- if ((shmid = shmget(mod_gm_shm_key, GM_SHM_SIZE, 0600)) < 0) {
- perror("shmget");
- *result_size = 0;
- return NULL;
- }
-
/* Now we attach the segment to our data space. */
if ((shm = shmat(shmid, NULL, 0)) == (int *) -1) {
perror("shmat");
@@ -693,7 +598,7 @@
return NULL;
}
- snprintf(result, GM_BUFFERSIZE, "%s has %i worker and is working on %i jobs. Version: %s|worker=%i jobs=%ic", hostname, shm[1], shm[0], GM_VERSION, shm[1], shm[2] );
+ snprintf(result, GM_BUFFERSIZE, "%s has %i worker and is working on %i jobs. Version: %s|worker=%i jobs=%ic", hostname, shm[1], shm[2], GM_VERSION, shm[1], shm[0] );
/* detach from shared memory */
if(shmdt(shm) < 0)
@@ -703,43 +608,6 @@
}
-/* set empty default job */
-int set_default_job(gm_job_t *job) {
-
- job->type = NULL;
- job->host_name = NULL;
- job->service_description = NULL;
- job->result_queue = NULL;
- job->command_line = NULL;
- job->output = NULL;
- job->exited_ok = TRUE;
- job->scheduled_check = TRUE;
- job->reschedule_check = TRUE;
- job->return_code = STATE_OK;
- job->latency = 0.0;
- job->timeout = mod_gm_opt->job_timeout;
- job->start_time.tv_sec = 0L;
- job->start_time.tv_usec = 0L;
-
- return(GM_OK);
-}
-
-
-/* free the job structure */
-int free_job(gm_job_t *job) {
-
- free(job->type);
- free(job->host_name);
- free(job->service_description);
- free(job->result_queue);
- free(job->command_line);
- free(job->output);
- free(job);
-
- return(GM_OK);
-}
-
-
#ifdef GM_DEBUG
/* write text to a debug file */
void write_debug_file(char ** text) {
|
[-]
[+]
|
Added |
mod_gearman-worker-suse.init
^
|
@@ -0,0 +1,203 @@
+#!/bin/sh
+#
+# Copyright (C) 2011 Carsten Schoene, Linux Administrator Networks
+#
+# This library is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or (at
+# your option) any later version.
+#
+# This library is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+# USA.
+#
+# /etc/init.d/mod_gearman_worker
+# and its symbolic link
+# /(usr/)sbin/rcmod_gearman_worker
+#
+#
+### BEGIN INIT INFO
+# Provides: mod_gearman_worker
+# Required-Start: $syslog $remote_fs
+# Should-Start: $time
+# Required-Stop: $syslog $remote_fs
+# Should-Stop: $null
+# Default-Start: 3 5
+# Default-Stop: 0 1 2 6
+# Short-Description: mod_gearman_worker daemon
+# Description: Start mod_gearman_worker
+### END INIT INFO
+#
+
+# Check for missing binaries (stale symlinks should not happen)
+# Note: Special treatment of stop for LSB conformance
+mod_gearman_worker_BIN=/usr/bin/mod_gearman_worker
+MOD_GM_PIDFILE=/var/run/mod_gearman/mod_gearman_worker.pid
+MOD_GM_CONFIG=/etc/mod_gearman_worker.conf
+test -x $mod_gearman_worker_BIN || { echo "$mod_gearman_worker_BIN not installed";
+ if [ "$1" = "stop" ]; then exit 0;
+ else exit 5; fi; }
+
+# Check for existence of needed config file and read it
+mod_gearman_worker_MOD_GM_CONFIG=/etc/sysconfig/mod_gearman_worker
+test -r $mod_gearman_worker_MOD_GM_CONFIG || { echo "$mod_gearman_worker_MOD_GM_CONFIG not existing";
+ if [ "$1" = "stop" ]; then exit 0;
+ else exit 6; fi; }
+
+# Read config
+. $mod_gearman_worker_MOD_GM_CONFIG
+
+# Source LSB init functions
+# providing start_daemon, killproc, pidofproc,
+# log_success_msg, log_failure_msg and log_warning_msg.
+# This is currently not used by UnitedLinux based distributions and
+# not needed for init scripts for UnitedLinux only. If it is used,
+# the functions from rc.status should not be sourced or used.
+#. /lib/lsb/init-functions
+
+# Shell functions sourced from /etc/rc.status:
+# rc_check check and set local and overall rc status
+# rc_status check and set local and overall rc status
+# rc_status -v be verbose in local rc status and clear it afterwards
+# rc_status -v -r ditto and clear both the local and overall rc status
+# rc_status -s display "skipped" and exit with status 3
+# rc_status -u display "unused" and exit with status 3
+# rc_failed set local and overall rc status to failed
+# rc_failed <num> set local and overall rc status to <num>
+# rc_reset clear both the local and overall rc status
+# rc_exit exit appropriate to overall rc status
+# rc_active checks whether a service is activated by symlinks
+. /etc/rc.status
+
+# Reset status of this service
+rc_reset
+
+# Return values acc. to LSB for all commands but status:
+# 0 - success
+# 1 - generic or unspecified error
+# 2 - invalid or excess argument(s)
+# 3 - unimplemented feature (e.g. "reload")
+# 4 - user had insufficient privileges
+# 5 - program is not installed
+# 6 - program is not configured
+# 7 - program is not running
+# 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl)
+#
+# Note that starting an already running service, stopping
+# or restarting a not-running service as well as the restart
+# with force-reload (in case signaling is not supported) are
+# considered a success.
+
+case "$1" in
+ start)
+ echo -n "Starting mod_gearman_worker "
+ ## Start daemon with startproc(8). If this fails
+ ## the return value is set appropriately by startproc.
+ /sbin/startproc -u ${MOD_GM_USERID} $mod_gearman_worker_BIN -d --config=${MOD_GM_CONFIG} --pidfile=${MOD_GM_PIDFILE}
+
+ # Remember status and be verbose
+ rc_status -v
+ ;;
+ stop)
+ echo -n "Shutting down mod_gearman_worker "
+ ## Stop daemon with killproc(8) and if this fails
+ ## killproc sets the return value according to LSB.
+
+ /sbin/killproc -TERM $mod_gearman_worker_BIN -p ${MOD_GM_PIDFILE}
+
+ # Remember status and be verbose
+ rc_status -v
+ ;;
+ try-restart|condrestart)
+ ## Do a restart only if the service was active before.
+ ## Note: try-restart is now part of LSB (as of 1.9).
+ ## RH has a similar command named condrestart.
+ if test "$1" = "condrestart"; then
+ echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}"
+ fi
+ $0 status
+ if test $? = 0; then
+ $0 restart
+ else
+ rc_reset # Not running is not a failure.
+ fi
+ # Remember status and be quiet
+ rc_status
+ ;;
+ restart)
+ ## Stop the service and regardless of whether it was
+ ## running or not, start it again.
+ $0 stop
+ $0 start
+
+ # Remember status and be quiet
+ rc_status
+ ;;
+ force-reload)
+ ## Signal the daemon to reload its config. Most daemons
+ ## do this on signal 1 (SIGHUP).
+ ## If it does not support it, restart the service if it
+ ## is running.
+
+ echo -n "Reload service mod_gearman_worker "
+ ## if it supports it:
+ /sbin/killproc -HUP $mod_gearman_worker_BIN
+ #touch /var/run/mod_gearman_worker.pid
+ rc_status -v
+
+ ## Otherwise:
+ #$0 try-restart
+ #rc_status
+ ;;
+ reload)
+ ## Like force-reload, but if daemon does not support
+ ## signaling, do nothing (!)
+
+ # If it supports signaling:
+ echo -n "Reload service mod_gearman_worker "
+ /sbin/killproc -HUP $mod_gearman_worker_BIN
+ #touch /var/run/mod_gearman_worker.pid
+ rc_status -v
+
+ ## Otherwise if it does not support reload:
+ #rc_failed 3
+ #rc_status -v
+ ;;
+ status)
+ echo -n "Checking for service mod_gearman_worker "
+ ## Check status with checkproc(8), if process is running
+ ## checkproc will return with exit status 0.
+
+ # Return value is slightly different for the status command:
+ # 0 - service up and running
+ # 1 - service dead, but /var/run/ pid file exists
+ # 2 - service dead, but /var/lock/ lock file exists
+ # 3 - service not running (unused)
+ # 4 - service status unknown :-(
+ # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.)
+
+ # NOTE: checkproc returns LSB compliant status values.
+ /sbin/checkproc $mod_gearman_worker_BIN
+ # NOTE: rc_status knows that we called this init script with
+ # "status" option and adapts its messages accordingly.
+ rc_status -v
+ ;;
+ probe)
+ ## Optional: Probe for the necessity of a reload, print out the
+ ## argument to this init script which is required for a reload.
+ ## Note: probe is not (yet) part of LSB (as of 1.9)
+
+ test /etc/mod_gearman_worker.conf -nt ${MOD_GM_PIDFILE} && echo reload
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
|
[-]
[+]
|
Added |
mod_gearman_worker.sysconfig
^
|
@@ -0,0 +1,20 @@
+## Type: string
+## Default: "/etc/mod_gearman_worker.conf"
+#
+# This define configuration file for mod_gearman_worker
+#
+MOD_GM_CONFIG=/etc/mod_gearman_worker.conf
+
+## Type: string
+## Default: "/var/run/mod_gearman/mod_gearman_worker.pid"
+#
+# mod_gearman_worker PID file location, must be writeable by worker user
+#
+MOD_GM_PIDFILE=/var/run/mod_gearman/mod_gearman_worker.pid
+
+## Type: string
+## Default: %USERID%
+#
+# mod_gearman_worker user
+#
+MOD_GM_USERID=%USERID%
|