check_cpu_usage 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. #!/usr/bin/perl
  2. #-------------------------------------------------------------------------------
  3. #
  4. # Programm : check_cpu_usage
  5. #
  6. #-------------------------------------------------------------------------------
  7. #
  8. # Beschreibung : Nagios check script to check the CPU Usage by monitoring
  9. # /proc/stat.
  10. #
  11. # Author : Marek Zavesicky
  12. # Version : $Revision: $
  13. # Erstellt : 2013/08/26
  14. # Letztes Update : $Date: $
  15. #
  16. # $Id: $
  17. # Change history :
  18. # $Log: $
  19. #
  20. # This program is free software; you can redistribute it and/or modify it
  21. # under the terms of the GNU General Public License as published by the
  22. # Free Software Foundation; either version 2 of the License, or (at your
  23. # option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
  24. #
  25. # This program is distributed in the hope that it will be useful, but
  26. # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  27. # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  28. # for more details.
  29. #
  30. #-------------------------------------------------------------------------------
  31. #-------------------------------------------------------------------------------
  32. # Pragma
  33. #-------------------------------------------------------------------------------
  34. use strict;
  35. use warnings;
  36. #-------------------------------------------------------------------------------
  37. # Used Modules
  38. #-------------------------------------------------------------------------------
  39. # use lib "/usr/local/nrpe/perl/lib";
  40. use Nagios::Plugin;
  41. #use Monitoring::Plugin;
  42. use Data::Dumper;
  43. #-------------------------------------------------------------------------------
  44. # Function : readStatFile
  45. #-------------------------------------------------------------------------------
  46. # Description : Parses the stat file and extract the counters, then store
  47. # them in a hash
  48. #
  49. # Input : $np Nagios::Plugins reference
  50. # $file A file with status informations
  51. # $names Array that has the order of the fields
  52. # Output : $stat A hash object with the newdata stats
  53. #-------------------------------------------------------------------------------
  54. sub readStatFile
  55. {
  56. my $np = shift;
  57. my $file = shift;
  58. my $names = shift;
  59. my $stat = ();
  60. open( FILE, "<", $file ) or $np->nagios_die( "cant open file $file" );
  61. while ( <FILE> )
  62. {
  63. next unless ( $_ =~ /^cpu/ );
  64. my ( $name, @cpudata ) = split( '\s+', $_ );
  65. $stat->{ $name } = \@cpudata;
  66. }
  67. close( FILE );
  68. return $stat;
  69. }
  70. #-------------------------------------------------------------------------------
  71. # Function : writeStatFile
  72. #-------------------------------------------------------------------------------
  73. # Description : Write the olddata object to the gapfile
  74. #
  75. # Input : $np Nagios::Plugins reference
  76. # $objects the data objects
  77. # $names Array that has the order of the fields
  78. # Output : -
  79. #-------------------------------------------------------------------------------
  80. sub writeStatFile
  81. {
  82. my $np = shift;
  83. my $objects = shift;
  84. my $names = shift;
  85. open( FILE, ">", $np->opts->gapfile ) or $np->nagios_die( "cant open file $np->opts->gapfile" );
  86. foreach ( keys %{ $objects->{ newdata } } )
  87. {
  88. my $string = $_ . " ";
  89. $string .= join( " ", @{ $objects->{ newdata }->{ $_ } } );
  90. print FILE $string . "\n";
  91. }
  92. close( FILE );
  93. }
  94. #-------------------------------------------------------------------------------
  95. # Function : calculateData
  96. #-------------------------------------------------------------------------------
  97. # Description : Calculate the diference between old and new data and store
  98. # the result in an array. Summarize all differences and
  99. # calculate the percentage of each value.
  100. #
  101. # Input : $np Nagios::Plugins reference
  102. # $objects the data objects
  103. # $names Array that has the order of the fields
  104. # Output : -
  105. #-------------------------------------------------------------------------------
  106. sub calculateData
  107. {
  108. my $name = shift;
  109. my $objects = shift;
  110. my $names = shift;
  111. my @results;
  112. my $sum = 0;
  113. my $cpu = ();
  114. for ( my $i = 0; $i < scalar @$names; $i++ )
  115. {
  116. if ( defined( $objects->{ olddata }->{ $name }->[ $i ] ) )
  117. {
  118. push( @results, $objects->{ newdata }->{ $name }->[ $i ] - $objects->{ olddata }->{ $name }->[ $i ] );
  119. $sum += $results[ $i ];
  120. }
  121. else
  122. {
  123. push( @results, 0 );
  124. }
  125. }
  126. for ( my $i = 0; $i < scalar @$names; $i++ )
  127. {
  128. $cpu->[ $i ] = $results[ $i ] * 100 / $sum;
  129. }
  130. return $cpu;
  131. }
  132. #-------------------------------------------------------------------------------
  133. # Function : processData
  134. #-------------------------------------------------------------------------------
  135. # Description : Process the hashes of cpu's.
  136. #
  137. # Input : $np Nagios::Plugins reference
  138. # $objects the data objects
  139. # $names Array that has the order of the fields
  140. # Output : -
  141. #-------------------------------------------------------------------------------
  142. sub processData
  143. {
  144. my $np = shift;
  145. my $objects = shift;
  146. my $names = shift;
  147. my $percent = ();
  148. $percent->{ cpu } = calculateData( "cpu", $objects, $names );
  149. if ( $np->opts->details )
  150. {
  151. foreach ( sort keys %{ $objects->{ olddata } } )
  152. {
  153. next if ( $_ eq 'cpu' );
  154. $percent->{ $_ } = calculateData( $_, $objects, $names );
  155. }
  156. }
  157. return $percent;
  158. }
  159. #-------------------------------------------------------------------------------
  160. # Function : compareData
  161. #-------------------------------------------------------------------------------
  162. # Description : Compare data with threshold if needed and generate the
  163. # performance data string.
  164. #
  165. # Input : $np Nagios::Plugins reference
  166. # $objects the data objects
  167. # $names Array that has the order of the fields
  168. # Output : -
  169. #-------------------------------------------------------------------------------
  170. sub compareData
  171. {
  172. my $np = shift;
  173. my $objects = shift;
  174. my $names = shift;
  175. my $warnings = [ split( ',', $np->opts->warning ) ];
  176. my $criticals = [ split( ',', $np->opts->critical ) ];
  177. my $string = "";
  178. my $result = 0;
  179. my $res;
  180. foreach ( sort keys %{ $objects->{ olddata } } )
  181. {
  182. # if details are not needed, grab the next line
  183. unless ( $np->opts->details )
  184. {
  185. next unless ( $_ eq 'cpu' );
  186. }
  187. # compute all columns and check the thresholds
  188. $string .= uc( $_ );
  189. for ( my $i = 0; $i < scalar @$names; $i++ )
  190. {
  191. if ( defined( $$warnings[ $i ] ) and defined( $$criticals[ $i ] ) and ( $$warnings[ $i ] ne "none" ) and ( $$criticals[ $i ] ne "none" ) )
  192. {
  193. $res = $np->check_threshold( check => $objects->{ percent }->{ $_ }->[ $i ],
  194. warning => $$warnings[ $i ],
  195. critical => $$criticals[ $i ] );
  196. # Evaluate the new return code, do not overwrite higher severity by lower
  197. $result = ( $res > $result ? $res : $result );
  198. $np->add_perfdata(
  199. label => $_ . "_" . $$names[ $i ],
  200. value => $objects->{ percent }->{ $_ }->[ $i ],
  201. warning => $$warnings[ $i ],
  202. critical => $$criticals[ $i ],
  203. uom => "%"
  204. );
  205. }
  206. else
  207. {
  208. $np->add_perfdata(
  209. label => $_ . "_" . $$names[ $i ],
  210. value => $objects->{ percent }->{ $_ }->[ $i ],
  211. uom => "%"
  212. );
  213. }
  214. # create the message string
  215. if ( $$names[ $i ] =~ /^user/ or $$names[ $i ] =~ /^system/ or $$names[ $i ] =~ /^idle/ or $$names[ $i ] =~ /^iowait/ or $$names[ $i ] =~ /^steal/ )
  216. {
  217. $string .= sprintf( " (%s=%3.2f)", $$names[ $i ], $objects->{ percent }->{ $_ }->[ $i ] );
  218. }
  219. }
  220. $string .= ", ";
  221. }
  222. # strip the last two characters from string
  223. return ( $result, substr( $string, 0, -2 ) );
  224. }
  225. #-------------------------------------------------------------------------------
  226. # Main
  227. #-------------------------------------------------------------------------------
  228. my $objects = ();
  229. my $names = [];
  230. my $np = Nagios::Plugin->new(
  231. shortname => "Linux CPU Usage",
  232. usage => "Usage: %s < arguments > " .
  233. "arguments: \n" .
  234. " [ -t|--timeout=<timeout> ] timeout\n" .
  235. " [ -c|--critical=<threshold> ] critical threshold\n" .
  236. " [ -w|--warning=<threshold> ] warning threshold\n" .
  237. " [ -s|--statfile=<file> ] name of the stat file (default /proc/stat)\n" .
  238. " [ -g|--gapfile=<file> ] name of the gap file (default /tmp/check_cpu_usage.gap.tmp)\n" .
  239. " [ -n|--names=<list> ] comma separated list of names representing the column in the stats file\n" .
  240. " [ -d|--details ] show detailed information for each core\n",
  241. plugin => 'check_cpu_usage'
  242. );
  243. $np->add_arg(
  244. spec => 'warning|w=s',
  245. help => "--warning -w\n a list of threshold for warning in the same order as names\n" .
  246. " (default none,none,none,none,none,none,none,none,none,none,none,none,none,none)",
  247. default => "none,none,none,none,none,none,none,none,none,none,none,none,none,none",
  248. required => 0
  249. );
  250. $np->add_arg(
  251. spec => 'critical|c=s',
  252. help => "--critical -c\n a list of threshold for critical in the same order as names\n" .
  253. " (default none,none,none,none,none,none,none,none,none,none,none,none,none,none)",
  254. default => "none,none,none,none,none,none,none,none,none,none,none,none,none,none",
  255. required => 0
  256. );
  257. $np->add_arg(
  258. spec => 'statfile|s=s',
  259. help => "--statfile -s\n name of the stat file (default /proc/stat)",
  260. default => "/proc/stat",
  261. required => 0
  262. );
  263. $np->add_arg(
  264. spec => 'gapfile|g=s',
  265. help => "--gapfile -g\n name of the gap file (default /tmp/check_cpu_usage.gap.tmp)",
  266. default => "/tmp/check_cpu_usage.gap.tmp",
  267. required => 0
  268. );
  269. $np->add_arg(
  270. spec => 'details|d',
  271. help => "--details -d\n show detailed information for each core",
  272. required => 0
  273. );
  274. $np->add_arg(
  275. spec => 'names|n=s',
  276. help => "--names -n\n a comma separated list of names representing the column in the stats file. See 'man proc' for details\n" .
  277. " (default user,nice,system,idle,iowait,irq,softirq,steal,guest,guest_nice,nyd1,nyd2,nyd3)",
  278. default => "user,nice,system,idle,iowait,irq,softirq,steal,guest,guest_nice,nyd1,nyd2,nyd3",
  279. required => 0
  280. );
  281. # read the cli options
  282. $np->getopts;
  283. # rearange scalar lists into arrays
  284. $names = [ split( ',', $np->opts->names ) ];
  285. # read data from stats and store it to a hash
  286. $objects->{ newdata } = readStatFile( $np, $np->opts->statfile, $names );
  287. if ( -e $np->opts->gapfile )
  288. {
  289. # read data from stored file and store it to a hash
  290. $objects->{ olddata } = readStatFile( $np, $np->opts->gapfile, $names );
  291. # calculate difference and percent for the data
  292. $objects->{ percent } = processData( $np, $objects, $names );
  293. }
  294. # write the new data to the gapfile
  295. writeStatFile( $np, $objects, $names );
  296. print Dumper( $names, $objects ) if ( $np->opts->verbose );
  297. # compare data with warning and critical threshold and exit
  298. $np->nagios_exit( compareData( $np, $objects, $names ) );