I have a console application written in c, it runs in the console and has its own pseudo-console. Through it, I configure this application and run it. All OK.
Now I am trying to run this application inside a Java application, and I have problems.
As an example, I use sh
ProcessBuilder builder = new ProcessBuilder("sh");
builder.redirectErrorStream(true);
Process process = builder.start();
try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()))) {
bw.write("echo lol");
while (true) {
// System.out.println(process.isAlive());
if (br.ready()) {
System.out.println(br.readLine());
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
The main idea is to run the application in the console and send several commands to it.
So, after a few experiments, I get the answer.
ProcessBuilder builder = new ProcessBuilder("sh");
Process process = builder.start();
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
new Thread(new Runnable() {
public void run() {
Scanner scan = new Scanner(br);
while (true) {
try {
if (!br.ready()) break;
System.out.println(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
PrintWriter bw = new PrintWriter(process.getOutputStream());
bw.println("echo Hello World");
bw.println("echo lol");
bw.flush();
bw.close();
Related
This question already has answers here:
Behavior of Java sockets when closing output stream
(2 answers)
Closed 4 years ago.
I need help with process outputs.
I working on a Process console, and if I write to process output, I need to close to write. If I want to send another command, I get "Stream closed" error. Can anyone help me?
Sources:
public void runServer(String servername) throws InterruptedException{
try {
//ProcessBuilder builder = new ProcessBuilder("cmd", "/c", "start && cmd.exe && cd \""+cm.getDataPath("server")+"\\"+servername+"\\\" && java -jar \""+cm.getDataPath("main")+"\\serverfiles\\"+getServerFile(servername)+"\"");
ProcessBuilder builder = new ProcessBuilder("cmd", "/c", ""+cm.getDataPath("main")+"\\run.bat "+cm.getDataPath("server")+"\\"+servername+"\\ "+cm.getDataPath("main")+"\\serverfiles\\"+getServerFile(servername)+"\"");
final Process process = builder.start(); /*Runtime.getRuntime().exec("cmd.exe /c START "+cm.getDataPath("main")+"\\run.bat "+cm.getDataPath("server")+"\\"+servername+"\\ "+cm.getDataPath("main")+"\\serverfiles\\"+getServerFile(servername)+"\"");*/
final Thread ioThread = new Thread() {
#Override
public void run() {
try {
writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
final BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
w.printConsole(line+"\n");
}
reader.close();
} catch (final Exception e) {
e.printStackTrace();
}
}
};
ioThread.start();
//process.waitFor();
runningserver = process;
} catch (IOException ex) {
Logger.getLogger(MainClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void sendCommand(String command){
writer = new BufferedWriter(new OutputStreamWriter(runningserver.getOutputStream()));
try {
writer.append(command);
writer.flush();
writer.close();
} catch (IOException ex) {
Logger.getLogger(MainClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
Every time you call sendCommand(...) you close a BufferedWriter that is wrapped around your server's OutputStream via writer.close();, and this also closes the stream. Don't do this as this prevents you from using this same stream again. In fact, your sendCommand method should re-use a writer field and your code should only close the writer when totally done with the stream.
I want to execute android shell command from my android app to execute a uiautomator test jar.
i have tried following options. but neither of them is working for me...
public void execute(String shellcommand) {
Runtime rt = Runtime.getRuntime();
Process p = r.exec(new String[]{"/system/bin/sh", "-c", shellcommand});
}
Also tried...
public void execute(String shellcommand) {
Process su = Runtime.getRuntime().exec("su");
DataOutputStream outputStream = new DataOutputStream(su.getOutputStream());
outputStream.writeBytes(shellcommand + "\n");
outputStream.flush();
outputStream.writeBytes("exit\n");
outputStream.flush();
su.waitFor();
}
Please tell what mistake i m doing?
Android 5.0 solved your problem. Here is new API using which you can execute shell commands.Check here : executeShellCommand (String command)
Enjoy!!!
Try this, i added an output reading process also. But you'll need to cut up your shell command:
ProcessBuilder pb = new ProcessBuilder("adb", "shell", "uiautomator", "runtest", "/data/local/tmp/MyJar.jar", "-c", "com.my.test.Class#testmethod", "-e someparameter someparameterName");
Process pc;
try {
pc = pb.start();
InputStream stdin = pc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdin);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
InputStreamReader esr = new InputStreamReader(pc.getErrorStream());
BufferedReader errorReader = new BufferedReader(esr);
pc.waitFor();
} catch (IOException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Assert.fail(e.getMessage());
}
I'm fairly new to ProcessBuilder and working with threads. In it's current state I have a J-Button which starts a scheduled executor service. The scheduled executor service is used to delegate a process to one of two process builders. The application is meant to record a user conversation. During the conversation, after x minutes it creates a wav and delegates it to an available process for transcription. The problem begins when the transcription class is called. The process is started and the application runs as expected. However, the transcription process doesn't actually do anything until I exit the parent application. Only then it will begin. Checking the task manager it shows as a process but uses 0.0% of the CPU and around 238MB of memory until I exit then the two processes jump to 30%-40% and 500-1000 MB of memory. Also, I am using the .waitFor() but am using a thread to run the .waitFor() process as from what I gather it causes the application to hang. How would I go about fixing this. Sorry I am unable to provide more details but I'm new to this. Thanks in advance!
public class TranDelegator {
Future<?> futureTranOne = null;
Future<?> futureTranTwo = null;
ExecutorService transcriberOne = Executors.newFixedThreadPool(1);
ExecutorService transcriberTwo = Executors.newFixedThreadPool(1);
final Runnable transcribeChecker = new Runnable() {
public void run() {
String currentWav = null;
File inputFile = new File("C:\\convoLists/unTranscribed.txt");
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(inputFile));
} catch (FileNotFoundException e1) {
System.out.println("reader didn't initialize");
e1.printStackTrace();
}
try {
currentWav = reader.readLine();
} catch (IOException e) {
System.out.println("currentWav string issue");
e.printStackTrace();
}
try {
reader.close();
} catch (IOException e) {
System.out.println("reader couldn't close");
e.printStackTrace();
}
if(currentWav != null){
if (futureTranOne == null || futureTranOne.isDone()) {
futureTranOne = transcriberOne.submit((transcriptorOne));
}
else if (futureTranTwo == null || futureTranTwo.isDone()) {
futureTranTwo = transcriberTwo.submit((transcriptorTwo));
}
}
}
};
final Runnable transcriptorOne = new Runnable() {
public void run() {
System.out.println("ONE");
try {
String classpath = System.getProperty("java.class.path");
String path = "C:/Program Files/Java/jre7/bin/java.exe";
ProcessBuilder processBuilder = new ProcessBuilder(path, "-cp",
classpath, Transcriber.class.getName());
Process process = processBuilder.start();
try {
process.waitFor();
} catch (InterruptedException e) {
System.out.println("process.waitFor call failed");
e.printStackTrace();
}
} catch (IOException e) {
System.out.println("Unable to call transcribeConvo");
e.printStackTrace();
}
}
};
final Runnable transcriptorTwo = new Runnable() {
public void run() {
System.out.println("TWO");
try {
String classpath = System.getProperty("java.class.path");
String path = "C:/Program Files/Java/jre7/bin/java.exe";
ProcessBuilder processBuilder = new ProcessBuilder(path, "-cp",
classpath, Transcriber.class.getName());
Process process = processBuilder.start();
try {
process.waitFor();
} catch (InterruptedException e) {
System.out.println("process.waitFor call failed");
e.printStackTrace();
}
} catch (IOException e) {
System.out.println("Unable to call transcribeConvo");
e.printStackTrace();
}
}
};
}
public class Transcriber {
public static void main(String[] args) throws IOException,
UnsupportedAudioFileException {
retreiveEmpInfo();
TextoArray saveConvo = new TextoArray();
ArrayList<String> entireConvo = new ArrayList();
URL audioURL;
String currentWav = wavFinder();
ConfigReader configuration = new ConfigReader();
ArrayList<String> serverInfo = configuration
.readFromDoc("serverconfig");
while (currentWav != null) {
audioURL = new URL("file:///" + currentWav);
URL configURL = Transcriber.class.getResource("config.xml");
ConfigurationManager cm = new ConfigurationManager(configURL);
Recognizer recognizer = (Recognizer) cm.lookup("recognizer");
recognizer.allocate(); // allocate the resource necessary for the
// recognizer
System.out.println(configURL);
// configure the audio input for the recognizer
AudioFileDataSource dataSource = (AudioFileDataSource) cm
.lookup("audioFileDataSource");
dataSource.setAudioFile(audioURL, null);
// Loop until last utterance in the audio file has been decoded, in
// which case the recognizer will return null.
Result result;
while ((result = recognizer.recognize()) != null) {
String resultText = result.getBestResultNoFiller();
// System.out.println(result.toString());
Collections.addAll(entireConvo, resultText.split(" "));
}
new File(currentWav).delete();
saveConvo.Indexbuilder(serverInfo, entireConvo);
entireConvo.clear();
currentWav = wavFinder();
}
System.exit(0);
}
private static String wavFinder() throws IOException {
String currentWav = null;
int x = 1;
File inputFile = new File("C:\\convoLists/unTranscribed.txt");
File tempFile = new File("C:\\convoLists/unTranscribedtemp.txt");
BufferedReader reader = new BufferedReader(new FileReader(inputFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile));
String currentLine = null;
String newLine = System.getProperty("line.separator");
while ((currentLine = reader.readLine()) != null) {
if (x == 1) {
currentWav = currentLine;
} else {
writer.write(currentLine);
writer.write(newLine);
}
x = 2;
}
reader.close();
writer.flush();
writer.close();
inputFile.delete();
// boolean successful =
tempFile.renameTo(inputFile);
// System.out.println("Success: " + successful);
// System.out.println("currentWav = " + currentWav);
return currentWav;
}
private static void retreiveEmpInfo() throws IOException {
File tempFile = new File("C:\\convoLists/tmp.txt");
BufferedReader reader = new BufferedReader(new FileReader(tempFile));
CurrentEmployeeInfo.setName(reader.readLine());
CurrentEmployeeInfo.setUserEmail(reader.readLine());
CurrentEmployeeInfo.setManagerEmail(reader.readLine());
reader.close();
}
}
This problem may be related to sub-process's input stream buffers.
You should clear the sub-process's input stream buffers.
These stream buffers got increased within the parent process's memory with time and at some moment your sub-process will stop responding.
There are few options to make sub-process work normally
Read continuously from sub-process's input streams
Redirect sub-process's input streams
Close sub-process's input streams
Closing sub-process's input streams
ProcessBuilder processBuilder = new ProcessBuilder(command);
Process process = processBuilder.start();
InputStream inStream = process.getInputStream();
InputStream errStream = process.getErrorStream();
try {
inStream.close();
errStream.close();
} catch (IOException e1) {
}
process.waitFor();
Reading sub-process's input streams
ProcessBuilder processBuilder = new ProcessBuilder(command);
Process process = processBuilder.start();
InputStreamReader tempReader = new InputStreamReader(new BufferedInputStream(p.getInputStream()));
final BufferedReader reader = new BufferedReader(tempReader);
InputStreamReader tempErrReader = new InputStreamReader(new BufferedInputStream(p.getErrorStream()));
final BufferedReader errReader = new BufferedReader(tempErrReader);
try {
while ((line = reader.readLine()) != null) {
}
} catch (IOException e) {
}
try {
while ((line = errReader.readLine()) != null) {
}
} catch (IOException e) {
}
process.waitFor();
Redirecting sub-process's input streams
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.redirectInput();
processBuilder.redirectError();
Process process = processBuilder.start();
process.waitFor();
(from comments)
Looks like process hang is due to out/error streams becoming full. You need to consume these streams; possibly via a thread.
Java7 provides another way to redirect output.
Related : http://alvinalexander.com/java/java-exec-processbuilder-process-3
I need to execute a command in my java program but after executing the command , it required another parameter ( a password in my case ). how can I manage the output process of Runtime.getRuntime().exec() to accept parameter for further execution ?
I tried new BufferedWriter(new OutputStreamWriter(signingProcess.getOutputStream())).write("123456"); but it did not work.
Does your program not feature a --password option ? Normally all command line based programs do, mainly for scripts.
Runtime.getRuntime().exec(new String[]{"your-program", "--password="+pwd, "some-more-options"});
Or the more complicated way and much more error-prone:
try {
final Process process = Runtime.getRuntime().exec(
new String[] { "your-program", "some-more-parameters" });
if (process != null) {
new Thread(new Runnable() {
#Override
public void run() {
try {
DataInputStream in = new DataInputStream(
process.getInputStream());
BufferedReader br = new BufferedReader(
new InputStreamReader(in));
String line;
while ((line = br.readLine()) != null) {
// handle input here ... ->
// if(line.equals("Enter Password:")) { ... }
}
in.close();
} catch (Exception e) {
// handle exception here ...
}
}
}).start();
}
process.waitFor();
if (process.exitValue() == 0) {
// process exited ...
} else {
// process failed ...
}
} catch (Exception ex) {
// handle exception
}
This sample opens a new thread (keep in mind concurrency and synchronisation) that's going to read the output of your process. Similar you can feed your process with input as long as it has not terminated:
if (process != null) {
new Thread(new Runnable() {
#Override
public void run() {
try {
DataOutputStream out = new DataOutputStream(
process.getOutputStream());
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(out));
bw.write("feed your process with data ...");
bw.write("feed your process with data ...");
out.close();
} catch (Exception e) {
// handle exception here ...
}
}
}).start();
}
Hope this helps.
Runtime r=Runtime.getRuntime();
process p=r.exec("your string");
try this way
You should give in parameter your windows command if you work on windows
visit this link for more details : http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html
I'm running a Java program from another Java application using Runtime.getRuntime().exec like this
Process p1 = Runtime.getRuntime().exec("javac test.java");
Process p2 = Runtime.getRuntime().exec("java test");
The content of the test.java
import java.io.*;
class test
{
public static void main(String args[])
{
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
System.out.println(s);
}
}
I want to handle Input, Output and Error stream of the process p2.
I did capture of the output of the test.java, however, I do not know how to handle output and error.
Here is my code:
try {
String s = "";
InputStream istr = p2.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(istr));
BufferedReader bre = new BufferedReader
(new InputStreamReader(p2.getErrorStream()));
while ((s = br.readLine()) != null) {
System.out.println(s);
}
br.close();
while ((s = bre.readLine()) != null) {
System.out.println(s);
}
bre.close();
p2.waitFor();
} catch (IOException ex) {
ex.printStackTrace();
} catch (Exception err) {
err.printStackTrace();
}
The code above works fine for capturing the output of the test.java. But it does not display error of the test.java.
Could you please give me a sample code for fixing this problem and handling output stream or share idea? Thanks in advance
The solution I've always used is to create a separate thread to read one of the streams
So, in your case it should be something like
String s = "";
InputStream istr = p2.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(istr));
BufferedReader bre = new BufferedReader
(new InputStreamReader(p2.getErrorStream()));
new Thread(new Runnable() {
#Override
public void run() {
while ((s = br.readLine()) != null) {
System.out.println(s);
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while ((s = bre.readLine()) != null) {
System.out.println(s);
}
}
}).start();
// when you are finished close streams