使用Java调用shell脚本的方法
方法一
这个方法比较直接,简单,适用于一般的场景,比如Jackie当前在做的项目。
方法二
这个方法相对要复杂一些,但对于需要向脚本传递参数的场景,会非常方便。但Jackie在项目里没有遇到类似的场景,所以没有使用这种方法。
注意事项
在Java代码中调用shell脚本或者命令时,有一些小细节要注意,否则等程序运行起来,就会发现各种小问题。
shell脚本的格式需要为unix格式,如果不是的话,需要使用dos2unix或者tr等命令对脚本文件的格式做处理,删除多余的\r。 命令的参考样例如下
shell脚本或者命令需要有可执行权限,这个很好理解,不解释。
shell脚本或者命令的路径。为了保证可靠性,比较省事的方法是在代码中使用脚本或者命令的全路径。在脚本里执行其它脚本或者命令时,也尽可能使用脚本或者命令的全路径,省掉准备PATH环境变量的工作。当然了,这会引入一个问题,即对脚本全路径的依赖,假如全路径是非标准路径,同时不同的设备上路径存在差异,那么Jackie推荐的做法是使用模板技术,比如Freemarker,将变化的部分抽取出来,作为变量插入到脚本里,每次执行脚本时,使用外部的变量来替换脚本中的路径,解决上述问题。但最有效、最省事的办法还是对路径进行标准化,保证脚本、命令的位置在所有设备上一致,这可以有效提高开发、运维的工作效率。
如需等待shell命令运行结束,获取运行结果,可以使用 Process的waitFor方法,样例如下:
启动shell进程后,发现进程长时间运行无法结束,同时失去响应。这个问题的原因是shell脚本或者命令在运行的过程中会向标准输出或者标准错误输出写出数据,但JVM又没有去读,导致缓冲区满,进而导致进程阻塞。这个问题的解决的方法比较简单,既然问题是缓冲区满之后没有及时清理,那么只要在Java代码里去读一下数据,保证缓冲区不会满即可。可参考如下实现。
shell命令中如果包含了管道或者重定向的操作,在SSH终端里可以正常运行,但使用Java代码运行时会报一些奇怪的错误。这个问题让Jackie纠结了半个下午,排查了好久,后来在网上搜索了一些文章,终于确认是使用方法的问题。 问题代码
正确的代码
差别在于带有管道或者重定向操作的命令需要作为参数传递给命令/bin/sh方能正常执行,否则就会报各种莫明其妙的错误,让人百思不得其解。
原文链接:https://blog.csdn.net/cihongmo6452/article/details/100831091