perl program to handle return of batch file - perl

i am trying to run a batch file from a perl script but i am not able to handle the return of a batch file. below is my code
perl script:
// call a batch file
my $output =system("D:\\WORKSPACE\\CC_Triggers\\batch_file.bat");
// based on output check the status of the batch file
if($output==0){
print "success in trigger**********";
}
else
{
print "FAilure**********";
}
batch file:
set "java_output="
setlocal enableDelayedExpansion
//this will call a java program and get return value.
for /f "delims=" %%J in ('java -cp "PMDfileRead.jar;jxl.jar" PMDfileRead') do (
set "java_output=!java_output! %%J"
)
endlocal & set java_output=%java_output%
// check the ouput of java and act accordingly
IF %java_output% == 1 (
echo failed
exit(1);
)else (
echo succeeded
)
basically i am trying to validate an xls file and return flag from java code which is being called by a batch file and from ther i need to return back to perl script which i am not able to get. in case of success and failure, i am getting as "0" as output due to which output is success.. request to please correct my code or suggest me the best way to handle this.

edit: Sorry i somehow read past the comment by mpapec stating the same thing.
The Perl part is fine. If you always get a 0, it has to be the batch script acting up. Or the Java.
If you want to inspect the return value in Perl for anything except whether it is zero or not, then you would have to shift it right 8 bits.
my $output = (system("D:\\WORKSPACE\\CC_Triggers\\batch_file.bat")) >> 8;
But as you only check for zero or not, that should not be an issue here.
edit:
When using Windows, it is important to never define an environment variable ERRORLEVEL as that will mix up with the actual exit codes returned by applications. This is explained in more detail here: How do I get the application exit code from a Windows command line?

Replace your system() call with backticks instead:
A system() wrapped call returns the exit status of the command, whereas using ``'s returns the actual STDOUT (i.e. your echo statements)
For more info:
What's the difference between Perl's backticks, system, and exec?
i.e.:
my $output = `D:\WORKSPACE\CC_Triggers\batch_file.bat`;

Related

How to pass integers and strings from MATLAB to a PowerShell script?

I need to automate a test. The test itself is being written (by me) in MATLAB, has 5 stages, each stage ends with setting a value to an integer (uint16_t and uint8_t) and with a message. I have to pass these 5 integers and 5 strings to a PowerShell script because Jenkins can only run a PowerShell or Python script, but I'm not entirely sure how can I achieve that. I have never used PS or done any scripting, and there isn't much on the Internet on how to even run a MATLAB script with PowerShell. (Maybe I should check batch file scripts running MATLAB scripts.)
The only option I've found so far is writing into a (temporary) file with MATLAB, then reading from it (and deleting it), it could be a .txt file, or preferably a .csv file (although using csvwrite is not recommended by Mathworks), but this isn't very reliable. Can anyone suggest other methods to pass it more directly? The MATLAB file is not a function, but it can be made to be one that has these variables as outputs. Also, it's fine if the integers are cast to another integer type.
Like #TessellatingHeckler said the way is $results = matlab.exe yourscript.
Here is an example if you want more features when launch the tests like no display windows ,run in a batch mode or wait to the end of matlab execution.
runTestMatlab (){
result=$(matlab.exe -wait -nosplash -noFigureWindows -batch TestScript.m)
if [ $? -ne 0 ]; then
# Error with the Matlab run
echo $result
return 1
fi
echo "$result"
return 0
}
Then you can parse the result with awk or any other tool that you want.

Suppress output to stderr in matlab

I'm trying to suppress output from a code section in a script (namely the network initialization from a Caffe network). I've tried wrapping the corresponding bit of code in an evalc command
[suppressed_output, var_output] = evalc('someFunction(input)');
But this doesn't work. I've still got loads of lines of (non-error) output from the network initialization that are clogging my logs (amidst all the wanted output printed via fprintf('') in the script). I think this happens because the corresponding function is writing to STDERR (instead of STDOUT?) - the first line it prints is this warning:
WARNING: Logging before InitGoogleLogging() is written to STDERR
... and then hundreds of lines of what it is doing follow, e.g.:
I0215 15:01:51.840272 28620 upgrade_proto.cpp:66] Attempting to upgrade input file specified using deprecated input fields: tmp-def.prototxt
I0215 15:01:51.840360 28620 upgrade_proto.cpp:69] Successfully upgraded file specified using deprecated input fields.
...
Can I somehow suppress the output to STDERR (without messing with the function content)? Ideally only locally for this specific function, since I'd still like to get potential error messages.
In case it is relevant:
I call myScript via matlab command line and its output written to a log (mlexec.log) with tee:
matlab -nodesktop -nosplash -display :1 -r "try, myScript; catch e, disp(getReport(e)), end, quit force" 2>&1| tee mlexec.log
The problem here is, that in the matlab command line call, the output from STDERR is streamed to STDOUT by this "command": 2>&1. Since the .cpp file seems to stream its output to STDERR (according to the Warning), it will be forwarded to STDOUT and eventually the log.
Streaming STDERR (2) to Nirvana with 2>NUL or a different log file (e.g. 2>mlexec.stderr.log) solves the problem.
I wanted to post this in a comment but it said I had to have 50 reputation (I have 49 now...)
I think this is what you're looking for
EDIT/UPDATE:
One thing you can do is enclose a section of your code with warning on/off statements as follows:
warning('off','all')
%your code here
warning('on','all')
This should stop any warnings being output to stderr from that section. I personally do not recommend this, it's good to know what you're doing that the MATLAB runtime does not like.

batch file call errorlevel twice

I am struggling at a batch file errorlevel return issue, and could not find the answer.
Could any one give me any hints?
I have an external binary file, external.exe which read the return code (0-success, other-fail) of a batch file to decide what to do.
Within the batch file, mybatch.cmd, I wanted to run a script (perl) and return the result to the batch file.
For example, mybatch.cmd:
#echo off
myperl.pl
exit %errorlevel%
While myperl.pl is:
#!perl.exe
exit 0;
So I wanted myperl.pl to return value 0 to the batch file, and then the batch file return 0 to the external.exe file.
But external.exe didn't work as expected.
1) If I run mybatch.cmd from CLI, and then "echo %errorlevel%" from CLI, I could see it is 0.
2) If I add a line to display the return code from myperl.pl, I could see the return code from myperl.pl is exactly 0.
For example:
#echo off
myperl.pl
echo %errorlevel%
REM exit %errorlevel%
It will display 0, so the perl script returns the value exactly.
3) If I add a line to manually set the return code to 0, the external.exe works fine.
#echo off
myperl.pl
result=0
exit %result%
That is really weird. Any ideas? I could not control the external.exe, so I could not do debug on it.
In this example, the %errorlevel% is called twice:
1) Return from myperl.pl to batch.
2) Return from mybatch.cmd to external.exe. Will that be an issue?
All you have said is right: myperl.pl return a certain errorlevel, the Batch file take it and then it returns the appropriate errorlevel value. The problem is this: the Batch file, to what process return its errorlevel?
This scheme always works as a parent-children relation: a parent process execute a children one and waits for it to terminate, then the parent may take the errorlevel value returned by the children. The way to solve your problem is if the external.exe program execute the Batch file (cmd.exe) as a children! However, if you "could not control the external.exe", then there is no way to solve your problem...
How do you know that the external.exe program "read the return code (0-success, other-fail) of a batch file to decide what to do"? I think you have a confusion at this point.
Found out the root cause finally.
myperl.pl should be with fullpath, otherwise the external.exe didn't know where the myperl.pl was.

CMD - If exists <file>

The below commands (with debug lines added - indented) should only redirect the echo's output to a file, should it already exist, according to my understanding.
However, it would seem that if exist %test0% always fills the file (creating it if non-existant) with the echo's output.
Does anyone know what is wrong?
#echo off
type test.bat
set test0="e:\documents and settings\administrator\desktop\test.log"
echo.&echo.
if exist %test0% (echo !!Exists!!) else (echo !!Doesn't Exist!!)
(if exist %test0% echo.&echo.&echo -------------------------------------------------&echo.&echo.)>>%test0%
And the file gets created(!)
EDIT: This above was a simplified example, and unfortunately MSalters answer doesn't help me solve the full command (I had hoped it would). The full one line if statement is:
if exist %test0% (echo.&echo.&echo -------------------------------------------------&echo.&echo.) else (set /p .=<nul)>>%test0%&set errorlevel=0||set errorlevel=1
How would I have whichever condition of the if matched output to the file (Hopefully with only one reference to the file, i.e., not one in each if conditional), and have the errorlevel set based on the existance of the file?
Could anyone help with the actual full command issue?
You should never set ERRORLEVEL directly. That name is reserved for reporting on the results of the prior command. When you set the value directly, you override the intended functionality and it ceases to expand to the actual ERRORLEVEL, it expands to the value you set instead. That can break all kinds of code.
You can force the ERRORLEVEL to a value by running a command with known result, redirecting output to nul if necessary: ver >nul sets ERRORLEVEL to 0, set /p .=<nul sets ERRORLEVEL to 1.
You can force the ERRORLEVEL to any particular value of your choosing by using cmd /c exit /b N, where N is an integral value.
You also have faulty logic. Your IF command succeeds (has no error) regardless whether the condition evaluates to TRUE or FALSE. If you want to set the ERRORLEVEL, then you need to do it within your parenthesized blocks.
There is nothing wrong with putting everything on one line, but I find the code easier to read when using multiple lines for complex statements like yours. I believe the following is what you are looking for.
if exist %test0% (
echo.
echo.
echo -------------------------------------------------
echo.
echo.
ver >nul
) >>%test0% else (
set /p .=<nul
)
Edit in response to comments
Not much change needed.
if exist %test0% (
(
echo.
echo.
echo -------------------------------------------------
echo.
echo.
set ERR=0
) >>%test0%
) else (
copy nul %test0%
set ERR=1
)
Check your parentheses. (x) >> output.log redirects the output of x to output.log. That means the redirection happens regardless of what the output is, and in particular always creates the file.
Now if you'd write if Y (echo Text >> output.log) the redirection would be conditional on Y, and might not happen.
[edit]
With the question as it's worded now, the simple solution seems to be:
Set %ERRORLEVEL% based on exist %test0%. No redirection has happened at this point.
Use %ERRORLEVEL% to determine what to do. You can change %test0% without altering %ERRORLEVEL%.
BTW, ERRORLEVEL is not %ERRORLEVEL%

running external process from scala using sbt ! operator under Windows

I have the following two lines in my scala program
val success:Int = ("d:\\program.bat" !)
println("started "+success)
program.bat looks like this
#echo off
start "" "d:\notepad.exe"
echo DONE
the program actually starts tomcat server, but it is all the same for firefox, notepad etc... so I simplified this to notepad.exe
I would like to start notepad and see "started 0".
The problem is that the code stops at the first line and doesnt print "started 0" until I close notepad
The last line of the program.bat is
echo DONE
and DONE is the last thing printed out before the execution stops (so I assume it doesnt stop inside program.bat).
I tried putting EXIT /B 0 at the end of my program.bat script but it doesn't change anything.
I heard it works fine under linux (using program.sh of course).
Any suggestions how to REALLY detach the notepad from program.bat and return 0?
This behaviour is to be expected, because the ! operator returns the exit code of the invoked program - which implies, that the program has to terminate before the exit code can be returned. Quoting an example from the process docs:
import scala.sys.process._
// This uses ! to get the exit code
def fileExists(name: String) = Seq("test", "-f", name).! == 0
// This uses !! to get the whole result as a string
val dirContents = "ls".!!
// This "fire-and-forgets" the method, which can be lazily read through
// a Stream[String]
def sourceFilesAt(baseDir: String): Stream[String] = {
val cmd = Seq("find", baseDir, "-name", "*.scala", "-type", "f")
cmd.lines
}
If you are interested in the exit code but want your Scala program to make progress in the mean time, for example, print the output of the invoked program, you could use ProcessBuilder.hasExitValue to find out when the exit code is available.