I'm trying to write a output file of a python script using java exec, however I get no output.
I got the expected file however is empty.
I made a script do what I want.
#!/bin/bash/
cd /home/taste/work/AIR/air/
python configure -f .air_config
I have already tried to execute this script from the shell and I can get the output.
Process p = Runtime.getRuntime().exec(new String[]{"bash","-c","sh
./Configuration_Data/Scripts/"+cF.folderName+"/testConfigure.sh >
configureOut.txt"});
This is the way I'm reading :
String line ="";
//Used to create output
StringBuilder text = new StringBuilder();
BufferedReader input = new BufferedReader(new
InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
text.append(line+"\n");
System.out.println(line);
}
I would like to have output from my python file.
Thank you.
Since you direct the script's output with > configureOut.txt to the file, there's simply nothing left to read from the input stream. If you really want the output in both the file and the input stream, you could change the above redirection to | tee configureOut.txt.
Related
I'm trying to use a shell script in a java file.
The script runs then prints out the content of a file, and asks the user if its ok to continue
I can start the script off with this and see some output:
try {
process = processBuilder.start();
process.getOutputStream();
process.getInputStream();
process.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String output_line = "";
while ((output_line = reader.readLine()) != null) {
System.out.println(output_line);
}
but I think when the file is closed it drops out of the while loop.
I was hoping to see "OK to proceed?" but it's just getting stuck on the last line of the file.
is there a way to keep reading from the command line until the script ends?
I'm looking a way to write running log of python which is executed by java app via script.
Let's say my script is:
import time
for x in range(120):
print("Running ", x)
time.sleep(1)
Here is my current solution:
Trigger script using java
String cmd = "python script.py";
var process = Runtime.getRuntime().exec(cmd, null, new File(sandboxPath));
Write log to new file:
String traceLogCmd = String.format("strace -p %s -s 9999 -e trace=write -o output.txt", process.pid());
Runtime.getRuntime().exec(traceLogCmd, null, new File(sandboxPath));
Now the problem is output.txt only has content whenever the python script is done executing so that I cannot tailf the output file.
Meanwhile if I execute python script.py and strace command dirrectly from terminal, the output is exactly what I expected.
Can someone correct me if I did something wrong or have a another way to get python log?
Thanks in advance.
Use ProcessBuilder instead of Runtime.exec(). More details: When Runtime.exec() won't
The following code will append to StringBuilder object output of the script sb.append(line);. It would not be difficult to write that content to a file.
Process p = new ProcessBuilder("sh", "-c", "python", "path-to-your-script").start();
String result = getCommandResult(p.getInputStream());
private static String getCommandResult(InputStream stream) throws IOException {
StringBuilder sb = new StringBuilder();
try (InputStreamReader isr = new InputStreamReader(stream);
BufferedReader in = new BufferedReader(isr)) {
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
}
}
return sb.toString().trim();
}
I am unfamiliar of the way how to use Jython to call a Python app from my Java (Spring Boot) Application, so I usually use the following method to retrieve the json response from the python app: (the Java app is running on a CentOS7 environment)
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec("python test.py");
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
log.debug(line + "\n");
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
That is helpful when I call any python application, which gives me back nothing but a single line, like {"status":"ok"}
But if it gives me back multiple lines, or an exception after giving me back the json answer I expect, my Java application returns an empty string, like if it wouldn't get any response back from the Python app.
Though when I run the same command via terminal, I get the multiple line answers.
So I wonder if the issue is with my code? Am I missing something to see here which obstructs me to have multiple lines from the answer? I need the answer regardless of how many lines I get back.
Your methode has nothing to do with Jython or Python in general. You are just starting a new Process and reading its standard output.
It just happens that in your case this is a python app and the output should be json (but could be anything).
If I understand you correctly, you only want to "accept" one line json outputs from your python process. Try this:
public String getOutputFromProcess() {
//Use StringBuilder instead of Buffer if you dont need the thread safety
StringBuilder output = new StringBuilder();
StringBuilder error = new StringBuilder();
//Removed error handling for simplicity
Process p = Runtime.getRuntime().exec("python test.py");
p.waitFor(); //Maybe this needs to be moved after the reading part
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
//You also need to read the standard error output
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
String line = "";
int counter = 0;
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
counter++;
}
while ((line = stdError.readLine()) != null) {
error.append(line + "\n");
}
//Check if we have read more than one line
//If yes return empty string or null etc.
if(counter > 1) return "";
//Here you should check if this is a valid json string
return output.toString();
}
In general I would suggest you have a look at Jython and call the python function directly. If you want to use your methode, have a look at ProcessBuilder.
So apparently the solution in my case was to create a shell script serving as a bridge between the Java and the Python app.
For some reason this python app I want to use simply doesn't return with any answer when there would be multiple lines.
There are several workaround on this, probably the best to go with is Jython, as #HectorLector advised.
Also it works when I create a shell script which calls the Python app, and my Java app calls the shell script instead of the Python file.
Another solution is to run the command with an additional > output.txt
in the command, which will make sure that the called process' output will flow into the specified file. Then later the application can retrieve the data from that file, and delete it when it is not necessary anymore.
I am attempting to generate a list of all installed Programs on my Windows machine.
This is the command I am using:
WMIC /output:D:\miep product get name && type D:\miep > D:\miep_
You might have realized that I'm also trying to make a type-Command as I need the output in UTF-8.
I made a Whitelist for this with a simple loop where I will look later where in my file certain Names will appear and keep them while I remove everything else.
The command works in the command prompt, but when I try to do the same inside my Java Program it keeps telling me I've got an Invalid GET-Expression ...
Here is my function:
void createLists() throws IOException {
//String cmd = "WMIC /output:D:\\miep.csv product get name /format:\"%WINDIR%\\System32\\wbem\\de-DE\\csv.xsl\"";
String cmd = "WMIC /output:D:\\miep product get name && type D:\\miep > D:\\miep_";
System.out.println(cmd);
Process p;
p = Runtime.getRuntime().exec(cmd);
p.getOutputStream().close();
String line;
BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
BufferedReader stderr = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while ((line = stderr.readLine()) != null) {
System.out.println(line);
}
stderr.close();
System.out.println("Done");
}
I also tried the converting stuff with the .csv files as you might have seen in the second line of my code and the same:
Works in CMD, but not in my Java-Program..!
Here it keeps telling me that it's an Invalid XSL-Format
Can someone help?
I am hoping to leverage the unix sort command to sort a large text file in Java. I've tried executing sort with the process builder, but with no luck. However when I print the exact command it is going to execute and copy and paste it into the terminal, it works fine.
So far I've tried executing with /bin/sh -c "", making sure the directory the input file is and where the output file will be is fully permissioned (chmod 777) but with no luck.
Here is the code (if it looks funny, note is using some functions found in Guava)
File inputFile = new File(inputFileName);
//build the command (optional number of sort columns)
List<String> command = new LinkedList<String>();
command.addAll(ImmutableList.<String>of("sort","-t"+delimiter));
for (int i : sortFieldPositions) {
command.add("-k"+i+","+i);
}
command.addAll(ImmutableList.<String>of(inputFileName,">",outputFileName));
//for debugging: output the command that will be executed
System.out.println("Executing: "+Joiner.on(" ").join(command));
//construct and start the process
Process process = new ProcessBuilder(command).redirectErrorStream(true).directory(inputFile.getParentFile()).start();
//for debugging: save process output
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder outputStringBuilder = new StringBuilder();
for (String line; (line = bufferedReader.readLine()) != null; /*reading taking place in check */) {
System.out.println("FROM PROCESS: "+line);
outputStringBuilder.append(line);
}
bufferedReader.close();
if (process.exitValue() != 0) {
//something went wrong
throw new RuntimeException("Error code "+process.exitValue()+" executing command: "+Joiner.on(" ").join(command)+"\n"+outputStringBuilder.toString());
}
Unfortunately this does not work, with the following output:
Executing: sort -t, -k2,2 -k1,1 /tmp/java/TestDataSorterImporterInput.txt /tmp/java/TestDataSorterImporterOutput.txt
FROM PROCESS: sort: stat failed: >: No such file or directory
Edit: It may be helpful to note that if I remove saving the output (> outputfile) from the command, then the command executes without complaint and the sorted version appears in the output from the Processes' input stream)
It is the shell that knows how to perform output redirection. The sort program cannot do it on its own. So if you want redirection, you need to do /bin/sh -c ... to let she shell into the loop.
(You write that you have tried this, but something else must have gone wrong with that).
Try this:
String whatever = "filename";
Process p = Runtime.getRuntime().exec("sort -t -k2 2 -k1 1 " + whatever);
See this site.
Process process = new ProcessBuilder("/bin/bash", "-c", "sort -t'|' -k2").start();