diff options
-rw-r--r-- | doc/README | 3 | ||||
-rw-r--r-- | doc/developer-guidelines.html | 931 | ||||
-rw-r--r-- | doc/developer-guidelines.sgml | 483 |
3 files changed, 1417 insertions, 0 deletions
diff --git a/doc/README b/doc/README new file mode 100644 index 00000000..388bc1d7 --- /dev/null +++ b/doc/README | |||
@@ -0,0 +1,3 @@ | |||
1 | The developer documentation here is generated from the DocBook format. | ||
2 | |||
3 | |||
diff --git a/doc/developer-guidelines.html b/doc/developer-guidelines.html new file mode 100644 index 00000000..efac605f --- /dev/null +++ b/doc/developer-guidelines.html | |||
@@ -0,0 +1,931 @@ | |||
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> | ||
2 | <HTML | ||
3 | ><HEAD | ||
4 | ><TITLE | ||
5 | >Nagios plug-in development guidelines</TITLE | ||
6 | ><META | ||
7 | NAME="GENERATOR" | ||
8 | CONTENT="Modular DocBook HTML Stylesheet Version 1.64 | ||
9 | "></HEAD | ||
10 | ><BODY | ||
11 | CLASS="BOOK" | ||
12 | BGCOLOR="#FFFFFF" | ||
13 | TEXT="#000000" | ||
14 | LINK="#0000FF" | ||
15 | VLINK="#840084" | ||
16 | ALINK="#0000FF" | ||
17 | ><DIV | ||
18 | CLASS="BOOK" | ||
19 | ><A | ||
20 | NAME="AEN1" | ||
21 | ></A | ||
22 | ><DIV | ||
23 | CLASS="TITLEPAGE" | ||
24 | ><H1 | ||
25 | CLASS="TITLE" | ||
26 | ><A | ||
27 | NAME="AEN3" | ||
28 | >Nagios plug-in development guidelines</A | ||
29 | ></H1 | ||
30 | ><H3 | ||
31 | CLASS="AUTHOR" | ||
32 | ><A | ||
33 | NAME="AEN5" | ||
34 | >Karl DeBisschop</A | ||
35 | ></H3 | ||
36 | ><DIV | ||
37 | CLASS="AFFILIATION" | ||
38 | ><DIV | ||
39 | CLASS="ADDRESS" | ||
40 | ><P | ||
41 | CLASS="ADDRESS" | ||
42 | >karl@debisschop.net</P | ||
43 | ></DIV | ||
44 | ></DIV | ||
45 | ><H3 | ||
46 | CLASS="AUTHOR" | ||
47 | ><A | ||
48 | NAME="AEN11" | ||
49 | >Ethan Galstad</A | ||
50 | ></H3 | ||
51 | ><DIV | ||
52 | CLASS="AFFILIATION" | ||
53 | ><DIV | ||
54 | CLASS="ADDRESS" | ||
55 | ><P | ||
56 | CLASS="ADDRESS" | ||
57 | >netsaint@linuxbox.com</P | ||
58 | ></DIV | ||
59 | ></DIV | ||
60 | ><H3 | ||
61 | CLASS="AUTHOR" | ||
62 | ><A | ||
63 | NAME="AEN21" | ||
64 | >Hugo Gayosso</A | ||
65 | ></H3 | ||
66 | ><DIV | ||
67 | CLASS="AFFILIATION" | ||
68 | ><DIV | ||
69 | CLASS="ADDRESS" | ||
70 | ><P | ||
71 | CLASS="ADDRESS" | ||
72 | >hgayosso@gnu.org</P | ||
73 | ></DIV | ||
74 | ></DIV | ||
75 | ><H3 | ||
76 | CLASS="AUTHOR" | ||
77 | ><A | ||
78 | NAME="AEN27" | ||
79 | >Subhendu Ghosh</A | ||
80 | ></H3 | ||
81 | ><DIV | ||
82 | CLASS="AFFILIATION" | ||
83 | ><DIV | ||
84 | CLASS="ADDRESS" | ||
85 | ><P | ||
86 | CLASS="ADDRESS" | ||
87 | >sghosh@sourceforge.net</P | ||
88 | ></DIV | ||
89 | ></DIV | ||
90 | ><H3 | ||
91 | CLASS="AUTHOR" | ||
92 | ><A | ||
93 | NAME="AEN33" | ||
94 | >Stanley Hopcroft</A | ||
95 | ></H3 | ||
96 | ><DIV | ||
97 | CLASS="AFFILIATION" | ||
98 | ><DIV | ||
99 | CLASS="ADDRESS" | ||
100 | ><P | ||
101 | CLASS="ADDRESS" | ||
102 | >stanleyhopcroft@sourceforge.net</P | ||
103 | ></DIV | ||
104 | ></DIV | ||
105 | ><P | ||
106 | CLASS="COPYRIGHT" | ||
107 | >Copyright © 2000 2001 2002 by Karl DeBisschop, Ethan Galstad, | ||
108 | Hugo Gayosso, Stanley Hopcroft, Subhendu Ghosh</P | ||
109 | ><HR></DIV | ||
110 | ><DIV | ||
111 | CLASS="TOC" | ||
112 | ><DL | ||
113 | ><DT | ||
114 | ><B | ||
115 | >Table of Contents</B | ||
116 | ></DT | ||
117 | ><DT | ||
118 | ><A | ||
119 | HREF="#PREFACE" | ||
120 | >About the guidelines</A | ||
121 | ></DT | ||
122 | ><DD | ||
123 | ><DL | ||
124 | ><DT | ||
125 | ><A | ||
126 | HREF="#AEN51" | ||
127 | >Copyright</A | ||
128 | ></DT | ||
129 | ></DL | ||
130 | ></DD | ||
131 | ><DT | ||
132 | ><A | ||
133 | HREF="#AEN56" | ||
134 | ></A | ||
135 | ></DT | ||
136 | ><DD | ||
137 | ><DL | ||
138 | ><DT | ||
139 | ><A | ||
140 | HREF="#PLUGOUTPUT" | ||
141 | >Plugin Output for Nagios</A | ||
142 | ></DT | ||
143 | ><DD | ||
144 | ><DL | ||
145 | ><DT | ||
146 | ><A | ||
147 | HREF="#AEN60" | ||
148 | >Print only one line of text</A | ||
149 | ></DT | ||
150 | ><DT | ||
151 | ><A | ||
152 | HREF="#AEN63" | ||
153 | >Screen Output</A | ||
154 | ></DT | ||
155 | ><DT | ||
156 | ><A | ||
157 | HREF="#AEN67" | ||
158 | >Return the proper status code</A | ||
159 | ></DT | ||
160 | ><DT | ||
161 | ><A | ||
162 | HREF="#AEN71" | ||
163 | >Plugin Return Codes</A | ||
164 | ></DT | ||
165 | ></DL | ||
166 | ></DD | ||
167 | ><DT | ||
168 | ><A | ||
169 | HREF="#SYSCMDAUXFILES" | ||
170 | >System Commands and Auxiliary Files</A | ||
171 | ></DT | ||
172 | ><DD | ||
173 | ><DL | ||
174 | ><DT | ||
175 | ><A | ||
176 | HREF="#AEN117" | ||
177 | >Don't execute system commands without specifying their | ||
178 | full path</A | ||
179 | ></DT | ||
180 | ><DT | ||
181 | ><A | ||
182 | HREF="#AEN121" | ||
183 | >Use spopen() if external commands must be executed</A | ||
184 | ></DT | ||
185 | ><DT | ||
186 | ><A | ||
187 | HREF="#AEN125" | ||
188 | >Don't make temp files unless absolutely required</A | ||
189 | ></DT | ||
190 | ><DT | ||
191 | ><A | ||
192 | HREF="#AEN128" | ||
193 | >Don't be tricked into following symlinks</A | ||
194 | ></DT | ||
195 | ><DT | ||
196 | ><A | ||
197 | HREF="#AEN131" | ||
198 | >Validate all input</A | ||
199 | ></DT | ||
200 | ></DL | ||
201 | ></DD | ||
202 | ><DT | ||
203 | ><A | ||
204 | HREF="#PERLPLUGIN" | ||
205 | >Perl Plugins</A | ||
206 | ></DT | ||
207 | ><DT | ||
208 | ><A | ||
209 | HREF="#RUNTIME" | ||
210 | >Runtime Timeouts</A | ||
211 | ></DT | ||
212 | ><DD | ||
213 | ><DL | ||
214 | ><DT | ||
215 | ><A | ||
216 | HREF="#AEN165" | ||
217 | >Use DEFAULT_SOCKET_TIMEOUT</A | ||
218 | ></DT | ||
219 | ><DT | ||
220 | ><A | ||
221 | HREF="#AEN168" | ||
222 | >Add alarms to network plugins</A | ||
223 | ></DT | ||
224 | ></DL | ||
225 | ></DD | ||
226 | ><DT | ||
227 | ><A | ||
228 | HREF="#PLUGOPTIONS" | ||
229 | >Plugin Options</A | ||
230 | ></DT | ||
231 | ><DD | ||
232 | ><DL | ||
233 | ><DT | ||
234 | ><A | ||
235 | HREF="#AEN174" | ||
236 | >Option Processing</A | ||
237 | ></DT | ||
238 | ><DT | ||
239 | ><A | ||
240 | HREF="#AEN187" | ||
241 | >Plugins with more than one type of threshold, or with | ||
242 | threshold ranges</A | ||
243 | ></DT | ||
244 | ></DL | ||
245 | ></DD | ||
246 | ><DT | ||
247 | ><A | ||
248 | HREF="#SUBMITTINGCHANGES" | ||
249 | >New submissions and patches</A | ||
250 | ></DT | ||
251 | ></DL | ||
252 | ></DD | ||
253 | ></DL | ||
254 | ></DIV | ||
255 | ><DIV | ||
256 | CLASS="PREFACE" | ||
257 | ><HR><H1 | ||
258 | ><A | ||
259 | NAME="PREFACE" | ||
260 | >About the guidelines</A | ||
261 | ></H1 | ||
262 | ><P | ||
263 | >The purpose of this guidelines is to provide a reference for | ||
264 | the plug-in developers and encourage the standarization of the | ||
265 | different kind of plug-ins: C, shell, perl, python, etc.</P | ||
266 | ><DIV | ||
267 | CLASS="SECTION" | ||
268 | ><HR><H1 | ||
269 | CLASS="SECTION" | ||
270 | ><A | ||
271 | NAME="AEN51" | ||
272 | >Copyright</A | ||
273 | ></H1 | ||
274 | ><P | ||
275 | >Nagios Plug-in Development Guidelines Copyright (C) 2000 2001 | ||
276 | 2002 | ||
277 | Karl DeBisschop, Ethan Galstad, Hugo Gayosso, Stanley Hopcroft, | ||
278 | Subhendu Ghosh</P | ||
279 | ><P | ||
280 | >Permission is granted to make and distribute verbatim | ||
281 | copies of this manual provided the copyright notice and this | ||
282 | permission notice are preserved on all copies.</P | ||
283 | ><P | ||
284 | >The plugins themselves are copyrighted by their respective | ||
285 | authors.</P | ||
286 | ></DIV | ||
287 | ></DIV | ||
288 | ><DIV | ||
289 | CLASS="ARTICLE" | ||
290 | ><DIV | ||
291 | CLASS="TOC" | ||
292 | ><DL | ||
293 | ><DT | ||
294 | ><B | ||
295 | >Table of Contents</B | ||
296 | ></DT | ||
297 | ><DT | ||
298 | ><A | ||
299 | HREF="#PLUGOUTPUT" | ||
300 | >Plugin Output for Nagios</A | ||
301 | ></DT | ||
302 | ><DT | ||
303 | ><A | ||
304 | HREF="#SYSCMDAUXFILES" | ||
305 | >System Commands and Auxiliary Files</A | ||
306 | ></DT | ||
307 | ><DT | ||
308 | ><A | ||
309 | HREF="#PERLPLUGIN" | ||
310 | >Perl Plugins</A | ||
311 | ></DT | ||
312 | ><DT | ||
313 | ><A | ||
314 | HREF="#RUNTIME" | ||
315 | >Runtime Timeouts</A | ||
316 | ></DT | ||
317 | ><DT | ||
318 | ><A | ||
319 | HREF="#PLUGOPTIONS" | ||
320 | >Plugin Options</A | ||
321 | ></DT | ||
322 | ><DT | ||
323 | ><A | ||
324 | HREF="#SUBMITTINGCHANGES" | ||
325 | >New submissions and patches</A | ||
326 | ></DT | ||
327 | ></DL | ||
328 | ></DIV | ||
329 | ><DIV | ||
330 | CLASS="SECTION" | ||
331 | ><H1 | ||
332 | CLASS="SECTION" | ||
333 | ><A | ||
334 | NAME="PLUGOUTPUT" | ||
335 | >Plugin Output for Nagios</A | ||
336 | ></H1 | ||
337 | ><P | ||
338 | >You should always print something to STDOUT that tells if the | ||
339 | service is working or why its failing. Try to keep the output short - | ||
340 | probably less that 80 characters. Remember that you ideally would like | ||
341 | the entire output to appear in a pager message, which will get chopped | ||
342 | off after a certain length.</P | ||
343 | ><DIV | ||
344 | CLASS="SECTION" | ||
345 | ><HR><H2 | ||
346 | CLASS="SECTION" | ||
347 | ><A | ||
348 | NAME="AEN60" | ||
349 | >Print only one line of text</A | ||
350 | ></H2 | ||
351 | ><P | ||
352 | >Nagios will only grab the first line of text from STDOUT | ||
353 | when it notifies contacts about potential problems. If you print | ||
354 | multiple lines, you're out of luck. Remember, keep it short and | ||
355 | to the point.</P | ||
356 | ></DIV | ||
357 | ><DIV | ||
358 | CLASS="SECTION" | ||
359 | ><HR><H2 | ||
360 | CLASS="SECTION" | ||
361 | ><A | ||
362 | NAME="AEN63" | ||
363 | >Screen Output</A | ||
364 | ></H2 | ||
365 | ><P | ||
366 | >The plug-in should print the diagnostic and just the | ||
367 | synopsis part of the help message. A well written plugin would | ||
368 | then have --help as a way to get the verbose help.</P | ||
369 | ><P | ||
370 | >Code and output should try to respect the 80x25 size of a | ||
371 | crt (remember when fixing stuff in the server room!)</P | ||
372 | ></DIV | ||
373 | ><DIV | ||
374 | CLASS="SECTION" | ||
375 | ><HR><H2 | ||
376 | CLASS="SECTION" | ||
377 | ><A | ||
378 | NAME="AEN67" | ||
379 | >Return the proper status code</A | ||
380 | ></H2 | ||
381 | ><P | ||
382 | >See <A | ||
383 | HREF="#RETURNCODES" | ||
384 | >Table 1 in the section called <I | ||
385 | >Plugin Return Codes</I | ||
386 | ></A | ||
387 | > below | ||
388 | for the numeric values of status codes and their | ||
389 | description. Remember to return an UNKNOWN state if bogus or | ||
390 | invalid command line arguments are supplied or it you are unable | ||
391 | to check the service.</P | ||
392 | ></DIV | ||
393 | ><DIV | ||
394 | CLASS="SECTION" | ||
395 | ><HR><H2 | ||
396 | CLASS="SECTION" | ||
397 | ><A | ||
398 | NAME="AEN71" | ||
399 | >Plugin Return Codes</A | ||
400 | ></H2 | ||
401 | ><P | ||
402 | >The return codes below are based on the POSIX spec of returning | ||
403 | a positive value. Netsaint prior to v0.0.7 supported non-POSIX | ||
404 | compliant return code of "-1" for unknown. Nagios supports POSIX return | ||
405 | codes by default.</P | ||
406 | ><P | ||
407 | >Note: Some plugins will on occasion print on STDOUT that an error | ||
408 | occurred and error code is 138 or 255 or some such number. These | ||
409 | are usually caused by plugins using system commands and having not | ||
410 | enough checks to catch unexpected output. Developers should include a | ||
411 | default catch-all for system command output that returns an UNKOWN | ||
412 | return code.</P | ||
413 | ><DIV | ||
414 | CLASS="TABLE" | ||
415 | ><A | ||
416 | NAME="RETURNCODES" | ||
417 | ></A | ||
418 | ><P | ||
419 | ><B | ||
420 | >Table 1. Plugin Return Codes</B | ||
421 | ></P | ||
422 | ><TABLE | ||
423 | BORDER="1" | ||
424 | BGCOLOR="#E0E0E0" | ||
425 | CELLSPACING="0" | ||
426 | CELLPADDING="4" | ||
427 | CLASS="CALSTABLE" | ||
428 | ><THEAD | ||
429 | ><TR | ||
430 | ><TH | ||
431 | ALIGN="LEFT" | ||
432 | VALIGN="TOP" | ||
433 | ><P | ||
434 | >Numeric Value</P | ||
435 | ></TH | ||
436 | ><TH | ||
437 | ALIGN="LEFT" | ||
438 | VALIGN="TOP" | ||
439 | ><P | ||
440 | >Service Status</P | ||
441 | ></TH | ||
442 | ><TH | ||
443 | ALIGN="LEFT" | ||
444 | VALIGN="TOP" | ||
445 | ><P | ||
446 | >Status Description</P | ||
447 | ></TH | ||
448 | ></TR | ||
449 | ></THEAD | ||
450 | ><TBODY | ||
451 | ><TR | ||
452 | ><TD | ||
453 | ALIGN="CENTER" | ||
454 | VALIGN="TOP" | ||
455 | ><P | ||
456 | >0</P | ||
457 | ></TD | ||
458 | ><TD | ||
459 | ALIGN="LEFT" | ||
460 | VALIGN="MIDDLE" | ||
461 | ><P | ||
462 | >OK</P | ||
463 | ></TD | ||
464 | ><TD | ||
465 | ALIGN="LEFT" | ||
466 | VALIGN="TOP" | ||
467 | ><P | ||
468 | >The plugin was able to check the service and it | ||
469 | appeared to be functioning properly</P | ||
470 | ></TD | ||
471 | ></TR | ||
472 | ><TR | ||
473 | ><TD | ||
474 | ALIGN="CENTER" | ||
475 | VALIGN="TOP" | ||
476 | ><P | ||
477 | >1</P | ||
478 | ></TD | ||
479 | ><TD | ||
480 | ALIGN="LEFT" | ||
481 | VALIGN="MIDDLE" | ||
482 | ><P | ||
483 | >Warning</P | ||
484 | ></TD | ||
485 | ><TD | ||
486 | ALIGN="LEFT" | ||
487 | VALIGN="TOP" | ||
488 | ><P | ||
489 | >The plugin was able to check the service, but it | ||
490 | appeared to be above some "warning" threshold or did not appear | ||
491 | to be working properly</P | ||
492 | ></TD | ||
493 | ></TR | ||
494 | ><TR | ||
495 | ><TD | ||
496 | ALIGN="CENTER" | ||
497 | VALIGN="TOP" | ||
498 | ><P | ||
499 | >2</P | ||
500 | ></TD | ||
501 | ><TD | ||
502 | ALIGN="LEFT" | ||
503 | VALIGN="MIDDLE" | ||
504 | ><P | ||
505 | >Critical</P | ||
506 | ></TD | ||
507 | ><TD | ||
508 | ALIGN="LEFT" | ||
509 | VALIGN="TOP" | ||
510 | ><P | ||
511 | >The plugin detected that either the service was not | ||
512 | running or it was above some "critical" threshold</P | ||
513 | ></TD | ||
514 | ></TR | ||
515 | ><TR | ||
516 | ><TD | ||
517 | ALIGN="CENTER" | ||
518 | VALIGN="TOP" | ||
519 | ><P | ||
520 | >3</P | ||
521 | ></TD | ||
522 | ><TD | ||
523 | ALIGN="LEFT" | ||
524 | VALIGN="MIDDLE" | ||
525 | ><P | ||
526 | >Unknown</P | ||
527 | ></TD | ||
528 | ><TD | ||
529 | ALIGN="LEFT" | ||
530 | VALIGN="TOP" | ||
531 | ><P | ||
532 | >Invalid command line arguments were supplied to the | ||
533 | plugin or the plugin was unable to check the status of the given | ||
534 | hosts/service</P | ||
535 | ></TD | ||
536 | ></TR | ||
537 | ></TBODY | ||
538 | ></TABLE | ||
539 | ></DIV | ||
540 | ></DIV | ||
541 | ></DIV | ||
542 | ><DIV | ||
543 | CLASS="SECTION" | ||
544 | ><HR><H1 | ||
545 | CLASS="SECTION" | ||
546 | ><A | ||
547 | NAME="SYSCMDAUXFILES" | ||
548 | >System Commands and Auxiliary Files</A | ||
549 | ></H1 | ||
550 | ><DIV | ||
551 | CLASS="SECTION" | ||
552 | ><H2 | ||
553 | CLASS="SECTION" | ||
554 | ><A | ||
555 | NAME="AEN117" | ||
556 | >Don't execute system commands without specifying their | ||
557 | full path</A | ||
558 | ></H2 | ||
559 | ><P | ||
560 | >Don't use exec(), popen(), etc. to execute external | ||
561 | commands without explicity using the full path of the external | ||
562 | program.</P | ||
563 | ><P | ||
564 | >Doing otherwise makes the plugin vulnerable to hijacking | ||
565 | by a trojan horse earlier in the search path. See the main | ||
566 | plugin distribution for examples on how this is done.</P | ||
567 | ></DIV | ||
568 | ><DIV | ||
569 | CLASS="SECTION" | ||
570 | ><HR><H2 | ||
571 | CLASS="SECTION" | ||
572 | ><A | ||
573 | NAME="AEN121" | ||
574 | >Use spopen() if external commands must be executed</A | ||
575 | ></H2 | ||
576 | ><P | ||
577 | >If you have to execute external commands from within your | ||
578 | plugin and you're writing it in C, use the spopen() function | ||
579 | that Karl DeBisschop has written.</P | ||
580 | ><P | ||
581 | >The code for spopen() and spclose() is included with the | ||
582 | core plugin distribution.</P | ||
583 | ></DIV | ||
584 | ><DIV | ||
585 | CLASS="SECTION" | ||
586 | ><HR><H2 | ||
587 | CLASS="SECTION" | ||
588 | ><A | ||
589 | NAME="AEN125" | ||
590 | >Don't make temp files unless absolutely required</A | ||
591 | ></H2 | ||
592 | ><P | ||
593 | >If temp files are needed, make sure that the plugin will | ||
594 | fail cleanly if the file can't be written (e.g., too few file | ||
595 | handles, out of disk space, incorrect permissions, etc.) and | ||
596 | delete the temp file when processing is complete.</P | ||
597 | ></DIV | ||
598 | ><DIV | ||
599 | CLASS="SECTION" | ||
600 | ><HR><H2 | ||
601 | CLASS="SECTION" | ||
602 | ><A | ||
603 | NAME="AEN128" | ||
604 | >Don't be tricked into following symlinks</A | ||
605 | ></H2 | ||
606 | ><P | ||
607 | >If your plugin opens any files, take steps to ensure that | ||
608 | you are not following a symlink to another location on the | ||
609 | system.</P | ||
610 | ></DIV | ||
611 | ><DIV | ||
612 | CLASS="SECTION" | ||
613 | ><HR><H2 | ||
614 | CLASS="SECTION" | ||
615 | ><A | ||
616 | NAME="AEN131" | ||
617 | >Validate all input</A | ||
618 | ></H2 | ||
619 | ><P | ||
620 | >use routines in utils.c or utils.pm and write more as needed</P | ||
621 | ></DIV | ||
622 | ></DIV | ||
623 | ><DIV | ||
624 | CLASS="SECTION" | ||
625 | ><HR><H1 | ||
626 | CLASS="SECTION" | ||
627 | ><A | ||
628 | NAME="PERLPLUGIN" | ||
629 | >Perl Plugins</A | ||
630 | ></H1 | ||
631 | ><P | ||
632 | >Perl plugins are coded a little more defensively than other | ||
633 | plugins because of embedded Perl. When configured as such, embedded | ||
634 | Perl Nagios (ePN) requires stricter use of the some of Perl's features. | ||
635 | This section outlines some of the steps needed to use ePN | ||
636 | effectively.</P | ||
637 | ><P | ||
638 | ></P | ||
639 | ><OL | ||
640 | TYPE="1" | ||
641 | ><LI | ||
642 | ><P | ||
643 | > Do not use BEGIN and END blocks since they will be called | ||
644 | the first time and when Nagios shuts down with Embedded Perl (ePN). In | ||
645 | particular, do not use BEGIN blocks to initialize variables.</P | ||
646 | ></LI | ||
647 | ><LI | ||
648 | ><P | ||
649 | >To use utils.pm, you need to provide a full path to the | ||
650 | module in order for it to work with ePN.</P | ||
651 | ><P | ||
652 | CLASS="LITERALLAYOUT" | ||
653 | > e.g.<br> | ||
654 | use lib "/usr/local/nagios/libexec";<br> | ||
655 | use utils qw(...);<br> | ||
656 | </P | ||
657 | ></LI | ||
658 | ><LI | ||
659 | ><P | ||
660 | >Perl scripts should be called with "-w"</P | ||
661 | ></LI | ||
662 | ><LI | ||
663 | ><P | ||
664 | >All Perl plugins must compile cleanly under "use strict" - i.e. at | ||
665 | least explicitly package names as in "$main::x" or predeclare every | ||
666 | variable. </P | ||
667 | ><P | ||
668 | >Explicitly initialize each varialable in use. Otherwise with | ||
669 | caching enabled, the plugin will not be recompilied each time, and | ||
670 | therefore Perl will not reinitialize all the variables. All old | ||
671 | variable values will still be in effect.</P | ||
672 | ></LI | ||
673 | ><LI | ||
674 | ><P | ||
675 | >Do not use < DATA > (these simply do not compile under ePN).</P | ||
676 | ></LI | ||
677 | ><LI | ||
678 | ><P | ||
679 | >Do not use named subroutines</P | ||
680 | ></LI | ||
681 | ><LI | ||
682 | ><P | ||
683 | >If writing to a file (perhaps recording | ||
684 | performance data) explicitly close close it. The plugin never | ||
685 | calls <I | ||
686 | CLASS="EMPHASIS" | ||
687 | >exit</I | ||
688 | >; that is caught by | ||
689 | p1.pl, so output streams are never closed.</P | ||
690 | ></LI | ||
691 | ><LI | ||
692 | ><P | ||
693 | >As in <A | ||
694 | HREF="#RUNTIME" | ||
695 | >the section called <I | ||
696 | >Runtime Timeouts</I | ||
697 | ></A | ||
698 | > all plugins need | ||
699 | to monitor their runtime, specially if they are using network | ||
700 | resources. Use of the <I | ||
701 | CLASS="EMPHASIS" | ||
702 | >alarm</I | ||
703 | > is recommended. | ||
704 | Plugins may import a default time out ($TIMEOUT) from utils.pm. | ||
705 | </P | ||
706 | ></LI | ||
707 | ><LI | ||
708 | ><P | ||
709 | >Perl plugins should import %ERRORS from utils.pm | ||
710 | and then "exit $ERRORS{'OK'}" rather than "exit 0" | ||
711 | </P | ||
712 | ></LI | ||
713 | ></OL | ||
714 | ></DIV | ||
715 | ><DIV | ||
716 | CLASS="SECTION" | ||
717 | ><HR><H1 | ||
718 | CLASS="SECTION" | ||
719 | ><A | ||
720 | NAME="RUNTIME" | ||
721 | >Runtime Timeouts</A | ||
722 | ></H1 | ||
723 | ><P | ||
724 | >Plugins have a very limited runtime - typically 10 sec. | ||
725 | As a result, it is very important for plugins to maintain internal | ||
726 | code to exit if runtime exceeds a threshold. </P | ||
727 | ><P | ||
728 | >All plugins should timeout gracefully, not just networking | ||
729 | plugins. For instance, df may lock if you have automounted | ||
730 | drives and your network fails - but on first glance, who'd think | ||
731 | df could lock up like that. Plus, it should just be more error | ||
732 | resistant to be able to time out rather than consume | ||
733 | resources.</P | ||
734 | ><DIV | ||
735 | CLASS="SECTION" | ||
736 | ><HR><H2 | ||
737 | CLASS="SECTION" | ||
738 | ><A | ||
739 | NAME="AEN165" | ||
740 | >Use DEFAULT_SOCKET_TIMEOUT</A | ||
741 | ></H2 | ||
742 | ><P | ||
743 | >All network plugins should use DEFAULT_SOCKET_TIMEOUT to timeout</P | ||
744 | ></DIV | ||
745 | ><DIV | ||
746 | CLASS="SECTION" | ||
747 | ><HR><H2 | ||
748 | CLASS="SECTION" | ||
749 | ><A | ||
750 | NAME="AEN168" | ||
751 | >Add alarms to network plugins</A | ||
752 | ></H2 | ||
753 | ><P | ||
754 | >If you write a plugin which communicates with another | ||
755 | networked host, you should make sure to set an alarm() in your | ||
756 | code that prevents the plugin from hanging due to abnormal | ||
757 | socket closures, etc. Nagios takes steps to protect itself | ||
758 | against unruly plugins that timeout, but any plugins you create | ||
759 | should be well behaved on their own.</P | ||
760 | ></DIV | ||
761 | ></DIV | ||
762 | ><DIV | ||
763 | CLASS="SECTION" | ||
764 | ><HR><H1 | ||
765 | CLASS="SECTION" | ||
766 | ><A | ||
767 | NAME="PLUGOPTIONS" | ||
768 | >Plugin Options</A | ||
769 | ></H1 | ||
770 | ><P | ||
771 | >A well written plugin should have --help as a way to get | ||
772 | verbose help. Code and output should try to respect the 80x25 size of a | ||
773 | crt (remember when fixing stuff in the server room!)</P | ||
774 | ><DIV | ||
775 | CLASS="SECTION" | ||
776 | ><HR><H2 | ||
777 | CLASS="SECTION" | ||
778 | ><A | ||
779 | NAME="AEN174" | ||
780 | >Option Processing</A | ||
781 | ></H2 | ||
782 | ><P | ||
783 | >For plugins written in C, we recommend the C standard | ||
784 | getopt library for short options. If using getopt_long, check to | ||
785 | be sure that HAVE_GETOPT_H is defined (configure checks this and | ||
786 | sets the #define in common/config.h).</P | ||
787 | ><P | ||
788 | >For plugins written in Perl, we recommend Getopt::Long module.</P | ||
789 | ><P | ||
790 | >Positional arguments are strongly discouraged.</P | ||
791 | ><P | ||
792 | >There are a few reserved options that should not be used | ||
793 | for other purposes:</P | ||
794 | ><P | ||
795 | CLASS="LITERALLAYOUT" | ||
796 | > -V version (--version)<br> | ||
797 | -h help (--help)<br> | ||
798 | -t timeout (--timeout)<br> | ||
799 | -w warning threshold (--warning)<br> | ||
800 | -c critical threshold (--critical)<br> | ||
801 | -H hostname (--hostname)<br> | ||
802 | </P | ||
803 | ><P | ||
804 | >In addition to the reserved options above, some other standard options are:</P | ||
805 | ><P | ||
806 | CLASS="LITERALLAYOUT" | ||
807 | > -C SNMP community (--community)<br> | ||
808 | -a authentication password (--authentication)<br> | ||
809 | -l login name (--logname)<br> | ||
810 | -p port or password (--port or --passwd/--password)monitors operational<br> | ||
811 | -u url or username (--url or --username)<br> | ||
812 | </P | ||
813 | ><P | ||
814 | >Look at check_pgsql and check_procs to see how I currently | ||
815 | think this can work. Standard options are:</P | ||
816 | ><P | ||
817 | >The option -V or --version should be present in all | ||
818 | plugins. For C plugins it should result in a call to print_revision, a | ||
819 | function in utils.c which takes two character arguments, the | ||
820 | command name and the plugin revision.</P | ||
821 | ><P | ||
822 | >The -? option, or any other unparsable set of options, | ||
823 | should print out a short usage statement. Character width should | ||
824 | be 80 and less and no more that 23 lines should be printed (it | ||
825 | should display cleanly on a dumb terminal in a server | ||
826 | room).</P | ||
827 | ><P | ||
828 | >The option -h or --help should be present in all plugins. | ||
829 | In C plugins, it should result in a call to print_help (or | ||
830 | equivalent). The function print_help should call print_revision, | ||
831 | then print_usage, then should provide detailed | ||
832 | help. Help text should fit on an 80-character width display, but | ||
833 | may run as many lines as needed.</P | ||
834 | ></DIV | ||
835 | ><DIV | ||
836 | CLASS="SECTION" | ||
837 | ><HR><H2 | ||
838 | CLASS="SECTION" | ||
839 | ><A | ||
840 | NAME="AEN187" | ||
841 | >Plugins with more than one type of threshold, or with | ||
842 | threshold ranges</A | ||
843 | ></H2 | ||
844 | ><P | ||
845 | >Old style was to do things like -ct for critical time and | ||
846 | -cv for critical value. That goes out the window with POSIX | ||
847 | getopt. The allowable alternatves are:</P | ||
848 | ><P | ||
849 | ></P | ||
850 | ><OL | ||
851 | TYPE="1" | ||
852 | ><LI | ||
853 | ><P | ||
854 | >long options like -critical-time (or -ct and -cv, I | ||
855 | suppose).</P | ||
856 | ></LI | ||
857 | ><LI | ||
858 | ><P | ||
859 | >repeated options like `check_load -w 10 -w 6 -w 4 -c | ||
860 | 16 -c 10 -c 10`</P | ||
861 | ></LI | ||
862 | ><LI | ||
863 | ><P | ||
864 | >for brevity, the above can be expressed as `check_load | ||
865 | -w 10,6,4 -c 16,10,10`</P | ||
866 | ></LI | ||
867 | ><LI | ||
868 | ><P | ||
869 | >ranges are expressed with colons as in `check_procs -C | ||
870 | httpd -w 1:20 -c 1:30` which will warn above 20 instances, | ||
871 | and critical at 0 and above 30</P | ||
872 | ></LI | ||
873 | ><LI | ||
874 | ><P | ||
875 | >lists are expressed with commas, so Jacob's check_nmap | ||
876 | uses constructs like '-p 1000,1010,1050:1060,2000'</P | ||
877 | ></LI | ||
878 | ><LI | ||
879 | ><P | ||
880 | >If possible when writing lists, use tokens to make the | ||
881 | list easy to remember and non-order dependent - so | ||
882 | check_disk uses '-c 10000,10%' so that it is clear which is | ||
883 | the precentage and which is the KB values (note that due to | ||
884 | my own lack of foresight, that used to be '-c 10000:10%' but | ||
885 | such constructs should all be changed for consistency, | ||
886 | though providing reverse compatibility is fairly | ||
887 | easy).</P | ||
888 | ></LI | ||
889 | ></OL | ||
890 | ><P | ||
891 | >As always, comments are welcome - making this consistent | ||
892 | without a host of long options was quite a hassle, and I would | ||
893 | suspect that there are flaws in this strategy. Perhaps clear | ||
894 | long-options is the most important of the above choices, but not | ||
895 | all POSIX systems have C libraries for long options, so the | ||
896 | short forms must exist as well.</P | ||
897 | ></DIV | ||
898 | ></DIV | ||
899 | ><DIV | ||
900 | CLASS="SECTION" | ||
901 | ><HR><H1 | ||
902 | CLASS="SECTION" | ||
903 | ><A | ||
904 | NAME="SUBMITTINGCHANGES" | ||
905 | >New submissions and patches</A | ||
906 | ></H1 | ||
907 | ><P | ||
908 | >If you would like other to use your plugins and have it included in | ||
909 | the standard distribution, please include patches for the relavant | ||
910 | configuration files, in particular "configure.in" Otherwise submitted | ||
911 | plugins will be included in the contrib directory.</P | ||
912 | ><P | ||
913 | >Plugins in the contrib directory are going to be migrated to the | ||
914 | standard plugins/plugin-scripts directory as time permits and per user | ||
915 | requests</P | ||
916 | ><P | ||
917 | >Patches should be submitted via the SourceForge and be announced to | ||
918 | the mailing list.</P | ||
919 | ><P | ||
920 | >For new plugins, provide a diff to add to the EXTRAS list (configure.in) | ||
921 | unless you are fairly sure that the plugin will work for all platforms with | ||
922 | no non-standard software added.</P | ||
923 | ><P | ||
924 | >If possible please submit a test harness. Documentation on sample | ||
925 | tests coming soon.</P | ||
926 | ></DIV | ||
927 | ></DIV | ||
928 | ></DIV | ||
929 | ></BODY | ||
930 | ></HTML | ||
931 | > \ No newline at end of file | ||
diff --git a/doc/developer-guidelines.sgml b/doc/developer-guidelines.sgml new file mode 100644 index 00000000..42ad8964 --- /dev/null +++ b/doc/developer-guidelines.sgml | |||
@@ -0,0 +1,483 @@ | |||
1 | <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN"> | ||
2 | <book> | ||
3 | <title>Nagios Plug-in Developer Guidelines</title> | ||
4 | |||
5 | <bookinfo> | ||
6 | <authorgroup> | ||
7 | <author> | ||
8 | <firstname>Karl</firstname> | ||
9 | <surname>DeBisschop</surname> | ||
10 | <affiliation> | ||
11 | <address><email>karl@debisschop.net</email></address> | ||
12 | </affiliation> | ||
13 | </author> | ||
14 | |||
15 | <author> | ||
16 | <firstname>Ethan</firstname> | ||
17 | <surname>Galstad</surname> | ||
18 | <authorblurb> | ||
19 | <para>Author of Nagios</para> | ||
20 | <para><ulink url="http://www.nagios.org"></ulink></para> | ||
21 | </authorblurb> | ||
22 | <affiliation> | ||
23 | <address><email>netsaint@linuxbox.com</email></address> | ||
24 | </affiliation> | ||
25 | </author> | ||
26 | |||
27 | <author> | ||
28 | <firstname>Hugo</firstname> | ||
29 | <surname>Gayosso</surname> | ||
30 | <affiliation> | ||
31 | <address><email>hgayosso@gnu.org</email></address> | ||
32 | </affiliation> | ||
33 | </author> | ||
34 | |||
35 | |||
36 | <author> | ||
37 | <firstname>Subhendu</firstname> | ||
38 | <surname>Ghosh</surname> | ||
39 | <affiliation> | ||
40 | <address><email>sghosh@sourceforge.net</email></address> | ||
41 | </affiliation> | ||
42 | </author> | ||
43 | |||
44 | <author> | ||
45 | <firstname>Stanley</firstname> | ||
46 | <surname>Hopcroft</surname> | ||
47 | <affiliation> | ||
48 | <address><email>stanleyhopcroft@sourceforge.net</email></address> | ||
49 | </affiliation> | ||
50 | </author> | ||
51 | |||
52 | </authorgroup> | ||
53 | |||
54 | <pubdate>2002</pubdate> | ||
55 | <title>Nagios plug-in development guidelines</title> | ||
56 | |||
57 | <revhistory> | ||
58 | <revision> | ||
59 | <revnumber>0.4</revnumber> | ||
60 | <date>2 May 2002</date> | ||
61 | </revision> | ||
62 | </revhistory> | ||
63 | |||
64 | <copyright> | ||
65 | <year>2000 2001 2002</year> | ||
66 | <holder>Karl DeBisschop, Ethan Galstad, | ||
67 | Hugo Gayosso, Stanley Hopcroft, Subhendu Ghosh</holder> | ||
68 | </copyright> | ||
69 | |||
70 | </bookinfo> | ||
71 | |||
72 | |||
73 | <preface id=preface> | ||
74 | <title>About the guidelines</title> | ||
75 | |||
76 | <para>The purpose of this guidelines is to provide a reference for | ||
77 | the plug-in developers and encourage the standarization of the | ||
78 | different kind of plug-ins: C, shell, perl, python, etc.</para> | ||
79 | |||
80 | |||
81 | <section> <title>Copyright</title> | ||
82 | |||
83 | <para>Nagios Plug-in Development Guidelines Copyright (C) 2000 2001 | ||
84 | 2002 | ||
85 | Karl DeBisschop, Ethan Galstad, Hugo Gayosso, Stanley Hopcroft, | ||
86 | Subhendu Ghosh</para> | ||
87 | |||
88 | <para>Permission is granted to make and distribute verbatim | ||
89 | copies of this manual provided the copyright notice and this | ||
90 | permission notice are preserved on all copies.</para> | ||
91 | |||
92 | <para>The plugins themselves are copyrighted by their respective | ||
93 | authors.</para> | ||
94 | |||
95 | </section> | ||
96 | </preface> | ||
97 | |||
98 | <article> | ||
99 | <section id="PlugOutput"><title>Plugin Output for Nagios</title> | ||
100 | |||
101 | <para>You should always print something to STDOUT that tells if the | ||
102 | service is working or why its failing. Try to keep the output short - | ||
103 | probably less that 80 characters. Remember that you ideally would like | ||
104 | the entire output to appear in a pager message, which will get chopped | ||
105 | off after a certain length.</para> | ||
106 | |||
107 | <section><title>Print only one line of text</title> | ||
108 | <para>Nagios will only grab the first line of text from STDOUT | ||
109 | when it notifies contacts about potential problems. If you print | ||
110 | multiple lines, you're out of luck. Remember, keep it short and | ||
111 | to the point.</para> | ||
112 | </section> | ||
113 | |||
114 | <section><title>Screen Output</title> | ||
115 | <para>The plug-in should print the diagnostic and just the | ||
116 | synopsis part of the help message. A well written plugin would | ||
117 | then have --help as a way to get the verbose help.</para> | ||
118 | <para>Code and output should try to respect the 80x25 size of a | ||
119 | crt (remember when fixing stuff in the server room!)</para> | ||
120 | </section> | ||
121 | |||
122 | <section><title>Return the proper status code</title> | ||
123 | <para>See <xref linkend="ReturnCodes"> below | ||
124 | for the numeric values of status codes and their | ||
125 | description. Remember to return an UNKNOWN state if bogus or | ||
126 | invalid command line arguments are supplied or it you are unable | ||
127 | to check the service.</para> | ||
128 | </section> | ||
129 | |||
130 | <section><title>Plugin Return Codes</title> | ||
131 | <para>The return codes below are based on the POSIX spec of returning | ||
132 | a positive value. Netsaint prior to v0.0.7 supported non-POSIX | ||
133 | compliant return code of "-1" for unknown. Nagios supports POSIX return | ||
134 | codes by default.</para> | ||
135 | |||
136 | <para>Note: Some plugins will on occasion print on STDOUT that an error | ||
137 | occurred and error code is 138 or 255 or some such number. These | ||
138 | are usually caused by plugins using system commands and having not | ||
139 | enough checks to catch unexpected output. Developers should include a | ||
140 | default catch-all for system command output that returns an UNKOWN | ||
141 | return code.</para> | ||
142 | |||
143 | <table id="ReturnCodes"><title>Plugin Return Codes</title> | ||
144 | <tgroup cols="3"> | ||
145 | <thead> | ||
146 | <row> | ||
147 | <entry><para>Numeric Value</para></entry> | ||
148 | <entry><para>Service Status</para></entry> | ||
149 | <entry><para>Status Description</para></entry> | ||
150 | </row> | ||
151 | </thead> | ||
152 | <tbody> | ||
153 | <row> | ||
154 | <entry align=center><para>0</para></entry> | ||
155 | <entry valign=middle><para>OK</para></entry> | ||
156 | <entry><para>The plugin was able to check the service and it | ||
157 | appeared to be functioning properly</para></entry> | ||
158 | </row> | ||
159 | <row> | ||
160 | <entry align=center><para>1</para></entry> | ||
161 | <entry valign=middle><para>Warning</para></entry> | ||
162 | <entry><para>The plugin was able to check the service, but it | ||
163 | appeared to be above some "warning" threshold or did not appear | ||
164 | to be working properly</para></entry> | ||
165 | </row> | ||
166 | <row> | ||
167 | <entry align=center><para>2</para></entry> | ||
168 | <entry valign=middle><para>Critical</para></entry> | ||
169 | <entry><para>The plugin detected that either the service was not | ||
170 | running or it was above some "critical" threshold</para></entry> | ||
171 | </row> | ||
172 | <row> | ||
173 | <entry align=center><para>3</para></entry> | ||
174 | <entry valign=middle><para>Unknown</para></entry> | ||
175 | <entry><para>Invalid command line arguments were supplied to the | ||
176 | plugin or the plugin was unable to check the status of the given | ||
177 | hosts/service</para></entry> | ||
178 | </row> | ||
179 | </tbody> | ||
180 | </tgroup> | ||
181 | </table> | ||
182 | |||
183 | |||
184 | </section> | ||
185 | |||
186 | |||
187 | </section> | ||
188 | |||
189 | <section id="SysCmdAuxFiles"><title>System Commands and Auxiliary Files</title> | ||
190 | |||
191 | <section><title>Don't execute system commands without specifying their | ||
192 | full path</title> | ||
193 | <para>Don't use exec(), popen(), etc. to execute external | ||
194 | commands without explicity using the full path of the external | ||
195 | program.</para> | ||
196 | |||
197 | <para>Doing otherwise makes the plugin vulnerable to hijacking | ||
198 | by a trojan horse earlier in the search path. See the main | ||
199 | plugin distribution for examples on how this is done.</para> | ||
200 | </section> | ||
201 | |||
202 | <section><title>Use spopen() if external commands must be executed</title> | ||
203 | |||
204 | <para>If you have to execute external commands from within your | ||
205 | plugin and you're writing it in C, use the spopen() function | ||
206 | that Karl DeBisschop has written.</para> | ||
207 | |||
208 | <para>The code for spopen() and spclose() is included with the | ||
209 | core plugin distribution.</para> | ||
210 | </section> | ||
211 | |||
212 | <section><title>Don't make temp files unless absolutely required</title> | ||
213 | |||
214 | <para>If temp files are needed, make sure that the plugin will | ||
215 | fail cleanly if the file can't be written (e.g., too few file | ||
216 | handles, out of disk space, incorrect permissions, etc.) and | ||
217 | delete the temp file when processing is complete.</para> | ||
218 | </section> | ||
219 | |||
220 | <section><title>Don't be tricked into following symlinks</title> | ||
221 | |||
222 | <para>If your plugin opens any files, take steps to ensure that | ||
223 | you are not following a symlink to another location on the | ||
224 | system.</para> | ||
225 | </section> | ||
226 | |||
227 | <section><title>Validate all input</title> | ||
228 | |||
229 | <para>use routines in utils.c or utils.pm and write more as needed</para> | ||
230 | </section> | ||
231 | |||
232 | </section> | ||
233 | |||
234 | |||
235 | |||
236 | |||
237 | <section id="PerlPlugin"><title>Perl Plugins</title> | ||
238 | |||
239 | <para>Perl plugins are coded a little more defensively than other | ||
240 | plugins because of embedded Perl. When configured as such, embedded | ||
241 | Perl Nagios (ePN) requires stricter use of the some of Perl's features. | ||
242 | This section outlines some of the steps needed to use ePN | ||
243 | effectively.</para> | ||
244 | |||
245 | <orderedlist> | ||
246 | |||
247 | <listitem><para> Do not use BEGIN and END blocks since they will be called | ||
248 | the first time and when Nagios shuts down with Embedded Perl (ePN). In | ||
249 | particular, do not use BEGIN blocks to initialize variables.</para> | ||
250 | </listitem> | ||
251 | |||
252 | <listitem><para>To use utils.pm, you need to provide a full path to the | ||
253 | module in order for it to work with ePN.</para> | ||
254 | |||
255 | <literallayout> | ||
256 | e.g. | ||
257 | use lib "/usr/local/nagios/libexec"; | ||
258 | use utils qw(...); | ||
259 | </literallayout> | ||
260 | </listitem> | ||
261 | |||
262 | <listitem><para>Perl scripts should be called with "-w"</para> | ||
263 | </listitem> | ||
264 | |||
265 | <listitem><para>All Perl plugins must compile cleanly under "use strict" - i.e. at | ||
266 | least explicitly package names as in "$main::x" or predeclare every | ||
267 | variable. </para> | ||
268 | |||
269 | |||
270 | <para>Explicitly initialize each varialable in use. Otherwise with | ||
271 | caching enabled, the plugin will not be recompilied each time, and | ||
272 | therefore Perl will not reinitialize all the variables. All old | ||
273 | variable values will still be in effect.</para> | ||
274 | </listitem> | ||
275 | |||
276 | <listitem><para>Do not use < DATA > (these simply do not compile under ePN).</para> | ||
277 | </listitem> | ||
278 | |||
279 | <listitem><para>Do not use named subroutines</para> | ||
280 | </listitem> | ||
281 | |||
282 | <listitem><para>If writing to a file (perhaps recording | ||
283 | performance data) explicitly close close it. The plugin never | ||
284 | calls <emphasis role=strong>exit</emphasis>; that is caught by | ||
285 | p1.pl, so output streams are never closed.</para> | ||
286 | </listitem> | ||
287 | |||
288 | <listitem><para>As in <xref linkend="runtime"> all plugins need | ||
289 | to monitor their runtime, specially if they are using network | ||
290 | resources. Use of the <emphasis>alarm</emphasis> is recommended. | ||
291 | Plugins may import a default time out ($TIMEOUT) from utils.pm. | ||
292 | </para> | ||
293 | </listitem> | ||
294 | |||
295 | <listitem><para>Perl plugins should import %ERRORS from utils.pm | ||
296 | and then "exit $ERRORS{'OK'}" rather than "exit 0" | ||
297 | </para> | ||
298 | </listitem> | ||
299 | |||
300 | </orderedlist> | ||
301 | |||
302 | </section> | ||
303 | |||
304 | <section id="runtime"><title>Runtime Timeouts</title> | ||
305 | |||
306 | <para>Plugins have a very limited runtime - typically 10 sec. | ||
307 | As a result, it is very important for plugins to maintain internal | ||
308 | code to exit if runtime exceeds a threshold. </para> | ||
309 | |||
310 | <para>All plugins should timeout gracefully, not just networking | ||
311 | plugins. For instance, df may lock if you have automounted | ||
312 | drives and your network fails - but on first glance, who'd think | ||
313 | df could lock up like that. Plus, it should just be more error | ||
314 | resistant to be able to time out rather than consume | ||
315 | resources.</para> | ||
316 | |||
317 | <section><title>Use DEFAULT_SOCKET_TIMEOUT</title> | ||
318 | |||
319 | <para>All network plugins should use DEFAULT_SOCKET_TIMEOUT to timeout</para> | ||
320 | |||
321 | </section> | ||
322 | |||
323 | |||
324 | <section><title>Add alarms to network plugins</title> | ||
325 | |||
326 | <para>If you write a plugin which communicates with another | ||
327 | networked host, you should make sure to set an alarm() in your | ||
328 | code that prevents the plugin from hanging due to abnormal | ||
329 | socket closures, etc. Nagios takes steps to protect itself | ||
330 | against unruly plugins that timeout, but any plugins you create | ||
331 | should be well behaved on their own.</para> | ||
332 | |||
333 | </section> | ||
334 | |||
335 | |||
336 | |||
337 | </section> | ||
338 | |||
339 | <section id="PlugOptions"><title>Plugin Options</title> | ||
340 | |||
341 | <para>A well written plugin should have --help as a way to get | ||
342 | verbose help. Code and output should try to respect the 80x25 size of a | ||
343 | crt (remember when fixing stuff in the server room!)</para> | ||
344 | |||
345 | <section><title>Option Processing</title> | ||
346 | |||
347 | <para>For plugins written in C, we recommend the C standard | ||
348 | getopt library for short options. If using getopt_long, check to | ||
349 | be sure that HAVE_GETOPT_H is defined (configure checks this and | ||
350 | sets the #define in common/config.h).</para> | ||
351 | |||
352 | <para>For plugins written in Perl, we recommend Getopt::Long module.</para> | ||
353 | |||
354 | <para>Positional arguments are strongly discouraged.</para> | ||
355 | |||
356 | <para>There are a few reserved options that should not be used | ||
357 | for other purposes:</para> | ||
358 | |||
359 | <literallayout> | ||
360 | -V version (--version) | ||
361 | -h help (--help) | ||
362 | -t timeout (--timeout) | ||
363 | -w warning threshold (--warning) | ||
364 | -c critical threshold (--critical) | ||
365 | -H hostname (--hostname) | ||
366 | </literallayout> | ||
367 | |||
368 | <para>In addition to the reserved options above, some other standard options are:</para> | ||
369 | |||
370 | <literallayout> | ||
371 | -C SNMP community (--community) | ||
372 | -a authentication password (--authentication) | ||
373 | -l login name (--logname) | ||
374 | -p port or password (--port or --passwd/--password)monitors operational | ||
375 | -u url or username (--url or --username) | ||
376 | </literallayout> | ||
377 | |||
378 | <para>Look at check_pgsql and check_procs to see how I currently | ||
379 | think this can work. Standard options are:</para> | ||
380 | |||
381 | |||
382 | <para>The option -V or --version should be present in all | ||
383 | plugins. For C plugins it should result in a call to print_revision, a | ||
384 | function in utils.c which takes two character arguments, the | ||
385 | command name and the plugin revision.</para> | ||
386 | |||
387 | <para>The -? option, or any other unparsable set of options, | ||
388 | should print out a short usage statement. Character width should | ||
389 | be 80 and less and no more that 23 lines should be printed (it | ||
390 | should display cleanly on a dumb terminal in a server | ||
391 | room).</para> | ||
392 | |||
393 | <para>The option -h or --help should be present in all plugins. | ||
394 | In C plugins, it should result in a call to print_help (or | ||
395 | equivalent). The function print_help should call print_revision, | ||
396 | then print_usage, then should provide detailed | ||
397 | help. Help text should fit on an 80-character width display, but | ||
398 | may run as many lines as needed.</para> | ||
399 | |||
400 | </section> | ||
401 | |||
402 | <section> | ||
403 | <title>Plugins with more than one type of threshold, or with | ||
404 | threshold ranges</title> | ||
405 | |||
406 | <para>Old style was to do things like -ct for critical time and | ||
407 | -cv for critical value. That goes out the window with POSIX | ||
408 | getopt. The allowable alternatves are:</para> | ||
409 | |||
410 | <orderedlist> | ||
411 | <listitem> | ||
412 | <para>long options like -critical-time (or -ct and -cv, I | ||
413 | suppose).</para> | ||
414 | </listitem> | ||
415 | |||
416 | <listitem> | ||
417 | <para>repeated options like `check_load -w 10 -w 6 -w 4 -c | ||
418 | 16 -c 10 -c 10`</para> | ||
419 | </listitem> | ||
420 | |||
421 | <listitem> | ||
422 | <para>for brevity, the above can be expressed as `check_load | ||
423 | -w 10,6,4 -c 16,10,10`</para> | ||
424 | </listitem> | ||
425 | |||
426 | <listitem> | ||
427 | <para>ranges are expressed with colons as in `check_procs -C | ||
428 | httpd -w 1:20 -c 1:30` which will warn above 20 instances, | ||
429 | and critical at 0 and above 30</para> | ||
430 | </listitem> | ||
431 | |||
432 | <listitem> | ||
433 | <para>lists are expressed with commas, so Jacob's check_nmap | ||
434 | uses constructs like '-p 1000,1010,1050:1060,2000'</para> | ||
435 | </listitem> | ||
436 | |||
437 | <listitem> | ||
438 | <para>If possible when writing lists, use tokens to make the | ||
439 | list easy to remember and non-order dependent - so | ||
440 | check_disk uses '-c 10000,10%' so that it is clear which is | ||
441 | the precentage and which is the KB values (note that due to | ||
442 | my own lack of foresight, that used to be '-c 10000:10%' but | ||
443 | such constructs should all be changed for consistency, | ||
444 | though providing reverse compatibility is fairly | ||
445 | easy).</para> | ||
446 | </listitem> | ||
447 | |||
448 | </orderedlist> | ||
449 | |||
450 | <para>As always, comments are welcome - making this consistent | ||
451 | without a host of long options was quite a hassle, and I would | ||
452 | suspect that there are flaws in this strategy. Perhaps clear | ||
453 | long-options is the most important of the above choices, but not | ||
454 | all POSIX systems have C libraries for long options, so the | ||
455 | short forms must exist as well.</para> | ||
456 | </section> | ||
457 | </section> | ||
458 | |||
459 | <section id="SubmittingChanges"><title>New submissions and patches</title> | ||
460 | |||
461 | <para>If you would like other to use your plugins and have it included in | ||
462 | the standard distribution, please include patches for the relavant | ||
463 | configuration files, in particular "configure.in" Otherwise submitted | ||
464 | plugins will be included in the contrib directory.</para> | ||
465 | |||
466 | <para>Plugins in the contrib directory are going to be migrated to the | ||
467 | standard plugins/plugin-scripts directory as time permits and per user | ||
468 | requests</para> | ||
469 | |||
470 | <para>Patches should be submitted via the SourceForge and be announced to | ||
471 | the mailing list.</para> | ||
472 | |||
473 | <para>For new plugins, provide a diff to add to the EXTRAS list (configure.in) | ||
474 | unless you are fairly sure that the plugin will work for all platforms with | ||
475 | no non-standard software added.</para> | ||
476 | |||
477 | <para>If possible please submit a test harness. Documentation on sample | ||
478 | tests coming soon.</para> | ||
479 | |||
480 | </section> | ||
481 | </article> | ||
482 | |||
483 | </book> | ||