从 Java 执行另一个应用程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3468987/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Executing another application from Java
提问by user234194
I need to execute a batch file which executes another Java application. I don't care whether it executes successfully or not and I don't have to capture any errors.
我需要执行一个批处理文件来执行另一个 Java 应用程序。我不在乎它是否成功执行,我不必捕获任何错误。
Is it possible to do this with ProcessBuilder? What are the consequences if I do not capture errors?
是否可以使用ProcessBuilder做到这一点?如果我不捕获错误会有什么后果?
However, my requirement is just to execute another Java application.
但是,我的要求只是执行另一个 Java 应用程序。
回答by Mot
I assume that you know how to execute the command using the ProcessBuilder
.
我假设您知道如何使用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.
从 Java 执行命令总是应该从进程中读取 stdout 和 stderr 流。否则可能会发生缓冲区已满并且进程无法继续,因为写入其 stdout 或 stderr 块。
回答by James B
If you don't care about the return value you could just use Runtime.getRuntime().exec("path.to.your.batch.file");
如果你不关心返回值,你可以使用 Runtime.getRuntime().exec("path.to.your.batch.file");
回答by Gopi
You could simply use Runtime.exec()
你可以简单地使用Runtime.exec()
回答by Jose Diaz
The Runtime.getRuntime().exec()
approach is quite troublesome, as you'll find out shortly.
这种Runtime.getRuntime().exec()
方法非常麻烦,您很快就会发现。
Take a look at the Apache Commons Execproject. It abstracts you way of a lot of the common problems associated with using the Runtime.getRuntime().exec()
and ProcessBuilder
API.
查看Apache Commons Exec项目。它抽象了许多与使用Runtime.getRuntime().exec()
和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);
回答by Dubas
You can execute a batch instruction, or any other application using
您可以使用批处理指令或任何其他应用程序执行
Runtime.getRuntime().exec(cmd);
- cmd is the command or te application path.
- cmd 是命令或 te 应用程序路径。
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
您在这里对不同类型的调用有完整的解释 http://www.rgagnon.com/javadetails/java-0014.html
回答by YoK
Yes it is possible using ProcessBuilder.
是的,可以使用 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.rgagnon.com/javadetails/java-0014.html
http://www.java-tips.org/java-se-tips/java.util/from-runtime.exec-to-processbuilder.html
http://www.java-tips.org/java-se-tips/java.util/from-runtime.exec-to-processbuilder.html
回答by cmevoli
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:
以下是如何使用ProcessBuilder
执行远程应用程序的示例。由于您不关心输入/输出和/或错误,您可以执行以下操作:
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.
该waitFor()
方法将等到进程结束后再继续。该方法返回进程的错误代码,但由于您不关心它,因此我没有将其放在示例中。
回答by Derek Ziemba
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.
我知道这是一个较旧的线程,但我认为我可能值得投入我的实现,因为我发现这个线程试图做与 OP 相同的事情,除了具有根级别访问权限,但并没有真正找到解决方案我正寻找。下面的方法创建了一个静态的根级 shell,用于只执行命令而不考虑错误检查,即使命令执行成功。
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
我使用我创建的 Android 手电筒应用程序,允许将 LED 设置为不同级别的亮度。通过消除所有错误检查和其他绒毛,我可以让 LED 在短短 3 毫秒内切换到指定的亮度级别,这为 LightTones(带光的铃声)打开了大门。可以在此处找到有关应用程序本身的更多详细信息: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:
然后在我的应用程序中的任何地方运行命令,例如更改 LED 亮度,我只需调用:
Shell.exec("echo " + bt.getLevel() + " > "+ flashfile);
回答by Ajay Kumar
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
下面的代码片段用于使用 ProcessBuilder 编译和运行外部 JAVA 程序,与我们可以运行任何外部程序的方式相同。确保必须在操作系统环境中设置 JAVA_HOME。查看更多
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();
}
}
}
回答by ForeverLearner
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).
我可以看到有一个比 apache commons exec 库更好的库。您可以使用 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
我有同样的问题。我用 JSch 来解决这个问题。Apache commons 在不同的服务器上运行命令时遇到了一些问题。加上 JSch 给了我结果和错误 InputStreams。我发现它更优雅。示例解决方案可以在这里找到: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.
编辑 1:为了找到在 Unix 上执行的进程(如果它是长时间运行的进程),请使用ps -aux | grep java
. 进程 ID 应与您正在执行的 unix 命令一起列出。