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