View Javadoc

1   /*******************************************************************************
2    * Copyright (c) 2007, 2014 Massimiliano Ziccardi
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *******************************************************************************/
16  package it.jnrpe.plugin;
17  
18  import it.jnrpe.ICommandLine;
19  import it.jnrpe.ReturnValue;
20  import it.jnrpe.Status;
21  import it.jnrpe.events.LogEvent;
22  import it.jnrpe.plugins.PluginBase;
23  import it.jnrpe.plugins.annotations.Option;
24  import it.jnrpe.plugins.annotations.Plugin;
25  import it.jnrpe.plugins.annotations.PluginOptions;
26  import it.jnrpe.utils.BadThresholdException;
27  import it.jnrpe.utils.StreamManager;
28  import it.jnrpe.utils.ThresholdUtil;
29  
30  import java.io.BufferedReader;
31  import java.io.File;
32  import java.io.FileReader;
33  import java.io.IOException;
34  import java.math.BigDecimal;
35  
36  /**
37   * Performs the following checks:
38   * <ul>
39   * <li>Checks that a file do not exist (param -F)
40   * <li>Checks that a file exist (param -f)
41   * <li>Checks file age (params -w and -c). Requires param -f
42   * <li>Checks file size (params -W and -C). Requires param -f
43   * <li>Checks how many time a string is repeatend inside a file (params -O).
44   * Requires param -f. The string cannot contain ','. Optionally, you can specify
45   * WARNING and CRITICAL range. To specify the ranges, use a syntax like:
46   * <blockquote> -f path/to/your/file -O *YOURSTRING*,*WARNING*,*CRITICAL*
47   * </blockquote> If you do not specify the ranges, it's the same as:
48   * <blockquote> -f path/to/your/file -O *YOURSTRING*,:0,:0 </blockquote> This
49   * means that a CRITICAL state will be raised if the string is not present.
50   * <B>Be careful! The whole file will be read. This can be quite slow with very
51   * large files</B>
52   * <li>Check that a file do not contains a string (params -N). Strings cannot
53   * contains ','. Strings are separated by comma. Requires param -f
54   * </ul>
55   *
56   * The params -w, -c, -W and -C requires as argument a range in the standard
57   * nagios format.
58   *
59   * @author Massimiliano Ziccardi
60   */
61  @Plugin(
62          name = "CHECK_FILE",
63          description = "This plugin is used to perform various check against files:\n\n" +
64          "  * checks that a file exists (-f)\n" +
65          "  * checks that a file does not exists (-F)\n" +
66          "  * check file age (requires -f)\n" +
67          "  * check file size (requires -f)\n" +
68          "  * check how many lines of a file contains the given string. You can specify the warning and the critical range. (requires -f)\n" +
69          "     EXAMPLE: -f /path/to/your/file --contains MyString,0:10,11:\n" +
70          "  * check that a string is not inside the file (requires -f)\n"
71                        )
72  @PluginOptions({
73      @Option(shortName="F", longName="FILE", description="The path of the file the must not exist",
74              required=false, hasArgs=true, argName="path", optionalArgs=false, option="FILE"),
75      @Option(shortName="f", longName="file", description="The path to the file to check",
76              required=false, hasArgs=true, argName="path", optionalArgs=false, option="file"),
77      @Option(shortName="w", longName="warning", description="The max age (in seconds) before a warning is raised",
78              required=false, hasArgs=true, argName="age threshold", optionalArgs=false, option="warning"),
79      @Option(shortName="c", longName="critical", description="The max age (in seconds) before a critical is raisedk",
80              required=false, hasArgs=true, argName="age threshold", optionalArgs=false, option="critical"),
81      @Option(shortName="W", longName="sizewarning", description="The min file size (in bytes) before a warning is raised",
82              required=false, hasArgs=true, argName="size threshold", optionalArgs=false, option="sizewarning"),
83      @Option(shortName="C", longName="sizecritical", description="The min file size (in bytes) before a critical is raised",
84              required=false, hasArgs=true, argName="size threshold", optionalArgs=false, option="sizecritical"),
85      @Option(shortName="O", longName="contains", 
86          description="The string that must be found inside the file in the format STRING,WARNING_RANGE,CRITICAL_RANGE.",
87              required=false, hasArgs=true, argName="string to check", optionalArgs=false, option="contains"),
88      @Option(shortName="N", longName="notcontains", description="The path to the file to check",
89              required=false, hasArgs=true, argName="string to check", optionalArgs=false, option="notcontains"),
90                })
91  public class CCheckFile extends PluginBase {
92  
93      /**
94       * Updates the checkfile plugin result.
95       *
96       * @param res
97       *            The current return value
98       * @param newVal
99       *            The new return value
100      * @return The updated return value
101      */
102     private ReturnValue updateRes(final ReturnValue res,
103             final ReturnValue newVal) {
104 
105         if (res == null) {
106             return newVal;
107         }
108 
109         switch (res.getStatus()) {
110         case CRITICAL:
111             return res;
112         case WARNING:
113             if (newVal.getStatus() != Status.CRITICAL) {
114                 return res;
115             }
116             return newVal;
117         case OK:
118             if (newVal.getStatus() == Status.OK) {
119                 return res;
120             }
121             return newVal;
122         default:
123             return res;
124         }
125     }
126 
127     /**
128      * Checks if the file exists and updates the return value object.
129      *
130      * @param f
131      *            The file to be checked
132      * @param res
133      *            The return value to be updated
134      * @return The updated return value
135      */
136     private ReturnValue checkFileExists(final File f, final ReturnValue res) {
137         if (f.exists()) {
138             return updateRes(res, new ReturnValue(Status.OK, "FILE OK"));
139         }
140         return updateRes(res, new ReturnValue(Status.CRITICAL,
141                 "FILE CRITICAL: File '" + f.getAbsolutePath()
142                         + "' do not exists"));
143     }
144 
145     /**
146      * Checks the file age and updates the return value.
147      *
148      * @param cl
149      *            The passed in command line
150      * @param f
151      *            The file to be checked
152      * @param res
153      *            The result value to be updated
154      * @return The updated return value
155      * @throws BadThresholdException
156      *             -
157      */
158     private ReturnValue checkAge(final ICommandLine cl, final File f,
159             final ReturnValue res)
160             throws BadThresholdException {
161         if (cl.hasOption("critical")) {
162             long lLastAccess = f.lastModified();
163             long lNow = System.currentTimeMillis();
164             BigDecimal lAge =
165                     new BigDecimal("" + ((lNow - lLastAccess) / 1000));
166             String sCriticalThreshold = cl.getOptionValue("critical");
167 
168             if (ThresholdUtil.isValueInRange(sCriticalThreshold, lAge)) {
169                 return updateRes(res, new ReturnValue(Status.CRITICAL,
170                         "FILE CRITICAL - File age : " + lAge + " seconds"));
171             }
172         }
173 
174         if (cl.hasOption("warning")) {
175             long lLastAccess = f.lastModified();
176             long lNow = System.currentTimeMillis();
177             BigDecimal lAge =
178                     new BigDecimal("" + ((lNow - lLastAccess) / 1000));
179             String sWarningThreshold = cl.getOptionValue("warning");
180 
181             if (ThresholdUtil.isValueInRange(sWarningThreshold, lAge)) {
182                 return updateRes(res, new ReturnValue(Status.WARNING,
183                         "FILE WARNING - File age : " + lAge + " seconds"));
184             }
185         }
186 
187         return updateRes(res, new ReturnValue(Status.OK, "FILE OK"));
188     }
189 
190     /**
191      * Checks the file size.
192      *
193      * @param cl
194      *            The passed in command line
195      * @param f
196      *            The file to be checked
197      * @param res
198      *            The return value to be updated
199      * @return The updated return value
200      * @throws BadThresholdException
201      *             -
202      */
203     private ReturnValue checkSize(final ICommandLine cl, final File f,
204             final ReturnValue res)
205             throws BadThresholdException {
206         if (cl.hasOption("sizecritical")) {
207             String sCriticalThreshold = cl.getOptionValue("sizecritical");
208             BigDecimal bdSize = new BigDecimal("" + f.length());
209 
210             if (ThresholdUtil.isValueInRange(sCriticalThreshold, bdSize)) {
211                 return updateRes(res, new ReturnValue(Status.CRITICAL,
212                         "FILE CRITICAL - File size : " + bdSize + " bytes"));
213             }
214         }
215 
216         if (cl.hasOption("sizewarning")) {
217             String sWarningThreshold = cl.getOptionValue("sizewarning");
218             BigDecimal bdSize = new BigDecimal("" + f.length());
219 
220             if (ThresholdUtil.isValueInRange(sWarningThreshold, bdSize)) {
221                 return updateRes(res, new ReturnValue(Status.WARNING,
222                         "FILE WARNING  - File size : " + bdSize + " bytes"));
223             }
224         }
225 
226         return updateRes(res, new ReturnValue(Status.OK, "FILE OK"));
227     }
228 
229     /**
230      * Checks the file content.
231      *
232      * @param cl
233      *            The passed in command line
234      * @param f
235      *            The file to be checked
236      * @param res
237      *            The return value to be updated
238      * @return The updated return value
239      * @throws BadThresholdException
240      *             -
241      */
242     private ReturnValue checkContains(final ICommandLine cl, final File f,
243             final ReturnValue res)
244             throws BadThresholdException {
245         if (!cl.hasOption("contains")) {
246             return updateRes(res, new ReturnValue(Status.OK, "FILE OK"));
247         }
248 
249         StreamManager sm = new StreamManager();
250 
251         try {
252             BufferedReader r =
253                     (BufferedReader) sm.handle(new BufferedReader(
254                             new FileReader(f)));
255             String sLine = null;
256 
257             String sWarningThreshold = ":0";
258             String sCriticalThreshold = ":0";
259 
260             String sPattern = cl.getOptionValue("contains");
261             if (sPattern.indexOf(',') != -1) {
262                 String[] vsParts = sPattern.split(",");
263                 sWarningThreshold = vsParts[1];
264                 if (vsParts.length > 1) {
265                     sCriticalThreshold = vsParts[2];
266                 }
267                 sPattern = vsParts[0];
268             }
269 
270             int iCount = 0;
271 
272             while ((sLine = r.readLine()) != null) {
273                 if (sLine.indexOf(sPattern) != -1) {
274                     iCount++;
275                 }
276                 // return updateRes(res, new ReturnValue(Status.OK, "FILE OK"));
277             }
278 
279             if (ThresholdUtil.isValueInRange(sCriticalThreshold, iCount)) {
280                 return updateRes(res, new ReturnValue(Status.CRITICAL,
281                         "FILE CRITICAL - String '" + sPattern + "' found "
282                                 + iCount + " times"));
283             }
284             if (ThresholdUtil.isValueInRange(sWarningThreshold, iCount)) {
285                 return updateRes(res, new ReturnValue(Status.WARNING,
286                         "FILE WARNING - String '" + sPattern + "' found "
287                                 + iCount + " times"));
288             }
289 
290             return updateRes(res, new ReturnValue(Status.OK,
291                     "FILE OK - String '" + sPattern + "' found " + iCount
292                             + " times"));
293         } catch (IOException e) {
294             sendEvent(LogEvent.WARNING,
295                     "Plugin Execution error : " + e.getMessage(), e);
296             return updateRes(res, new ReturnValue(Status.UNKNOWN,
297                     "FILE UNKNOWN - " + e.getMessage()));
298         } finally {
299             sm.closeAll();
300         }
301 
302     }
303 
304     /**
305      * Checks that the file do not contains a string.
306      *
307      * @param cl
308      *            The passed in command line
309      * @param f
310      *            The file to be checked
311      * @param res
312      *            The result to be updated
313      * @return The updated result
314      */
315     private ReturnValue checkNotContains(final ICommandLine cl, final File f,
316             final ReturnValue res) {
317         if (!cl.hasOption("notcontains")) {
318             return updateRes(res, new ReturnValue(Status.OK, "FILE OK"));
319         }
320 
321         StreamManager sm = new StreamManager();
322 
323         try {
324             BufferedReader r =
325                     (BufferedReader) sm.handle(new BufferedReader(
326                             new FileReader(f)));
327             String sLine = null;
328 
329             String[] vsPatterns = cl.getOptionValue("notcontains").split(",");
330 
331             while ((sLine = r.readLine()) != null) {
332                 for (int i = 0; i < vsPatterns.length; i++) {
333                     if (sLine.indexOf(vsPatterns[i]) != -1) {
334                         return updateRes(
335                                 res,
336                                 new ReturnValue(
337                                         Status.CRITICAL,
338                                         "FILE CRITICAL - String '"
339                                             + cl.getOptionValue("notcontains")
340                                             + "' found"));
341                     }
342                 }
343             }
344             return updateRes(res, new ReturnValue(Status.OK,
345                     "FILE OK: String '" + cl.getOptionValue("notcontains")
346                             + "' not found"));
347         } catch (IOException e) {
348             sendEvent(LogEvent.WARNING,
349                     "Plugin Execution error : " + e.getMessage(), e);
350             return updateRes(res, new ReturnValue(Status.UNKNOWN,
351                     "FILE UNKNOWN - " + e.getMessage()));
352         } finally {
353             sm.closeAll();
354         }
355 
356     }
357 
358     /**
359      * Executes the plugin.
360      *
361      * @param cl
362      *            The command line
363      * @return the return value
364      * @throws BadThresholdException
365      *             -
366      */
367     public final ReturnValue execute(final ICommandLine cl)
368             throws BadThresholdException {
369         if (cl.hasOption("FILE")) {
370             File f = new File(cl.getOptionValue("FILE"));
371             if (f.exists()) {
372                 return new ReturnValue(Status.CRITICAL, "File '" + f.getName()
373                         + "' exists");
374             } else {
375                 return new ReturnValue(Status.OK, "File '" + f.getName()
376                         + "' is OK");
377             }
378         }
379 
380         // ReturnValue res = new ReturnValue(Status.OK, "CHECK_FILE: OK");
381 
382         File f = null;
383 
384         if (cl.hasOption("file")) {
385             f = new File(cl.getOptionValue("file"));
386         } else {
387             return new ReturnValue(Status.UNKNOWN,
388                     "Either param -f or -F must be specified");
389         }
390 
391         // if (!f.exists())
392         // return new ReturnValue(Status.CRITICAL, "File '" + f.getName() +
393         // "' not found");
394 
395         // Check that the file exists...
396         ReturnValue res = checkFileExists(f, null);
397 
398         if (res == null || res.getStatus() != Status.CRITICAL) {
399             res = checkAge(cl, f, res);
400         }
401         if (res == null || res.getStatus() != Status.CRITICAL) {
402             res = checkSize(cl, f, res);
403         }
404         if (res == null || res.getStatus() != Status.CRITICAL) {
405             res = checkContains(cl, f, res);
406         }
407         if (res == null || res.getStatus() != Status.CRITICAL) {
408             res = checkNotContains(cl, f, res);
409         }
410 
411         return res;
412     }
413 
414     @Override
415     protected String getPluginName() {
416         return "CHECK_FILE";
417     }
418 }