如何从Java代码运行Unix shell脚本?
从Java运行Unix命令非常简单。
Runtime.getRuntime().exec(myCommand);
但是是否可以从Java代码运行Unix shell脚本? 如果是的话,从Java代码中运行一个shell脚本是不是一个好习惯?
你应该看看Process Builder 。 这是真的为这种事情而build。
ProcessBuilder pb = new ProcessBuilder("myshellScript.sh", "myArg1", "myArg2"); Map<String, String> env = pb.environment(); env.put("VAR1", "myValue"); env.remove("OTHERVAR"); env.put("VAR2", env.get("VAR1") + "suffix"); pb.directory(new File("myDir")); Process p = pb.start();
我会说,从Java运行一个shell脚本不符合Java的精神 。 Java是跨平台的,运行一个shell脚本将会限制它的使用。
这样说,从Java内部运行一个shell脚本是绝对有可能的。 您可以使用与列出的语法完全相同的语法(我没有自己尝试过,但直接尝试执行shell脚本,如果不行,请执行shell本身,将脚本作为命令行parameter passing) 。
我想你已经用自己的问题回答了
Runtime.getRuntime().exec(myShellScript);
至于这是不是好的做法…你想用一个你不能用Java做的shell脚本来做什么?
您也可以使用Apache Commons exec库 。
例如:
package testShellScript; import java.io.IOException; import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.DefaultExecutor; import org.apache.commons.exec.ExecuteException; public class TestScript { int iExitValue; String sCommandString; public void runScript(String command){ sCommandString = command; CommandLine oCmdLine = CommandLine.parse(sCommandString); DefaultExecutor oDefaultExecutor = new DefaultExecutor(); oDefaultExecutor.setExitValue(0); try { iExitValue = oDefaultExecutor.execute(oCmdLine); } catch (ExecuteException e) { System.err.println("Execution failed."); e.printStackTrace(); } catch (IOException e) { System.err.println("permission denied."); e.printStackTrace(); } } public static void main(String args[]){ TestScript testScript = new TestScript(); testScript.runScript("sh /root/Desktop/testScript.sh"); } }
为了进一步的参考, Apache Doc也给出了一个例子。
是的,有可能这样做。 这为我解决了。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import org.omg.CORBA.portable.InputStream; public static void readBashScript() { try { Process proc = Runtime.getRuntime().exec("/home/destino/workspace/JavaProject/listing.sh /"); //Whatever you want to execute BufferedReader read = new BufferedReader(new InputStreamReader( proc.getInputStream())); try { proc.waitFor(); } catch (InterruptedException e) { System.out.println(e.getMessage()); } while (read.ready()) { System.out.println(read.readLine()); } } catch (IOException e) { System.out.println(e.getMessage()); } }
至于我所有的事情一定是简单的。 运行脚本只需要执行
new ProcessBuilder("pathToYourShellScript").start();
这是我的例子。 希望它是有道理的。
public static void excuteCommand(String filePath) throws IOException{ File file = new File(filePath); if(!file.isFile()){ throw new IllegalArgumentException("The file " + filePath + " does not exist"); } if(this.isLinux()){ Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", filePath}, null); }else if(this.isWindows()){ Runtime.getRuntime().exec("cmd /c start " + filePath); } } public static boolean isLinux(){ String os = System.getProperty("os.name"); return os.toLowerCase().indexOf("linux") >= 0; } public static boolean isWindows(){ String os = System.getProperty("os.name"); return os.toLowerCase().indexOf("windows") >= 0; }
为了避免硬编码一个绝对path,你可以使用下面的方法来查找和执行你的脚本,如果它在你的根目录下的话。
public static void runScript() throws IOException, InterruptedException { ProcessBuilder processBuilder = new ProcessBuilder("./nameOfScript.sh"); //Sets the source and destination for subprocess standard I/O to be the same as those of the current Java process. processBuilder.inheritIO(); Process process = processBuilder.start(); int exitValue = process.waitFor(); if (exitValue != 0) { // check for errors new BufferedInputStream(process.getErrorStream()); throw new RuntimeException("execution of script failed!"); } }
这是可能的,只是执行它作为任何其他程序。 只要确保你的脚本有正确的#! (she-bang)行作为脚本的第一行,并确保文件上有执行权限。
例如,如果它是一个bash脚本,在脚本的顶部放置#!/ bin / bash,也是chmod + x。
另外,如果这是一个好的做法,不,不是,特别是对于Java,但是如果它节省了大量的时间移植一个大脚本,并且没有多花钱去做;)节省你的时间,执行脚本,并将其移植到您的长期待办事项列表中的Java。
String scriptName = PATH+"/myScript.sh"; String commands[] = new String[]{scriptName,"myArg1", "myArg2"}; Runtime rt = Runtime.getRuntime(); Process process = null; try{ process = rt.exec(commands); process.waitFor(); }catch(Exception e){ e.printStackTrace(); }
是的,这是可能的,你已经回答了! 关于良好的做法,我认为最好从文件中启动命令,而不是直接从代码中启动。 所以你必须让Java在现有的.bat,.sh,.ksh …文件中执行命令列表(或者一个命令)。 下面是一个在“MyFile.sh”文件中执行命令列表的例子:
String[] cmd = { "sh", "MyFile.sh", "\pathOfTheFile"}; Runtime.getRuntime().exec(cmd);
ZT Process Executor库是Apache Commons Exec的替代品。 它具有运行命令,捕获输出,设置超时等function。
我还没有使用它,但它看起来相当有据可查。
文档中的示例:执行一个命令,将stderr泵入logging器,以UTF8string的forms返回输出。
String output = new ProcessExecutor().command("java", "-version") .redirectError(Slf4jStream.of(getClass()).asInfo()) .readOutput(true).execute() .outputUTF8();
其文档比Commons Exec列出了以下优点:
- 改进了对stream的处理
- 读/写stream
- 将stderrredirect到stdout
- 改进处理超时
- 改进了退出代码的检查
- 改进的API
- 一个用于相当复杂的用例的内衬
- 一个内衬将stream程输出到一个string
- 访问可用的过程对象
- 支持asynchronousstream程( 未来 )
- 使用SLF4J API改进日志logging
- 支持多个进程
和Solaris 5.10一样,它的工作原理就是这样./batchstart.sh
有一个技巧,我不知道你的操作系统是否接受它使用\\. batchstart.sh
\\. batchstart.sh
代替。 这个双斜线可能有帮助。
我认为与
System.getProperty("os.name");
如果支持,检查操作系统可以pipe理shell / bash脚本。 如果需要使代码便携。