I need to execute a batch file which executes another Java application. I don't care wheth开发者_StackOverflow社区er it executes successfully or not and I don't have to capture any errors.
Is it possible to do this with ProcessBuilder? What are the consequences if I do not capture errors?
However, my requirement is just to execute another Java application.
The Runtime.getRuntime().exec()
approach is quite troublesome, as you'll find out shortly.
Take a look at the Apache Commons Exec project. It abstracts you way of a lot of the common problems associated with using the Runtime.getRuntime().exec()
and ProcessBuilder
API.
It's as simple as:
String line = "myCommand.exe";
CommandLine commandLine = CommandLine.parse(line);
DefaultExecutor executor = new DefaultExecutor();
executor.setExitValue(1);
int exitValue = executor.execute(commandLine);
Yes it is possible using ProcessBuilder.
ProcessBuilder example:
import java.io.*;
import java.util.*;
public class CmdProcessBuilder {
public static void main(String args[])
throws InterruptedException,IOException
{
List<String> command = new ArrayList<String>();
command.add(args[0]);
ProcessBuilder builder = new ProcessBuilder(command);
Map<String, String> environ = builder.environment();
final Process process = builder.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
System.out.println("Program terminated!");
}
}
Check these examples:
http://www.rgagnon.com/javadetails/java-0014.html
http://www.java-tips.org/java-se-tips/java.util/from-runtime.exec-to-processbuilder.html
Here is an example of how to use ProcessBuilder
to execute your remote application. Since you do not care about input/output and/or errors, you can do as follows:
List<String> args = new ArrayList<String>();
args.add ("script.bat"); // command name
args.add ("-option"); // optional args added as separate list items
ProcessBuilder pb = new ProcessBuilder (args);
Process p = pb.start();
p.waitFor();
the waitFor()
method will wait until the process had ended before continuing. This method returns the error code of the process but, since you don't care about it, I didn't put it in the example.
You can execute a batch instruction, or any other application using
Runtime.getRuntime().exec(cmd);
- cmd is the command or te application path.
Also yo can wait for executing and getting the return code (to check if its executed correctly) with this code:
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();
int exitVal = p.exitValue();
You have a full explanation of different types of calls here http://www.rgagnon.com/javadetails/java-0014.html
I assume that you know how to execute the command using the ProcessBuilder
.
Executing a command from Java always should read the stdout and stderr streams from the process. Otherwise it can happen that the buffer is full and the process cannot continue because writing its stdout or stderr blocks.
I know this is an older thread, but I figure it might be worthwhile for me to put in my implementation since I found this thread trying to do the same thing as OP, except with Root level access, but didn't really find a solution I was looking for. The below method creates a static Root level shell that is used for just executing commands without regard to error checking or even if the command executed successfully.
I use it an Android flashlight app I've created that allows setting the LED to different level of brightness. By removing all the error checking and other fluff I can get the LED to switch to a specified brightness level in as little as 3ms, which opens the door to LightTones (RingTones with light). More details on the app itself can be found here: http://forum.xda-developers.com/showthread.php?t=2659842
Below is the class in its entirety.
public class Shell {
private static Shell rootShell = null;
private final Process proc;
private final OutputStreamWriter writer;
private Shell(String cmd) throws IOException {
this.proc = new ProcessBuilder(cmd).redirectErrorStream(true).start();
this.writer = new OutputStreamWriter(this.proc.getOutputStream(), "UTF-8");
}
public void cmd(String command) {
try {
writer.write(command+'\n');
writer.flush();
} catch (IOException e) { }
}
public void close() {
try {
if (writer != null) { writer.close();
if(proc != null) { proc.destroy(); }
}
} catch (IOException ignore) {}
}
public static void exec(String command) { Shell.get().cmd(command); }
public static Shell get() {
if (Shell.rootShell == null) {
while (Shell.rootShell == null) {
try { Shell.rootShell = new Shell("su"); //Open with Root Privileges
} catch (IOException e) { }
}
}
return Shell.rootShell;
}
}
Then anywhere in my app to run a command, for instance changing the LED brightness, I just call:
Shell.exec("echo " + bt.getLevel() + " > "+ flashfile);
Below snippet code is written to compile and run external JAVA program using ProcessBuilder, same way we can run any external program. Make sure JAVA_HOME must be set in OS environment. see more
package com.itexpert.exam;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class JavaProcessBuilder {
/**
* Provide absolute JAVA file path
*/
private static final String JAVA_FILE_LOCATION = "D:\\Test.java";
public static void main(String args[]) throws IOException{
String command[] = {"javac",JAVA_FILE_LOCATION};
ProcessBuilder processBuilder = new ProcessBuilder(command);
Process process = processBuilder.start();
/**
* Check if any errors or compilation errors encounter then print on Console.
*/
if( process.getErrorStream().read() != -1 ){
print("Compilation Errors",process.getErrorStream());
}
/**
* Check if javac process execute successfully or Not
* 0 - successful
*/
if( process.exitValue() == 0 ){
process = new ProcessBuilder(new String[]{"java","-cp","d:\\","Test"}).start();
/** Check if RuntimeException or Errors encounter during execution then print errors on console
* Otherwise print Output
*/
if( process.getErrorStream().read() != -1 ){
print("Errors ",process.getErrorStream());
}
else{
print("Output ",process.getInputStream());
}
}
}
private static void print(String status,InputStream input) throws IOException{
BufferedReader in = new BufferedReader(new InputStreamReader(input));
System.out.println("************* "+status+"***********************");
String line = null;
while((line = in.readLine()) != null ){
System.out.println(line);
}
in.close();
}
}
If you don't care about the return value you could just use Runtime.getRuntime().exec("path.to.your.batch.file");
I could see that there is a better library than the apache commons exec library. You can execute your job using Java Secure Shell (JSch).
I had the same problem. I used JSch to solve this problem. Apache commons had some issues running commands on a different server. Plus JSch gave me result and errors InputStreams. I found it more elegant. Sample solution can be found here : http://wiki.jsch.org/index.php?Manual%2FExamples%2FJschExecExample
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import org.apache.commons.exec.*;
import com.jcraft.*;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.ChannelExec;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
public class exec_linux_cmd {
public HashMap<String,List<String>> exec_cmd (
String USERNAME,
String PASSWORD,
String host,
int port,
String cmd)
{
List<String> result = new ArrayList<String>();
List<String> errors = new ArrayList<String>();
HashMap<String,List<String>> result_map = new HashMap<String,List<String>>();
//String line = "echo `eval hostname`";
try{
JSch jsch = new JSch();
/*
* Open a new session, with your username, host and port
* Set the password and call connect.
* session.connect() opens a new connection to remote SSH server.
* Once the connection is established, you can initiate a new channel.
* this channel is needed to connect and remotely execute the program
*/
Session session = jsch.getSession(USERNAME, host, port);
session.setConfig("StrictHostKeyChecking", "no");
session.setPassword(PASSWORD);
session.connect();
//create the excution channel over the session
ChannelExec channelExec = (ChannelExec)session.openChannel("exec");
// Gets an InputStream for this channel. All data arriving in as messages from the remote side can be read from this stream.
InputStream in = channelExec.getInputStream();
InputStream err = channelExec.getErrStream();
// Set the command that you want to execute
// In our case its the remote shell script
channelExec.setCommand(cmd);
//Execute the command
channelExec.connect();
// read the results stream
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
// read the errors stream. This will be null if no error occured
BufferedReader err_reader = new BufferedReader(new InputStreamReader(err));
String line;
//Read each line from the buffered reader and add it to result list
// You can also simple print the result here
while ((line = reader.readLine()) != null)
{
result.add(line);
}
while ((line = err_reader.readLine()) != null)
{
errors.add(line);
}
//retrieve the exit status of the remote command corresponding to this channel
int exitStatus = channelExec.getExitStatus();
System.out.println(exitStatus);
//Safely disconnect channel and disconnect session. If not done then it may cause resource leak
channelExec.disconnect();
session.disconnect();
System.out.println(exitStatus);
result_map.put("result", result);
result_map.put("error", errors);
if(exitStatus < 0){
System.out.println("Done--> " + exitStatus);
System.out.println(Arrays.asList(result_map));
//return errors;
}
else if(exitStatus > 0){
System.out.println("Done -->" + exitStatus);
System.out.println(Arrays.asList(result_map));
//return errors;
}
else{
System.out.println("Done!");
System.out.println(Arrays.asList(result_map));
//return result;
}
}
catch (Exception e)
{
System.out.print(e);
}
return result_map;
}
//CommandLine commandLine = CommandLine.parse(cmd);
//DefaultExecutor executor = new DefaultExecutor();
//executor.setExitValue(1);
//int exitValue = executor.execute(commandLine);
public static void main(String[] args)
{
//String line = args[0];
final String USERNAME ="abc"; // username for remote host
final String PASSWORD ="abc"; // password of the remote host
final String host = "3.98.22.10"; // remote host address
final int port=22; // remote host port
HashMap<String,List<String>> result = new HashMap<String,List<String>>();
//String cmd = "echo `eval hostname`"; // command to execute on remote host
exec_linux_cmd ex = new exec_linux_cmd();
result = ex.exec_cmd(USERNAME, PASSWORD , host, port, cmd);
System.out.println("Result ---> " + result.get("result"));
System.out.println("Error Msg ---> " +result.get("error"));
//System.out.println(Arrays.asList(result));
/*
for (int i =0; i < result.get("result").size();i++)
{
System.out.println(result.get("result").get(i));
}
*/
}
}
EDIT 1: In order to find your process (if its a long-running one) being executed on Unix, use the ps -aux | grep java
. The process ID should be listed alongwith the unix command you are executing.
You could simply use Runtime.exec()
精彩评论