在Java中运行Bash命令 [英] Running Bash commands in Java

查看:142
本文介绍了在Java中运行Bash命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下课程.它允许我通过Java执行命令.

I have the following class. It allows me to execute commands through java.

public class ExecuteShellCommand {

public String executeCommand(String command) {

    StringBuffer output = new StringBuffer();

    Process p;
    try {
        p = Runtime.getRuntime().exec(command);
        p.waitFor();
        BufferedReader reader = 
                        new BufferedReader(new InputStreamReader(p.getInputStream()));

        String line = "";           
        while ((line = reader.readLine())!= null) {
            output.append(line + "\n");
        }

    } catch (Exception e) {
        e.printStackTrace();
    }

    return output.toString();

}

}

当我运行命令时,上一个命令的结果不会保存.例如:

When I run commands, the result of the previous command isn't saved. For example:

public static void main(String args[]) {

    ExecuteShellCommand com = new ExecuteShellCommand();
    System.out.println(com.executeCommand("ls"));
    System.out.println(com.executeCommand("cd bin"));
    System.out.println(com.executeCommand("ls"));

}

给出输出:

bin
src


bin
src

第二个"ls"命令为什么不显示"bin"目录的内容?

Why doesn't the second 'ls' command show the contents of the 'bin' directory?

推荐答案

您可以使用Runtime.exec(command)启动新进程.每个进程都有一个工作目录.通常这是启动父进程的目录,但是您可以更改启动进程的目录.

You start a new process with Runtime.exec(command). Each process has a working directory. This is normally the directory in which the parent process was started, but you can change the directory in which your process is started.

我建议使用 ProcessBuilder

ProcessBuilder pb = new ProcessBuilder("ls");
pb.inheritIO();
pb.directory(new File("bin"));
pb.start();

如果要在一个shell中运行多个命令,最好创建一个临时的shell脚本并运行它.

If you want to run multiple commands in a shell it would be better to create a temporary shell script and run this.

public void executeCommands() throws IOException {

    File tempScript = createTempScript();

    try {
        ProcessBuilder pb = new ProcessBuilder("bash", tempScript.toString());
        pb.inheritIO();
        Process process = pb.start();
        process.waitFor();
    } finally {
        tempScript.delete();
    }
}

public File createTempScript() throws IOException {
    File tempScript = File.createTempFile("script", null);

    Writer streamWriter = new OutputStreamWriter(new FileOutputStream(
            tempScript));
    PrintWriter printWriter = new PrintWriter(streamWriter);

    printWriter.println("#!/bin/bash");
    printWriter.println("cd bin");
    printWriter.println("ls");

    printWriter.close();

    return tempScript;
}

当然,您也可以在系统上使用任何其他脚本.在运行时生成脚本有时是有意义的,例如如果执行的命令必须更改.但是,您首先应该尝试创建一个可以使用参数调用的脚本,而不是在运行时动态生成该脚本.

Of course you can also use any other script on your system. Generating a script at runtime makes sometimes sense, e.g. if the commands that are executed have to change. But you should first try to create one script that you can call with arguments instead of generating it dynamically at runtime.

如果脚本生成很复杂,那么使用模板引擎(例如Velocity)也可能是合理的.

It might also be reasonable to use a template engine like velocity if the script generation is complex.

编辑

您还应该考虑将流程构建器的复杂性隐藏在一个简单的界面后面.

You should also consider to hide the complexity of the process builder behind a simple interface.

将需要的内容(接口)与完成的方式(实现)分开.

Separate what you need (the interface) from how it is done (the implementation).

public interface FileUtils {
    public String[] listFiles(String dirpath);
}

然后,您可以提供使用流程生成器或本机方法执行的实现,并且可以为linux或Windows等不同环境提供不同的实现.

You can then provide implementations that use the process builder or maybe native methods to do the job and you can provide different implementations for different environments like linux or windows.

最后,这样的接口在单元测试中也更容易模拟.

Finally such an interface is also easier to mock in unit tests.

这篇关于在Java中运行Bash命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆