Unable to communicate from a python script with java program.
I have a java program that reads from standard input.
Logic is:
public static void main(String[] args) {
...
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String cmd;
boolean salir = faslse
while (!salir) {
cmd = in.readLine();
JOptionPane.showMessageDialog(null, "run: " + cmd);
//execute cmd
...
System.out.println(result);
System.out.flush();
}
}
I run the program through the console console
java -cp MyProgram.jar package.MyMainClass
And execute commands and get results, and shows the command executed in a dialogue (JOptionPane.showMessageDialog(null, "run: " + cmd); )
I need to call the program from python.
Right now I'm trying with this:
#!/usr/bin/python
import subprocess
p = subprocess.Popen("java -cp MyProgram.jar package.MyMainClass", shell=True, stdout=subprocess.PIPE , stdin=subprocess.PIPE)
print '1- create ok'
p.stdin.write('comand parameter1 parameter2')
print '2- writeComand ok'
p.stdin.flush()
print '3- flush ok'
result = p.stdout.readline() # this line spoils the script
print '4- readline ok'
print result
p.stdin.close()
p.stdout.close()
print 'end'
And the output is
1- create ok
2- writeComand ok
3- flush ok
And does not show the dialog.
however if I run:
#!/usr/bin/python
import subprocess
p = subprocess.Popen("java -cp MyProgram.jar package.MyMainClass", shell=True, stdout=subprocess.PIPE , stdin=subprocess.PIPE)
print '1- create ok'
p.stdin.write('comand parameter1 parameter2')
print '2- writeComand ok'
p.stdin.flush()
print '3- flush ok'
p.stdin.close()
p.stdout.close()
print 'end'
the output is
1- create ok
2- writeComand ok
3- flush ok
end
and show show the dialog.
the line p.stdout.readline() spoils the script, as I can fix this?
Thank you very much any help.
Flush your System.out after printing just one result.
Additionally change your code to do this:
p = subprocess.Popen("java -cp MyProgram.jar package.MyMainClass",
shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
p.stdin.write(command1)
p.stdin.flush() # this should trigger the processing in the Java process
result = p.stdout.readline() # this only proceeds if the Java process flushes
p.stdin.write(command2)
p.stdin.flush()
result = p.stdout.readline()
# and afterwards:
p.stdin.close()
p.stdout.close()
Related
I have created the shell script to add two numbers. I want to execute that shell script from java. Can you please help me on this.
first_num=0
second_num=0
echo -n "Enter the first number-->"
read first_num
echo -n "Enter the second number-->"
read second_num
echo "first number + second number = $ (( first_num + second_num ))"
And I need a piece of code based on the "jsch" library
you can do it by getting the runtime, as next
Process p = null;
Runtime rt = Runtime.getRuntime ();
String rutaFinal=path+carpeta+"/";
System.out.println("** Executing command *****");
p = rt.exec("chmod x process.sh");
p = rt.exec ("sh process.sh");
p.waitFor();
Also you can execute commands one by one, hope this help!!!
I have a strange behavior when calling a perl script from Java.
The perl code is:
#!/usr/bin/env perl
use warnings;
print "dada\n";
$file = "settings.txt";
open $ds, "<", $file;
print "doudou\n";
while ($line = <$ds>){
print "$line\n";
last if $. == 4;
}
print "dodo\n";
close $ds;
As you can see, in this code I want to read the file "settings.txt" which contents :
1 : a
2 : b
3 : c
4 : d
And this script works when called from cygwin and the output is :
dada
doudou
1 : a
2 : b
3 : c
4 : d
dodo
But when I call it from Java using the following code:
String line;
String cmd = "perl C:\\Data\\Tests\\match_settings.pl";
try {
Process proc = Runtime.getRuntime().exec(cmd);
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
while ((line = in.readLine()) != null) {
System.out.println("Line :" + line);
}
in.close();
} catch (IOException a) {
// TODO Auto-generated catch block
a.printStackTrace();
}
Then when the Java function is executed, I get the output:
Line :dada
Line :doudou
Line :dodo
Which means that $line = <$ds> is not well executed, but I don't know why.
Any idea ?
Sorry for the long post, wanted to be as precise as possible.
PS : I know some of you are wondering "Why not read the settings.txt file by Java code himself ?" but that's not the question here ;)
It seems that the folder from which your perl code is executed is not the same when executing from Cygwin and Java. So the perl Script can't find your file.
You should add error checking in your perl code, and verify your current working dir directory.
I would write:
#!/usr/bin/env perl
use warnings;
use Cwd;
my $cwd = cwd();
print "dada\n";
print "In folder: $cwd";
$file = "settings.txt";
open ($ds, "<", $file) || die "Can't open settings.txt. Error code: $!";
print "doudou\n";
while ($line = <$ds>){
print "$line\n";
last if $. == 4;
}
print "dodo\n";
close $ds;
This will help you debug why, when your script is executed from Java, you don't get the expected results.
You should also redirect stderr to stdout in your Java code, so you will get error lines.
I'm attempting to execute jstack command using Runtime.exec but it seems there is an error but I can't find it out.
In addition, I can execute the following command in CMD and it works fine:
C:\Users\bob>"C:\Program Files\Java\jdk1.6.0_18\bin\jstack" 5540 > d:\s.log
Test class full text:
package test;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args) {
try {
Process process = Runtime.getRuntime().exec("\"C:\\Program Files\\Java\\jdk1.6.0_18\\bin\\jstack\" 5540 > d:\\s.log");
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
while ((line = input.readLine()) != null) {
System.out.println(line);
}
int exitVal = process.waitFor();
System.out.println("Exited with code '" + exitVal + "'");
} catch (Exception e) {
System.out.println("Error.");
}
}
}
Output:
Usage:
jstack [-l] <pid>
(to connect to running process)
Options:
-l long listing. Prints additional information about locks
-h or -help to print this help message
Exited with code '1'
How can I solve this problem?
Thanks in advance.
the cause is your output redirection argument: > d:\\s.log
jstack actually receives that bit as extra arguments, fails to parse it, and prints out the error.
when you invoke the same command from the class (cmd.exe on windows) the shell itself recognizes the redirect command, strips it out of the command, and jstack only "sees" the pid argument.
you have 2 options to fix this:
dont call jstack.exe, call cmd.exe with an argument telling it to run jstack and redirect the output
drop the redirection bit and write the output to file yourself
Trying to build a basic launcher for a java game. I'm building the proper command to run the application. When the following command executes in the launcher, the launcher closes as expected, but the command doesn't appear to work - either it doesn't work or the game launches and immediately crashes.
When I print this same command to the console and copy/paste it into console and execute manually, it works perfectly.
/**
*
*/
protected void launch(){
currentStatusMsg = "Launching...";
String cmd = "java -jar";
cmd += " -Djava.library.path=\"" +nativesDirectory.getAbsolutePath() + "\"";
cmd += " \""+applicationJar.getAbsolutePath() + "\"";
System.out.println(cmd);
try {
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec(cmd);
//closeLauncher();
BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line=null;
while((line=input.readLine()) != null) {
System.out.println(line);
}
int exitVal = pr.waitFor();
System.out.println("Exited with error code "+exitVal);
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
}
I tried adding something to read the output, but nothing is printed.
I was originally using the following format instead, but it has the same effect:
Process pr = Runtime.getRuntime().exec(new String[]{
"java",
"-Djava.library.path=\"" +nativesDirectory.getAbsolutePath() + "\"",
"-jar",
applicationJar.getAbsolutePath()});
Update I realized I was closing the launcher before allowing the debug code to run. The system only prints: "Exited with error code 1"
I finally was able to get the subprocess error to print. It states:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no lwjgl in java.library.path
However, it should be available because the command I'm executing includes the library path, and when this exact command is run manually, it works fine.
the java command launcher is not a shell. don't use quoting and space separated commands because it won't end well. put each argument into a separate String without any extra quoting, and use the exec(String[]) method.
I have written a shell script for automatic
1) start of hadoop services (namenode,datanode,jobtracker,tasktracker,secondary namenode),
2) dropping all tables from hive
3) again importing all tables in hive from SQL SERVER
And I am calling this shel script from java. Below is the code of Shell Script and Java Code
Shell Script:
export HADOOP_HOME=/home/hadoop/hadoop-0.20.2-cdh3u2/
export HIVE_HOME=/home/hadoop/hive-0.7.1/
export SQOOP_HOME=/home/hadoop/sqoop-1.3.0-cdh3u1/
export MSSQL_CONNECTOR_HOME=/home/hadoop/sqoop-sqlserver-1.0
export HBASE_HOME=/home/hadoop/hbase-0.90.1-cdh3u0
export ZOOKEEPER_HOME=/home/hadoop/zookeeper-3.3.1+10
export SQOOP_CONF_DIR=/home/hadoop/sqoop-1.3.0-cdh3u1/conf/
/home/hadoop/hadoop-0.20.2-cdh3u2/bin/hadoop/start-all.sh
/home/hadoop/hadoop-0.20.2-cdh3u2/bin/hadoop -rmr /user/hadoop/*
/home/hadoop/hive-0.7.1/bin/hive -e 'show tables' > TablesToDelete.txt
while read line1
do
echo 'drop table '$line1
/home/hadoop/hive-0.7.1/bin/hive -e 'drop table '$line1
done < TablesToDelete.txt
while read line
do
echo $line" ------------------------------"
/home/hadoop/sqoop-1.3.0-cdh3u1/bin/sqoop-import --connect 'jdbc:sqlserver://192.168.1.1;username=abcd;password=12345;database=HadoopTest' --table line --hive-table $line --create-hive-table --hive-import -m 1 --hive-drop-import-delims --hive-home /home/hadoop/hive-0.7.1 --verbose
done < /home/hadoop/sqoop-1.3.0-cdh3u1/bin/tables.txt
Java Code:
public class ImportTables
{
public static void main(String arsg[])
{
PrintWriter pw=null;
try
{
Formatter formatter = new Formatter();
String LogFile = "Log-"+ formatter.format("%1$tm%1$td-%1$tH%1$tM%1$tS", new Date());
File f=new File("/home/hadoop/"+LogFile);
FileWriter fw1=null;
pw=new PrintWriter(f);
String cmd = "/home/hadoop/sqoop-1.3.0-cdh3u1/bin/TablesToImport.sh"; // this is the command to execute in the Unix shell
// create a process for the shell
ProcessBuilder pb = new ProcessBuilder("bash", "-c", cmd);
pb.redirectErrorStream(true); // use this to capture messages sent to stderr
Process shell = pb.start();
InputStream shellIn = shell.getInputStream(); // this captures the output from the command
int shellExitStatus = shell.waitFor();
// wait for the shell to finish and get the return code
// at this point you can process the output issued by the command
// for instance, this reads the output and writes it to System.out:
int c;
while ((c = shellIn.read()) != -1)
{
System.out.write(c);
}
// close the stream
shellIn.close();
}
catch(Exception e)
{
e.printStackTrace();
e.printStackTrace(pw);
pw.flush();
System.exit(1);
}
}
}
But as I run the program I see nothiing on the console, and program remains in running mode.
And If I put the following code ion shell script:
/home/hadoop/hive-0.7.1/bin/hive -e 'show tables' > TablesToDelete.txt
while read line1
do
echo 'drop table '$line1
/home/hadoop/hive-0.7.1/bin/hive -e 'drop table '$line1
done < TablesToDelete.txt
Then the output come as:
Cannot find hadoop installation: $HADOOP_HOME must be set or hadoop must be in the path
What is the problem in my program/script? Where and How to set HADOOP_HOME and all that path in my script?
The call to waitFor is a blocking call, just as the name implies. It halts further execution until the process is done. But since your code is also the sink for the process's stdout, the whole thing blocks. Just move the waitFor to after you've processed the script's output.