I there a way to return status message along with status code.
Here is an example in my python script how i return status code but not message:
def checkResults():
if not os.path.exists(jmeter_run_log) :
print "Status: Unknown. Error processing jmeter results file. Results file doesn't exist by % path." % jmeter_run_log
sys.exit(3);
numberOfFailures = 0
try:
fileHandler = open(jmeter_run_log, 'r')
#Check for failing requests
for line in fileHandler :
if line.split(jmeter_result_delimiter)[7] == "false":
numberOfFailures += 1
fileHandler.close()
except IOError, (errno, strerror):
print "Status: Critical. CRITICAL - reading jmeter results file failed with error: %s" %(strerror)
sys.exit(2)
if numberOfFailures > 0 :
print "Status: Critical. Number of failure requests = %s " % numberOfFailures
#sendNotificationEmail("Status: Critical. Number of failure requests = %s " % numberOfFailures)
sys.exit(2)
else:
print "Status: OK"
sys.exit(0)
I'm not sure exactly what you're asking. NRPE will already return both whatever you output to stdout as the return status message, and also sends along the exit code as the check result status. 0=OK, 1=WARN, 2=CRIT, 3=UNKNOWN.
So both your first example and code sample are already returning status strings along with status code. Am I missing something?
Related
I needed to write a solution to write data on and then print RFID labels en-masse, each generated as .png images from a template python script and data taken from a database or excel file.
To print the program simply calls the relative system utility (CUPS on unix systems) using subprocess.check_call(print_cmd) passing the image file (saved on a ram-mounted file system for minimal disk usage)
Now, it also needs to run on Windows systems, but there is not really a decent system utility for that, and solutions under a similar question command line tool for print picture? don't account for print-job completion or if the job results in an error, the margins are all screwed and the image is always rotated 90 degrees for some reason.
How can I sanely print an image using a command or a script in Windows and wait for it to complete successfully or return an error if the job results in an error?
Possibly with no dependencies
If you can install dependencies, there are many programs that offer a solution out-of-the-box.
The only sane way i could find to solve this issue with no dependencies is by creating a powershell script to account for this
[CmdletBinding()]
param (
[string] $file = $(throw "parameter is mandatory"),
[string] $printer = "EXACT PRINTER NAME HERE"
)
$ERR = "UserIntervention|Error|Jammed"
$status = (Get-Printer -Name $printer).PrinterStatus.ToString()
if ($status -match $ERR){ exit 1 }
# https://stackoverflow.com/a/20402656/17350905
# only sends the print job to the printer
rundll32 C:\Windows\System32\shimgvw.dll,ImageView_PrintTo $file $printer
# wait until printer is in printing status
do {
$status = (Get-Printer -Name $printer).PrinterStatus.ToString()
if ($status -match $ERR){ exit 1 }
Start-Sleep -Milliseconds 100
} until ( $status -eq "Printing" )
# wait until printing is done
do {
$status = (Get-Printer -Name $printer).PrinterStatus.ToString()
if ($status -match $ERR){ exit 1 }
Start-Sleep -Milliseconds 100
} until ( $status -eq "Normal" )
I would then need to slightly modify the print subprocess call to
powershell -File "path\to\print.ps1" "C:\absolute\path\to\file.png"
Then there are a couple of necessary setup steps:
(discaimer, I don't use windows in english so i don't know how the english thigs are supposed to be called. i will use cursive for those)
create an example image, right click and then select Print
from the print dialog that opens then set up all the default options you want, like orientation, margins, paper type, etc etc for the specific printer you're gonna use.
Go to printer settings, under tools then edit Printer Status Monitoring
edit monitoring frequency to "only during print jobs". it should be disabled by default
in the next tab, modify polling frequency to the minimum available, 100ms during print jobs (you can use a lower one for the while not printing option
Assuming the following:
only your program is running this script
theres always only 1 printing job at a time for a given printer
the printer drivers were not written by a monkey and they actually report the current, correct printer status
This little hack will allow to print an image from a command and await job completion, with error management; and uses only windows preinstalled software
Further optimization could be done by keeping powershell subprocess active and only passing it scripts in the & "path\to\print.ps1" "C:\absolute\path\to\file.png" format, waiting for standard output to report an OK or a KO; but only if mass printing is required.
Having had to work on this again, just wanted to add a simpler solution in "pure" python using the pywin32 package
import time
import subprocess
from typing import List
try:
import win32print as wprint
PRINTERS: List[str] = [p[2] for p in wprint.EnumPrinters(wprint.PRINTER_ENUM_LOCAL)]
PRINTER_DEFAULT = wprint.GetDefaultPrinter()
WIN32_SUPPORTED = True
except:
print("[!!] an error occured while retrieving printers")
# you could throw an exception or whatever
# bla bla do other stuff
if "WIN32_SUPPORTED" in globals():
__printImg_win32(file, printer_name)
def __printImg_win32(file: str, printer: str = ""):
if not printer:
printer = PRINTER_DEFAULT
# verify prerequisites here
# i still do prefer to print calling rundll32 directly,
# because of the default printer settings shenaningans
# and also because i've reliably used it to spool millions of jobs
subprocess.check_call(
[
"C:\\Windows\\System32\\rundll32",
"C:\\Windows\\System32\\shimgvw.dll,ImageView_PrintTo",
file,
printer,
]
)
__monitorJob_win32(printer)
pass
def __monitorJob_win32(printer: str, timeout=16.0):
p = wprint.OpenPrinter(printer)
# wait for job to be sheduled
t0 = time.time()
while (time.time()-t0) < timeout:
ptrr = wprint.GetPrinter(p, 2)
# unsure about those flags, but definitively not errors.
# it seems they are "moving paper forward"
if ptrr["Status"] != 0 and ptrr["Status"] not in [1024,1048576]:
raise Error("Printer is in error (status %d)!" % ptrr["Status"])
if ptrr["cJobs"] > 0:
break
time.sleep(0.1)
else:
raise Error("Printer timeout sheduling job!")
# await job completion
t0 = time.time()
while (time.time()-t0) < timeout:
ptrr = wprint.GetPrinter(p, 2)
if ptrr["Status"] != 0 and ptrr["Status"] not in [1024,1048576]:
raise Error("Printer is in error (status %d)!" % ptrr["Status"])
if ptrr["cJobs"] == 0 and ptrr["Status"] == 0:
break
time.sleep(0.1)
else:
raise Error("Printer timeout waiting for completion!")
wprint.ClosePrinter(p)
return
useful additional resources
Print image files using python
Catch events from printer in Windows
pywin32's win32print "documentation"
I dont have much experience with IDL but i need to fix a bug where in the compilation failure status needs to be returned to the calling script.
cat << ENDCAT > something.pro
PRINT, "Start"
PRINT, "Compiling functions needing early compile"
#do_early_func
PRINT, "Compiling remaining functions"
#do_other_func
PRINT, "Running: resolve_all"
resolve_all
EXIT
ENDCAT
setenv IDL_STARTUP something.pro
$IDL_DIR/bin/idl
The above content exists in a script called make_program which is called by another script called the build_script
The problem i am facing is that even if 'resolve_all' results in a compilation failure, the make_program always returns a true to the build_script making it think the compilation succeeded when it actually didnt. How can i return the failure status back to the calling script?
The EXIT routine has a STATUS keyword that can return the exit status of the script. So something like:
exit, status=status_code
To determine if RESOLVE_ALL completed correctly, you may need to do a CATCH block. The easiest way is probably to wrap RESOLVE_ALL in your own routine that has an ERROR keyword that returns whether the RESOLVE_ALL succeeded.
I'm not sure where I picked this up but you'll need two routines:
function validate_syntax_helper, routineName
compile_opt strictarr, hidden
catch, error
if (error ne 0) then return, 0
resolve_routine, routineName, /either, /compile_full_file
return, 1
end
and
function validate_syntax, routineName
compile_opt strictarr, hidden
oldquiet = !quiet
!quiet = 1
catch, error
if (error ne 0) then return, 0
; Get current directory
cd, current=pwd
o = obj_new('IDL_IDLBridge')
o->execute, '#' + pref_get('IDL_STARTUP')
; Change to current directory
o->execute, 'cd, ''' + pwd + ''''
; Validate syntax
cmd = 'result = validate_syntax_helper(''' + routineName + ''')'
o->execute, cmd
result = o->getVar('result')
obj_destroy, o
!quiet = oldquiet
return, result
end
You then call validate_syntax, which returns 1 when it can compile and 0 when it can't. I don't think this can be used from the IDL virtual machine since it uses execute, but maybe that doesn't matter to you. You'll have to manually run this on all your routines to be compiled instead of running resolve_all.
I've got an AutoIt script that goes to a website, logs in, and navigates to another page. But _IENavigate is throwing an error that isn't in the documentation . The output to the following code is: "Here is what the flag is: -1 and the error flag is: 0"
But you'll see in the documentation that only error codes 1-9 exist, there is no flag for #error = 0...
I do notice that the browser does navigate to the second page but when I try getting all the tags on the page, it doesn't find them. Please help! :)
Local $oIE = _IE
Create("http://www.example.com/")
_IELoadWait($oIE)
Local $j_username = _IEGetObjByName($oIE, "username")
_IEFormElementSetValue($j_username, $sUser)
Local $j_password = _IEGetObjByName($oIE, "password")
_IEFormElementSetValue($j_password, $sPass)
Local $login_submit = _IEGetObjByName($oIE, "button")
_IEAction($login_submit, "click")
_IELoadWait($oIE)
$iFlag = _IENavigate($oIE, "http://www.example.com/page2", 1)
ConsoleWrite( "Here is what the flag is: " & $iFlag & " and the error flag is: " & #error & #CRLF)
_IELoadWait($oIE)
Turns out the documentation says:
This function always returns a value of -1. This is because the navigate method has no useful return value and therefore nothing can be implied from it.
It's a feature, not a bug. :)
I created a bash script file:
#!/bin/bash
default_card=`head -1 /proc/asound/modules`
echo $default_card
if [ ! -e /etc/modprobe.d/sound.blacklist.conf ] ; then
echo "Default sound card(snd_hda_intel) is not added in black list"
/usr/bin/expect <<delim
exp_internal 0
set timeout 20
spawn sudo sh -c "echo 'blacklist snd_hda_intel' > /etc/modprobe.d/sound.blacklist.conf"
expect "password for ubuntu:"
send "1234\n"
expect eof
delim
else
echo "Default sound cardis already added in black list";
fi
I am creating a black list file in "/etc/modprobe.d". Creating or deleting any file from "/etc" requires sudo access.
I want to implement the same functionality in Ruby using a Rake task. I created the task as:
desc "Check/creates soundcard blacklist"
task :create_blacklist do
begin
if !File.exists?("/etc/modprobe.d/sound.blacklist.conf")
# code for creating new file and write into it
......
......
else
puts "Sound-card blacklist file is present at /etc/modprobe.d/sound.blacklist.conf"
end
rescue Exception => e
puts "problem creating file #{e.message}"
end
end
I don't know how to create new file using sudo, and write into it.
I am using Ruby 1.9.3 (without RVM).
Look at https://stackoverflow.com/a/18366155/128421, https://stackoverflow.com/a/18398804/128421, and "communicating w/ command-line program (OR ruby expect)" for more information.
Ruby's IO class implements expect but it's not too full-featured:
=== Implementation from IO
------------------------------------------------------------------------------
IO#expect(pattern,timeout=9999999) -> Array
IO#expect(pattern,timeout=9999999) { |result| ... } -> nil
------------------------------------------------------------------------------
Reads from the IO until the given pattern matches or the timeout is over.
It returns an array with the read buffer, followed by the matches. If a block
is given, the result is yielded to the block and returns nil.
When called without a block, it waits until the input that matches the given
pattern is obtained from the IO or the time specified as the timeout passes.
An array is returned when the pattern is obtained from the IO. The first
element of the array is the entire string obtained from the IO until the
pattern matches, followed by elements indicating which the pattern which
matched to the anchor in the regular expression.
The optional timeout parameter defines, in seconds, the total time to wait for
the pattern. If the timeout expires or eof is found, nil is returned or
yielded. However, the buffer in a timeout session is kept for the next expect
call. The default timeout is 9999999 seconds.
I use the Spyder IDE. Usually, when I am running non-parallelized scripts, I tend to debug using print statements. Depending on which statements are printed (or not), I can see where errors are occurring.
For example:
print "Started while loop..."
doWhileLoop = False
while doWhileLoop == True:
print "Doing something important!"
time.sleep(5)
print "Finished while loop..."
Above, I am missing a line that changes doWhileLoop to False at some point, so I will be stuck perpetually in the while loop, but my print statements let me see where it is in my code that I have hung up.
However, when running scripts that are parallelized, I get no output to the console until after the process has finished. Normally, what I do in this case is attempt to debug with a single process (i.e. temporarily deparallelize the program by running only one task, for instance), but currently, I am dealing with an error that seems to occur only when I am running more than one task.
So, I am having trouble figuring out what this error is using my usual methods -- how should I change my usual debugging practice in order to efficiently debug scripts employing multiprocessing?
Like #roippi said, debugging parallel things is hard. Another tool is using logging over print. Logging gives you severity, timestamps, and most importantly which process is doing something.
Example code:
import logging, multiprocessing, Queue
def myproc(arg):
return arg*2
def worker(inqueue, outqueue):
mylog = multiprocessing.get_logger()
mylog.info('start')
for job in iter(inqueue.get, 'STOP'):
mylog.info('got %s', job)
try:
outqueue.put( myproc(job), timeout=1 )
except Queue.Full:
mylog.error('queue full!')
mylog.info('done')
def executive(inqueue):
total = 0
mylog = multiprocessing.get_logger()
for num in iter(inqueue.get, 'STOP'):
total += num
mylog.info('got {}\ttotal{}', job, total)
logger = multiprocessing.log_to_stderr(
level=logging.INFO,
)
logger.info('setup')
inqueue, outqueue = multiprocessing.Queue(), multiprocessing.Queue()
if 0: # debug 'queue full!' issues
outqueue = multiprocessing.Queue(maxsize=1)
# prefill with 3 jobs
for num in range(3):
inqueue.put(num)
# signal end of jobs
inqueue.put('STOP')
worker_p = multiprocessing.Process(
target=worker, args=(inqueue, outqueue),
name='worker',
)
worker_p.start()
worker_p.join()
logger.info('done')
Example output:
[INFO/MainProcess] setup
[INFO/worker] child process calling self.run()
[INFO/worker] start
[INFO/worker] got 0
[INFO/worker] got 1
[INFO/worker] got 2
[INFO/worker] done
[INFO/worker] process shutting down
[INFO/worker] process exiting with exitcode 0
[INFO/MainProcess] done
[INFO/MainProcess] process shutting down