I have to print a PDF file in java program and make sure it's printed successfully, else throw exception.
My Code is:
Process p = Runtime.getRuntime().exec("lp -c -n 1 -d 1.2.3.4 abc.pdf");
System.out.println(p.waitFor());
Above code prints 0, but it only confirms that job is submitted fine, how to make sure that it's printed also.
Is there any other way to do this?
Run lpstat (after lp) and capture the process output.
Related
I working on a python 3 script for doing some bench (school purpose). So I need to invoke my JAR.
I use subprocess.check_output for that.
java_out = subprocess.check_output("java -jar my_jar.jar -p input_file", shell=True)
In terminal it works fine, I get the expected output and exit code is 0.
But in python, I get this :
Syntax error. (One of my java exception, but it might not happen in this case)
Traceback (most recent call last):
File "C:/Users/Jeremy/PycharmProjects/bench_bf/bench_script.py", line 41, in <module>
main()
File "C:/Users/Jeremy/PycharmProjects/bench_bf/bench_script.py", line 32, in main
result_list.append(bench(bf_file, stats_file))
File "C:/Users/Jeremy/PycharmProjects/bench_bf/bench_script.py", line 10, in bench
java_out = subprocess.check_output("java -jar my_jar.jar -p input_file", shell=True)
File "C:\Python34\lib\subprocess.py", line 620, in check_output
raise CalledProcessError(retcode, process.args, output=output)
subprocess.CalledProcessError: Command 'java -jar my_jar.jar -p input_file' returned non-zero exit status 5
Process finished with exit code 1
That does not make any sense to me. Can anyone help me ? Thanks !
The full code is following (I've also tried with absolute path) :)
import subprocess
import os
import re
FILE_NAME = "input_file"
JAR_NAME = "my_jar.jar"
TEST_ITER = 5
def bench(bf_file, stats_file):
java_out = subprocess.check_output("java -jar "+ JAR_NAME + " -p " + FILE_NAME, shell=True)
print(java_out)
m = re.search(".*EXEC_TIME : (\d*) ms.*EXEC_MOVE : (\d*)", java_out)
return [m.group(0), m.group(1)]
def init_stats(f):
f.write("Iterations; Exec time; exec move")
def write_file(f):
f.write("+++")
def main():
bf_file = open(FILE_NAME, "w", encoding="utf-8")
stats_file = open("bench-result.csv", "w")
write_file(bf_file)
init_stats(stats_file);
result_list = []
for i in range(0,TEST_ITER):
result_list.append(bench(bf_file, stats_file))
average_time = 0;
for res in result_list:
average_time += res[0]
average_time /= TEST_ITER;
stats_file.write(average_time + ";" + result_list[0][1])
main()
EDIT: I also tried java_out = subprocess.check_output(["java", "-jar", "my_jar.jar", "-p", "input_file"], shell=True), it changes nothing.
EDIT 2: Same result using absolute path or os.system
* SOLUTION *
Since I open the file in write mode, my JAR can't open it, and consider it's empty... Thanks my mate DjNikita :)
My first thought would be that there is something in your environment that is not transferring to the subprocess. Try this and see if it outputs anything that looks relevant
import os
for key in os.environ:
if any(token in key.lower() for token in ['java', 'jre', 'jdk']):
print(key, os.environ[key])
I've had another thought too. Some programs expect their input to be a tty (ie. interactive terminal) and get angry when they're fed in a pipe. Is there anything in your Java program that might cause it to expect a certain type of input stream?
Try specifying the absolute path of the jar file, as it might be that your sub-process isn't running the directory you think it is.
Try running 'dir' and seeing where it returns, for instance. Maybe check that 'java --V' (the version flag? not in a position to check at the moment) returns something indicating that Java ran, rather than an error. Basically, try and get a simple thing running via Python, then extend it.
C code
#include <stdio.h>
int main() {
printf("Expected to print");
int a = 1/0;
return 0;
}
compile it using
gcc Test.c
From java running
p = Runtime.getRuntime().exec(cmd);
here cmd is [/bin/bash, -c, ./a.out]
and then i capture the errorStream of the process p.getErrorStream()
but errorStream does not have the Floating point exception in it which we get if we run
./a.out
from console
Floating point exception isn't printed from the program but by bash. If you interactively start the program and the program got the FPE bash prints the FPE message.
With bash -c a.out bash just calls one of the exec() functions without calling fork() before and thus is directly replaced by a.out hence it can't print out anything.
I get Floating point exception (core dumped) in the Java error stream if I use Runtime.getRuntime().exec(new String[]{"/bin/bash","-i","-c","echo -n;./a.out"});.
With the echo -n,which does nothing, bash is forced to stay alive and so can print out the FPE message. The -i sets the bash to interactive mode.
I'm trying to read exit value from external program but it's always 0.
String command = ("cmd /c start /wait "+ Script[0]);
Process exec = runtime.exec(command);
int waitFor = exec.waitFor();
System.out.println(exec.exitValue); //always 0
System.out.println(waitFor); //always 0
Program is used for programming modules and I need to know if there were any error's.
How to get the application exit value?
The program you're actually running is the cmd program, not whatever you're running under that.
See How do I get the application exit code from a Windows command line? for how to extract the underlying exit code.
I have a perl CGI that calls a java application which in turn checks a Mysql database. If I search for an entry that does not exist, the java application displays an exception handler message on the server (requires an X display window). The exception is straight forward and understandable, however must be clicked to close it, at which point the perl CGI can continue. Customers of course cannot (and should not) see the exception message.
My question is.. how can I prevent the exception message from displaying on the server window and preventing the CGI from continuing? Is there a way to close the message from perl? I have control over the perl script, but not the java application I call.
$ENV{'DISPLAY'} = 'myserver:0.0';
$testline = system("java -Dby.product=true -jar javaApp.jar $version status>mytest.txt") >> 8;
if $version doesn't exist, I get the exception.
I pipe the results to a file for later file handling in perl
Thanks.
Rocky.
=====================
Thanks.
I added this...
$ENV{'DISPLAY'} = 'server:0.0';
use IPC::Open2;
use POSIX ":sys_wait_h";
$pid = open2(\*CHLD_OUT, \*CHLD_IN, "java -Dby.product=true -jar javaApp.jar $version status>mytest.txt 2>/tmp/java_error.$$");
sleep(5);
kill('TERM', $pid);
If I use a known value in the database, it works fine, as before.
If I search a nonexistent value, the java message still pops up.
Without the sleep line, the java message does NOT popup. In other words it looks like the pid is killed, but so quickly that the result does not get fed into mytest.txt. I thought the sleep function would give some time for the java app to work and then the kill would remove the popup message. But this does not happen.
It seems likely I will have to request changes to the java application so that it does not display a message on screen in the server.
Corrected and extended
Try
system("java -Dby.product=true -jar javaApp.jar $version status 2>/dev/null >mytest.txt");
It redirects the stderr of java to nowhere. Or redirect to a file (like 2>/tmp/java_error.$$) to save it debugging the error.
If it is on windows use 2>nul.
Or use IPC::Open3 and process both input file handles as You like.
More detailed. I created a simple a.java code which writes to stdout, stderr and throws an exception if an arg is defined:
public class a {
public static void main(String[] args) {
System.out.println("STDOUT");
System.err.println("STDERR");
if (args.length > 0) { int i = 1/0; }
}
};
I compiled and run it (don't care about the gcj warning):
$ gcj -C a.java
$ gij -cp . a
STDOUT
STDERR
$ gij -cp . a x
STDOUT
STDERR
Exception in thread "main" java.lang.ArithmeticException: / by zero
at a.main(a.java:5)
$ gij -cp . a >/dev/null
STDERR
$ gij -cp . a x 2>/dev/null
STDOUT
So the stack dump is written to the stderr as expected, so it can be redirected.
$ perl -e 'system("gij -cp . a x 2>/dev/null")'
STDOUT
The example program with IPC::Open3:
#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open3 'open3';
use Symbol 'gensym';
my ($fcin, $fcout, $fcerr);
$fcerr = gensym;
my $pid = open3 $fcin, $fcout, $fcerr, "gij -cp . a x";
my #out = <$fcout>;
my #err = <$fcerr>;
my $err = waitpid $pid, 0;
print "Exit:", ($err >> 8), "\n";
print "OUT: #out\n";
print "ERR: #err\n";
Output:
Exit:72
OUT: STDOUT
ERR: STDERR
Exception in thread "main" java.lang.ArithmeticException: / by zero
at a.main(a.java:5)
Even the man page of IPC::Open3 suggests to use the IPC::Run package. I tried, but it is not the part of the normal distribution. So You can install it from CPAN if You wish.
I have a java program which is supposed to launch a shell script. The script contains 6 tasks which are to be executed in sequence. The java program launches the script and it starts(as I see the logs). But after 10-15 seconds, the execution stops, even before the first task in the shell script is completed. The strange thing is that the script runs fine when I launch it in terminal. To avoid risking the program to hang while the script is being executed, I launch it in a separate thread. What might be a probable reason?
Java code -
try {
log.info("run cmd - "+optionsRun);
String[] cmdLine = (String[]) optionsRun.toArray(new String[optionsRun.size()]);
Process process = Runtime.getRuntime().exec(cmdLine);
log.info("end run cmd " + this.getScriptPath());
//
// BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
// writer.write("mypwd");
// writer.flush();
// writer.close();
InputStream is = process.getErrorStream();
String error = inputStreamToStringValue(is);
log.trace("Eventual error was : " + error);
InputStream os = process.getInputStream();
String output = inputStreamToStringValue(os);
log.info("Eventual output was : " + output);
if (error!=null & error.length()>0) {
throw new ActionProcessingException("An error occurred when running the script :'"+this.getScriptPath()+"' with following error message : "+error);
}else {
log.info("Script run ended successfully.");
}
And the shell script looks this way -
#!/bin/sh
# ./publish <path-to-publish-home-folder> <workspace_id> <start_date> <end_date>
# ./publish <path-to-publish-home-folder> 100011 2010-01-06-12:00:00-CET 2012-01-14-19:00:00-CET
rm -f $1/publish.log
echo 'Start publish' >> $1/publish.log
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 >> $1/publish.log
# lancement de l'export RDF du domaine
cd $1/1-export-domain
echo "Starting export domain with the command - ./export.sh $2" >> $1/publish.log
./export.sh $2
# lancement de l'export des translations du domaine
cd $1/2-export-trans
echo "Starting export domain(translated) with the command - ./export.sh $2" >> $1/publish.log
./export.sh $2
.....
.....
a couple of more steps like 1 and 2
....
Thanks in advance,
I'm not sure, but I'll recommend two links that might help you figure it out.
The first is a very old one about Runtime.exec():
http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
The second is about ProcessBuilder, the new class intended to replace Runtime.exec():
http://www.java-tips.org/java-se-tips/java.util/from-runtime.exec-to-processbuilder.html
I cannot be sure I my guess is that the problem is in your method inputStreamToStringValue(is). It reads STDERR and it is blocking on read. When it has nothing to read from STDERR but the process is not terminated yet you will be blocked forever.
I'd recommend you to use ProcessBuilder:
ProcessBuilder b = new ProcessBuilder();
b.redirectErrorStream(true);
Now you can read STDIN and STDERR together.
If you still want to read them separately you have 2 solutions.
First do as you are doing now but do not be block on read, i.e. call in.available() before each call of read and then read only number of bytes that were previously available.
Second way is to use the shell redirection. Run you script and redirect its STDOUT and STDERR to temporary files. Then wait until your process terminates and then read from files. I personally think that this solution is easier and more robust.
Good luck.