通过ProcessBuilder进行调度
这种方法比较直观,而且参数的设置也比较方便, 比如我在实践中的代码(我隐藏了部分业务代码):
ProcessBuilder pb = new ProcessBuilder("./" + RUNNING_SHELL_FILE, param1, param2, param3); pb.directory(new File(SHELL_FILE_DIR)); int runningStatus = 0; String s = null; try { Process p = pb.start(); try { runningStatus = p.waitFor(); } catch (InterruptedException e) { } } catch (IOException e) { } if (runningStatus != 0) { } return;
这里有必要解释一下几个参数:
RUNNING_SHELL_FILE:要运行的脚本
SHELL_FILE_DIR:要运行的脚本所在的目录; 当然你也可以把要运行的脚本写成全路径。
runningStatus:运行状态,0标识正常。 详细可以看java文档。
param1, param2, param3:可以在RUNNING_SHELL_FILE脚本中直接通过1,2,$3分别拿到的参数。
直接通过系统Runtime执行shell
这个方法比较暴力,也比较常用, 代码如下:
p = Runtime.getRuntime().exec(SHELL_FILE_DIR + RUNNING_SHELL_FILE + " "+param1+" "+param2+" "+param3); p.waitFor();
我们发现,通过Runtime的方式并没有builder那么方便,特别是参数方面,必须自己加空格分开,因为exec会把整个字符串作为shell运行。
可能存在的问题以及解决方法
如果你觉得通过上面就能满足你的需求,那么可能是要碰壁了。你会遇到以下情况。
没权限运行
这个情况我们团队的朱东方就遇到了, 在做DTS迁移的过程中,要执行包里面的shell脚本, 解压出来了之后,发现执行不了。 那么就按照上面的方法授权吧
ProcessBuilder builder = new ProcessBuilder("/bin/chmod", "755", tempFile.getPath()); Process process = builder.start(); int rc = process.waitFor();
java进行一直等待shell返回
这个问题估计更加经常遇到。 原因是, shell脚本中有echo或者print输出, 导致缓冲区被用完了! 为了避免这种情况, 一定要把缓冲区读一下, 好处就是,可以对shell的具体运行状态进行log出来。 比如上面我的例子中我会变成:
ProcessBuilder pb = new ProcessBuilder("./" + RUNNING_SHELL_FILE, keyword.trim(), taskId.toString(), fileName); pb.directory(new File(CASPERJS_FILE_DIR)); int runningStatus = 0; String s = null; try { Process p = pb.start(); BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())); BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream())); while ((s = stdInput.readLine()) != null) { LOG.error(s); } while ((s = stdError.readLine()) != null) { LOG.error(s); } try { runningStatus = p.waitFor(); } catch (InterruptedException e) { }
记得在start()之后, waitFor()之前把缓冲区读出来打log, 就可以看到你的shell为什么会没有按照预期运行。 这个还有一个好处是,可以读shell里面输出的结果, 方便java代码进一步操作。
问题内容: 我必须将一些常规代码发送给仅安装了Java的某些用户(没有常规,没有$ groovy_home等)。我正在尝试从命令行调用Groovy,但是我没有运气。这是我的蝙蝠文件: 这是我的例外: 有人有线索吗?我在\ lib目录中有’groovy-all-1.6-beta-1.jar’。 问题答案: 我认为您需要在类路径中明确列出groovy jar
问题内容: 说我有Method1(void),Method2(void)… 有什么方法可以选择其中一个带有变量的方法吗? 问题答案: 使用反射:
问题内容: 与此处类似的问题,但在此处没有足够的评论要点。 根据最新的Spark 文档,可以两种不同的方式使用,一种用于SQL,另一种用于DataFrame。我找到了多个如何与sql 一起使用的示例,但还没有找到有关如何直接在DataFrame上使用a的任何示例。 op所提供的解决方案,在上面链接的问题上使用,根据Spark Java API文档,该解决方案将在Spark 2.0中删除。在那里,它
问题内容: 如何从Java调用GraphViz,以及如何使用Java调用GraphViz函数?为了访问用于构建点图的GraphViz库,必须包含哪些必需的jar文件?是否有用于生成点图的示例程序 问题答案: 检查此 API,它很简单,并且具有几种输出格式(即pdf gif ..etc)。 编辑2016年5月: 许多人评论说该API不再可用;这里是其源代码: 首先,您需要创建并复制以下文件,然后粘贴
问题内容: 我有一个想从Java使用的Perl模块。是否可以使用Windows上的ActiveState Perl或Linux随附的通用Perl来调用此代码?我找到了对JPL的引用,但似乎不再维护了。 问题答案: Inline-Java是从Perl调用Java的常用库,因此本文提出了 org.perl.java 模块,该模块应允许按要求从Java调用Perl。 但是,由于不同的JVM的JNI实现的
问题内容: 我需要从我的C ++程序中运行以下行: java -jar test.jar text1 text2 Java应用程序将给出一个float值并将其提供给c ++程序。 我怎样才能做到这一点?我从未从ms visual studio C ++文件中调用过Java东西。 问题答案: 当我直接在命令提示符下运行java命令时,它可以工作。但是当我从c ++文件运行命令时,错误显示“系统无法执