java中bash应用,在Java中运行Bash命令

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"));

}

Gives the output:

bin

src

bin

src

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

解决方案

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.

I would recommend to use ProcessBuilder

ProcessBuilder pb = new ProcessBuilder("ls");

pb.inheritIO();

pb.directory(new File("bin"));

pb.start();

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.

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

EDIT

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);

}

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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值