Free disk Nagios plugin using python - nagios

IF there anyone can help me to modify the script below. I'm trying to use the Python script to check for
disk space alert on the filesystems, but as a right now the script ONLY check the root "/" filesystem. I would to check with the script all the filesystems available on the servers. This is for a nagios filesystem disk space and the script only check "df /". If any one can help into find the solution to this.
#!/usr/bin/python
import re,sys,commands
#################
#Set variables
command = "df /"
critical = 95.0
warning = 75.0
#################
#build regex
dfPattern = re.compile('[0-9]+')
#get disk utilization
diskUtil = commands.getstatusoutput(command)
#split out the util %
diskUtil = diskUtil[1].split()[11]
#look for a match. If no match exit and return an
#UNKNOWN (3) state to Nagios
matchobj = dfPattern.match(diskUtil)
if (matchobj):
diskUtil = eval(matchobj.group(0))
else:
print "STATE UNKNOWN"
sys.exit(3)
#Determine state to pass to Nagios
#CRITICAL = 2
#WARNING = 1
#OK = 0
if diskUtil >= critical:
print "FREE SPACE CRITICAL: '/' is %.2f%% full" % (float(diskUtil))
sys.exit(2)
elif diskUtil >= warning:
print "FREE SPACE WARNING: '/' is %.2f%% full" % (float(diskUtil))
sys.exit(1)
else:
print "FREE SPACE OK: '/' is %.2f%% full" % (float(diskUtil))
sys.exit(0)

Nagios already comes with a filesystem disk space check. My first recommendation would be to use it.
To answer your specific question, the script is running "df /", so you'll only get the results of that filesystem.
Why not run just "df", which will return you multiple rows, which you can then loop across?
You might also consider writing it in native python:
s = os.statvfs('/')
(s.f_bavail * s.f_frsize) / 1024

Your query returns the result for / because that is explicitly called out in the statement command="df /"
You could:
a) substitute a command line option for / in command="df /" that lets you pick the partition
b) make multiple versions that looked explicitly for different partitions /, /home, /var, etc.
c) use the nagios built in
d) write it in shell/awk, since you just want to evaluate the output from a shell command

Related

Cgi programming in C, calling system() from my cgi program.

I've had a CGI program that I wrote in C and have used for some 20 years, and for the first time in a long time, I'm running in Windows, specifically windows 10, and I can't get a system() call to execute from the CGI program. It seems like the system call is just ignored and doesn't create my output on the server side that I expect.
The CGI program is called from a form and using sprintf makes up the html page response into a giant buffer (szbuffer) and then prints to stdout which in the apache world goes back to the client. Here is the routine that outputs the built up html page to the user:
/** Print the CGI response header, required for all HTML output. **/
/** Note the extra \n, to send the blank line. **/
printf("Content-type: text/html\n\n") ;
printf("%s\n<!--JL 7/12/01 11:00am -->\n",szBuffer);
free ( szBuffer);
Now this has worked fine for years, but in this version I wanted to run some system calls to search a csv file and create an answer set to be read with an fopen(). The way I've done this in linux is to just run commands using the system() command:
getvaluecgivar(szcustomer_chain, "cust_field3", globals);
getvaluecgivar(szcustomer_id, "cust_field4", globals);
//sprintf(szdoscommand,"./awklookup_customer_id.bat %s %s "
sprintf(szdoscommand,"awklookup_customer_id.bat %s %s"
,szcustomer_chain
,szcustomer_id
);
system(szdoscommand);
system("cat lunch.trace >hw.lis");
system("cat lunch.trace >/temp/hwt.lis");
sprintf(szTempstring,"system command:%s: return code=%d\n"
,szdoscommand
,return_from_system_call
);
strcat(szBuffer, szTempstring);
} // then lookup by customer id
for reasons I need explaining and fixing, it appears as if the system() call (all three of them) never execute. The two "cat lunch.trace" system calls were just a test to see if I could get ANY system call to run and those commands also seem to fail. Now I know I've done this on Linux without any issue before:
FILE * tfile;
system( "cat /tmp/relaystatus20*.txt >/tmp/rs20all.txt");
tfile = fopen( "/tmp/rs20all.txt" , "r");
if (tfile) {
strcat(szBuffer, "<pre>");
while(!feof(tfile)) {
and this creates the file rs20all.txt in the /tmp directory.
Is there something special I have to do on Windows? I did capture the return code from the awklookup_customer_id.bat and it was 127.
Here is awklookup_customer_id.bat, it runs fine from either the dos prompt cmd.exe or a cygwin64 terminal:
call \jon\bat\local >t.lis
rem echo %1%, %2%
set arg1=%1%
set arg2=%2%
gawk -F',' '{ if($3==%arg1%) print $0 }' t5_clean_customer.csv >awk01.lis
gawk -F',' '{ if($4==%arg2%) print $0 }' awk01.lis >awk02.lis
\jon\bat\grep.exe -nf awk02.lis t5_clean_customer.csv >awk03.lis
cat awk03.lis|wc -l >awk03_c.lis
set LINE_COUNT=0
set /p LINE_COUNT=<awk03_c.lis
cut -d: -f1 awk03.lis >awk03_ln.lis
set LINE_NUMBER=0
set /p LINE_NUMBER=<awk03_ln.lis
SET /A Result = %LINE_COUNT% * 10000000 + %LINE_NUMBER%
echo number of lines that match :%LINE_COUNT% line number: %LINE_NUMBER%
rem pause
exit %Result%
I'm running Apache 2.4, here are the environment variables that the cgi program gets:
Print_environ::
[HTTP_HOST=localhost]
[HTTP_CONNECTION=keep-alive]
[CONTENT_LENGTH=380]
[HTTP_CACHE_CONTROL=max-age=0]
[HTTP_ORIGIN=http://localhost]
[HTTP_UPGRADE_INSECURE_REQUESTS=1]
[CONTENT_TYPE=application/x-www-form-urlencoded]
[HTTP_USER_AGENT=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36]
[HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8]
[HTTP_REFERER=http://localhost/cgi-bin/bf_customer.cgi]
[HTTP_ACCEPT_ENCODING=gzip, deflate, br]
[HTTP_ACCEPT_LANGUAGE=en-US,en;q=0.9]
[PATH=/cygdrive/c/Program Files (x86)/Common Files/Oracle/Java/javapath:/cygdrive/c/Program Files (x86)/Intel/iCLS Client:/cygdrive/c/Program Files/Intel/iCLS Client:/cygdrive/c/Windows/system32:/cygdrive/c/Windows:/cygdrive/c/Windows/System32/Wbem:/cygdrive/c/Windows/System32/WindowsPowerShell/v1.0:/cygdrive/c/Program Files (x86)/Intel/Intel(R) Management Engine Components/DAL:/cygdrive/c/Program Files/Intel/Intel(R) Management Engine Components/DAL:/cygdrive/c/Program Files (x86)/Intel/Intel(R) Management Engine Components/IPT:/cygdrive/c/Program Files/Intel/Intel(R) Management Engine Components/IPT:/cygdrive/c/Program Files (x86)/NVIDIA Corporation/PhysX/Common:/cygdrive/c/Windows/system32/config/systemprofile/.dnx/bin:/cygdrive/c/Program Files/Microsoft DNX/Dnvm:/cygdrive/c/Program Files (x86)/Windows Kits/8.1/Windows Performance Toolkit:/cygdrive/c/Program Files/Intel/WiFi/bin:/cygdrive/c/Program Files/Common Files/Intel/WirelessCommon:/cygdrive/c/Program Files (x86)/2Printer:/cygdrive/c/Program Files/MATLAB/MATLAB Runtime/v93/runtime/win64:/cygdrive/c/Program Files (x86)/Pico Technology/PicoScope6:/cygdrive/c/Program Files (x86)/IVI Foundation/VISA/WinNT/Bin:/cygdrive/c/Program Files/IVI Foundation/VISA/Win64/Bin:/cygdrive/c/Users/jleslie/AppData/Local/Microsoft/WindowsApps]
[SYSTEMROOT=C:\Windows]
[COMSPEC=C:\Windows\system32\cmd.exe]
[PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC]
[WINDIR=C:\Windows]
[SERVER_SIGNATURE=]
[SERVER_SOFTWARE=Apache/2.4.23 (Win64)]
[SERVER_NAME=localhost]
[SERVER_ADDR=::1]
[SERVER_PORT=80]
[REMOTE_ADDR=::1]
[DOCUMENT_ROOT=C:/jon/programs/Apache24/htdocs]
[REQUEST_SCHEME=http]
[CONTEXT_PREFIX=/cgi-bin/]
[CONTEXT_DOCUMENT_ROOT=c:/jon/programs/Apache24/cgi-bin/]
[SERVER_ADMIN=admin#example.com]
[SCRIPT_FILENAME=C:/jon/programs/Apache24/cgi-bin/bf_customer.cgi]
[REMOTE_PORT=52945]
[GATEWAY_INTERFACE=CGI/1.1]
[SERVER_PROTOCOL=HTTP/1.1]
[REQUEST_METHOD=POST]
[QUERY_STRING=]
[REQUEST_URI=/cgi-bin/bf_customer.cgi]
[SCRIPT_NAME=/cgi-bin/bf_customer.cgi]
[TERM=cygwin]
[HOME=/home/jleslie]
cgi vars:
[colora] = [maroon]
[cust_field1] = []
[cust_field2] = []
[cust_field3] = [0]
[cust_field4] = [16]
I figured it out. the answer has to do with httpd.conf. I needed to tell apache that its ok to run .bat file:
# (You will also need to add "ExecCGI" to the "Options" directive.)
#
#AddHandler cgi-script .cgi
AddHandler cgi-script .bat # add .exe if you wish
Options +ExecCGI +FollowSymlinks
sorry about the confusion with the return_from_system_call, I was adding and removing it so often I posted a version of the code where it wasn't set. This is the final code section that works:
getvaluecgivar(szcustomer_chain, "cust_field3", globals);
getvaluecgivar(szcustomer_id, "cust_field4", globals);
sprintf(szdoscommand,"awklookup_customer_id.bat %s %s"
,szcustomer_chain
,szcustomer_id
);
return_from_system_call =system(szdoscommand);
sprintf(szTempstring,"system command:%s: return code=%d\n"
,szdoscommand
,return_from_system_call
);
strcat(szBuffer, szTempstring);

libssh2 - channel read is hanging

I'm currently developing a remote job scheduler on perl.
It has to connect via ssh to x servers and execute already defined jobs/jobs groups.
I use Net:SSH2 which is build upon libssh2.
My program usually works fine with like 400/500 servers, but when i try to run the basic uptime command on 1000 servers, one or more of my threads hangs and never finishes, or like 30 minutes after.
It's random : sometimes it finishes on time, sometimes not.
I tracked the problem as coming from this Net::SSH2 command : $in .= $buf while $chan->read( $buf, 10240 );
Here is the full code of the connection :
my $chan = $this->{netssh2}->channel() or die $!;
$chan->blocking(1);
$chan->exec($command);
my ($in,$err,$buf,$buf_err);
$in .= $buf while $chan->read( $buf, 10240 );
$err .= $buf_err while $chan->read( $buf_err, 10240, 1 );
$chan->send_eof;
1 while !$chan->eof;
$chan->wait_closed;
I then downloaded a Net::SSH2 source package and modified the C-perl linking (xs) file.
It showed me that the problem comes from this line :
count = libssh2_channel_read_ex(ch->channel, XLATEXT, pv_buffer, size);
This command comes with the libssh2 library : http://www.libssh2.org/libssh2_channel_read_ex.html
Sometimes (about 1 in 1000 times) the program enters this read and never leaves. Servers affected are differents most of the time.
Do you have any idea what I should be looking for/checking ?
I've been working on this for a few day, I'd like an external advice very much :)

Python: how to run a command while using a defined variable?

I'm a beginner with Python and I'm trying to list the contents of a directory which is defined as a variable but to no avail.
This is the code:
#!/usr/bin/python
import os
location = "/home/itaig/testdir"
command = os.system('ls -l')," location"
My aim is to count the number of files in the location and print the number.
How can it be achieved?
Edit #1:
In bash I'd do ls -l $location | wc -l , what would be the equivalent in Python?
In any case, I've looked at the links from the comments but wasn't able to get it to work... can you please show me an example?
Thanks
You can use os.listdir.
This is platform independent as the os module will handle the low level work
print len(os.listdir(location))
You can use the good old os.popen function:
p = os.popen('ls -l %s' % location)
nb_lines = 0
while p.readline():
nb_lines += 1

while using google appengine request_logs, where it store the temp file?

While using the appcfg.py request_logs, it shows "copy the download logs to [the output file path]". Where would be the location google app engine used to store the temp file?
EDIT1
While using appcfg.py request_logs, I noticed that the first program will first download logs to a temp place then it copy these files to the user specify output file . I am looking for where the data stored before it has been copy to the target log file.
I'm not sure I've understood your question, but if you run a command like this from your app engine project directory (where your app.yaml file is):
appcfg.py request_logs . logs.out
then the output will end up in the file logs.out in that same directory (your project directory).
I found out GAE firstly using standard tempfile to store logs at first. Then it copy them to the desired output file location.
def DownloadLogs(self):
"""Download the requested logs.
This will write the logs to the file designated by
self.output_file, or to stdout if the filename is '-'.
Multiple roundtrips to the server may be made.
"""
StatusUpdate('Downloading request logs for %s %s.' %
(self.config.application, self.version_id))
tf = tempfile.TemporaryFile()
last_offset = None
try:
while True:
try:
new_offset = self.RequestLogLines(tf, last_offset)
if not new_offset or new_offset == last_offset:
break
last_offset = new_offset
except KeyboardInterrupt:
StatusUpdate('Keyboard interrupt; saving data downloaded so far.')
break
StatusUpdate('Copying request logs to %r.' % self.output_file)
if self.output_file == '-':
of = sys.stdout
else:
try:
of = open(self.output_file, self.write_mode)
except IOError, err:
StatusUpdate('Can\'t write %r: %s.' % (self.output_file, err))
sys.exit(1)
try:
line_count = CopyReversedLines(tf, of)
finally:
of.flush()
if of is not sys.stdout:
of.close()
finally:
tf.close()
StatusUpdate('Copied %d records.' % line_count)

How to save all console output to file in R?

I want to redirect all console text to a file. Here is what I tried:
> sink("test.log", type=c("output", "message"))
> a <- "a"
> a
> How come I do not see this in log
Error: unexpected symbol in "How come"
Here is what I got in test.log:
[1] "a"
Here is what I want in test.log:
> a <- "a"
> a
[1] "a"
> How come I do not see this in log
Error: unexpected symbol in "How come"
What am I doing wrong? Thanks!
You have to sink "output" and "message" separately (the sink function only looks at the first element of type)
Now if you want the input to be logged too, then put it in a script:
script.R
1:5 + 1:3 # prints and gives a warning
stop("foo") # an error
And at the prompt:
con <- file("test.log")
sink(con, append=TRUE)
sink(con, append=TRUE, type="message")
# This will echo all input and not truncate 150+ character lines...
source("script.R", echo=TRUE, max.deparse.length=10000)
# Restore output to console
sink()
sink(type="message")
# And look at the log...
cat(readLines("test.log"), sep="\n")
If you have access to a command line, you might prefer running your script from the command line with R CMD BATCH.
== begin contents of script.R ==
a <- "a"
a
How come I do not see this in log
== end contents of script.R ==
At the command prompt ("$" in many un*x variants, "C:>" in windows), run
$ R CMD BATCH script.R &
The trailing "&" is optional and runs the command in the background.
The default name of the log file has "out" appended to the extension, i.e., script.Rout
== begin contents of script.Rout ==
R version 3.1.0 (2014-04-10) -- "Spring Dance"
Copyright (C) 2014 The R Foundation for Statistical Computing
Platform: i686-pc-linux-gnu (32-bit)
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.
Natural language support but running in an English locale
R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.
Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.
[Previously saved workspace restored]
> a <- "a"
> a
[1] "a"
> How come I do not see this in log
Error: unexpected symbol in "How come"
Execution halted
== end contents of script.Rout ==
If you are able to use the bash shell, you can consider simply running the R code from within a bash script and piping the stdout and stderr streams to a file. Here is an example using a heredoc:
File: test.sh
#!/bin/bash
# this is a bash script
echo "Hello World, this is bash"
test1=$(echo "This is a test")
echo "Here is some R code:"
Rscript --slave --no-save --no-restore - "$test1" <<EOF
## R code
cat("\nHello World, this is R\n")
args <- commandArgs(TRUE)
bash_message<-args[1]
cat("\nThis is a message from bash:\n")
cat("\n",paste0(bash_message),"\n")
EOF
# end of script
Then when you run the script with both stderr and stdout piped to a log file:
$ chmod +x test.sh
$ ./test.sh
$ ./test.sh &>test.log
$ cat test.log
Hello World, this is bash
Here is some R code:
Hello World, this is R
This is a message from bash:
This is a test
Other things to look at for this would be to try simply pipping the stdout and stderr right from the R heredoc into a log file; I haven't tried this yet but it will probably work too.
You can't. At most you can save output with sink and input with savehistory separately. Or use external tool like script, screen or tmux.
Run R in emacs with ESS (Emacs Speaks Statistics) r-mode. I have one window open with my script and R code. Another has R running. Code is sent from the syntax window and evaluated. Commands, output, errors, and warnings all appear in the running R window session. At the end of some work period, I save all the output to a file. My own naming system is *.R for scripts and *.Rout for save output files.
Here's a screenshot with an example.
You can print to file and at the same time see progress having (or not) screen, while running a R script.
When not using screen, use R CMD BATCH yourscript.R & and step 4.
When using screen, in a terminal, start screen
screen
run your R script
R CMD BATCH yourscript.R
Go to another screen pressing CtrlA, then c
look at your output with (real-time):
tail -f yourscript.Rout
Switch among screens with CtrlA then n
To save text from the console: run the analysis and then choose (Windows) "File>Save to File".
Set your Rgui preferences for a large number of lines, then timestamp and save as file at suitable intervals.
If you want to get error messages saved in a file
zz <- file("Errors.txt", open="wt")
sink(zz, type="message")
the output will be:
Error in print(errr) : object 'errr' not found
Execution halted
This output will be saved in a file named Errors.txt
In case, you want printed values of console to a file you can use 'split' argument:
zz <- file("console.txt", open="wt")
sink(zz, split=TRUE)
print("cool")
print(errr)
output will be:
[1] "cool"
in console.txt file. So all your console output will be printed in a file named console.txt
This may not work for your needs, but one solution might be to run your code from within an Rmarkdown file. You could write both the code and console output to HTML/PDF/Word.

Resources