Java – 运行Bash命令

我有以下课程。 它允许我通过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(); } } 

运行命令时,不保存上一个命令的结果。 例如:

 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’目录的内容?

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

我建议使用ProcessBuilder

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

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

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

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

如果脚本生成很复杂,使用像velocity这样的模板引擎也是合理的。

每次调用都在它自己的shell中执行。 因此第三次调用的“cd”没有被第三次调用看到。

请参阅: https : //docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#exec(java.lang.String) 。

这表明该命令在单独的进程中运行。 因此,您产生了3个进程。

如果你想在同一个过程中全部3,试试这个:

 com.executeCommand("ls; cd bin; ls"); 

你运行的每个命令都有自己的bash shell,所以一旦你cd到那个目录,下一个命令你打开新的bash shell

尝试将命令更改为

 ls bin 

你可以形成一个复杂的bash命令来执行所有操作:“ls; cd bin; ls”。 要完成这项工作,您需要显式调用bash。 这种方法应该为您提供bash命令行的所有function(报价处理,$扩展,管道等)。

 /** * Execute a bash command. We can handle complex bash commands including * multiple executions (; | && ||), quotes, expansions ($), escapes (\), eg: * "cd /abc/def; mv ghi 'older ghi '$(whoami)" * @param command * @return true if bash got started, but your command may have failed. */ public static boolean executeBashCommand(String command) { boolean success = false; System.out.println("Executing BASH command:\n " + command); Runtime r = Runtime.getRuntime(); // Use bash -c so we can handle things like multi commands separated by ; and // things like quotes, $, |, and \. My tests show that command comes as // one argument to bash, so we do not need to quote it to make it one thing. // Also, exec may object if it does not have an executable file as the first thing, // so having bash here makes it happy provided bash is installed and in path. String[] commands = {"bash", "-c", command}; try { Process p = r.exec(commands); p.waitFor(); BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream())); String line = ""; while ((line = b.readLine()) != null) { System.out.println(line); } b.close(); success = true; } catch (Exception e) { System.err.println("Failed to execute bash with command: " + command); e.printStackTrace(); } return success; } 

每个命令都是单独执行的。 他们不同意上下文。

供将来参考:在cd后运行bash命令,在子目录中:

 import java.io.BufferedReader; import java.io.InputStreamReader; /* $ ( D=somewhere/else ; mkdir -p $D ; cd $D ; touch file1 file2 ; ) $ javac BashCdTest.java && java BashCdTest .. stdout: -rw-r--r-- 1 ubuntu ubuntu 0 Dec 28 12:47 file1 .. stdout: -rw-r--r-- 1 ubuntu ubuntu 0 Dec 28 12:47 file2 .. stderr: /bin/ls: cannot access isnt_there: No such file or directory .. exit code:2 */ class BashCdTest { static void execCommand(String[] commandArr) { String line; try { Process p = Runtime.getRuntime().exec(commandArr); BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(p.getInputStream())); while ((line = stdoutReader.readLine()) != null) { // process procs standard output here System.out.println(" .. stdout: "+line); } BufferedReader stderrReader = new BufferedReader(new InputStreamReader(p.getErrorStream())); while ((line = stderrReader.readLine()) != null) { // process procs standard error here System.err.println(" .. stderr: "+line); } int retValue = p.waitFor(); System.out.println(" .. exit code:"+Integer.toString(retValue)); } catch(Exception e) { System.err.println(e.toString()); } } public static void main(String[] args) { String flist = "file1 file2 isnt_there"; String outputDir = "./somewhere/else"; String[] cmd = { "/bin/bash", "-c", "cd "+outputDir+" && /bin/ls -l "+flist+" && /bin/rm "+flist }; execCommand(cmd); } }