Java执行shell脚本,java代码调用shell命令

  Java执行shell脚本,java代码调用shell命令

  00-1010要求介绍1。通过ProcessBuilder 2进行调度。直接通过system 1的运行时类执行shell遇到的问题。没有运行2的权限。调用shell脚本的技巧:没有这样的文件或目录3。shell脚本输出太大,程序卡死。下面提供了工具类和您自己的外壳脚本工具类外壳脚本。

  00-1010GET方法下载远程压缩包,然后解压压缩包,取出一级目录再次压缩,得到新的压缩包。

  00-1010如果选择使用java代码的IO流操作,在没有确定zip包大小的情况下,可能会占用大量内存,所以选择异步调用shell脚本来实现这个操作;

  

目录

 

  00-1010//解决方案脚本没有执行权限。Process Builder=新的流程生成器(/bin/chmod , 755 ,script path);process process=builder . start();process . wait for();

  

需求

运行时类封装了运行时环境。每个Java应用程序都有一个运行时类的实例,这使得应用程序能够与其运行环境相连接。

 

  一般来说,你不能实例化一个运行时对象,应用程序也不能创建自己的运行时类实例。但是,可以通过getRuntime方法获取当前运行时运行时对象的引用。

  一旦获得了对当前运行时对象的引用,就可以调用运行时对象的方法来控制Java虚拟机的状态和行为。

  //shell _ file _ dir running _ shell _ file是脚本的完整路径,以下传递给shell脚本的参数用空格分隔:sting cmd=shell _ file _ dir running _ shell _ file param 1 param 2 param 3//Runtime执行脚本processps=Runtime . get Runtime();exec(cmd);//waitFor等待shell完成运行。如果返回值为0,则表示int execStatus=ps.waitFor()正常运行;

  

问题

 

  00-1010通过ProcessBuilder设置文件权限

  //解决方案脚本没有执行权限,scriptPath是脚本的完整路径,Process Builder=New Process Builder(/bin/chmod , 755 ,script path);process process=builder . start();process . wait for();

  00-1010原因:文件格式不正确。windows下写的sh文件是DOS格式的。使用:set ff=unix强制将文件转换为unix格式。

  具体操作:

  在vim模式下打开这个shell脚本,检查编码格式并将其设置为unix编码。回车:设置ff?查看格式是否为fileformat=unix;如果没有,将其设置为unix

  :set ff=unix然后保存(:wq)。

  

介绍

执行runtime.getruntime()后的Java。exec(命令),Linux会创建一个进程,该进程与JVM进程建立三个管道连接:标准输入流、标准输出流和标准错误流。

 

  当标准输出流或标准错误流非常大时,会出现调用waitFor方法卡住的bug。在真实环境下,标准输出在10000行左右时,就会卡死。

  原因分析:

  假设linux进程一直向标准输出流和标准错误流写入数据,但是JVM没有读取,那么数据将被临时存储在linux缓存中。当缓存满了,进程无法继续写数据,就会冻结,导致java进程卡在waitFor()上,永远不结束。

  解决方式:

  由于标准输出和错误输出都将数据写入Linux缓存,脚本如何输出这两个流是

  Java端不能确定的。为了不让shell脚本的子进程卡死,这两种输出需要分别读取,而且不能互相影响。所以必须新开两个线程来进行读取。

  

new Thread() { public void run() { BufferedReader br1 = new BufferedReader(new InputStreamReader(is1)); try { String line1 = null; while ((line1 = br1.readLine()) != null) { if (line1 != null){} } } catch (IOException e) { e.printStackTrace(); } finally{ try { is1.close(); } catch (IOException e) { e.printStackTrace(); } } } }.start(); new Thread() { public void run() { BufferedReader br2 = new BufferedReader(new InputStreamReader(is2)); try { String line2 = null ; while ((line2 = br2.readLine()) != null ) { if (line2 != null){} } } catch (IOException e) { e.printStackTrace(); } finally{ try { is2.close(); } catch (IOException e) { e.printStackTrace(); } } } }.start();

 

  

下面提供工具类和自己的shell脚本

 

  

工具类

import org.apache.commons.lang.ArrayUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.*;import java.util.Arrays; public class ShellCommandUtils { /* * 日志 */ private final static Logger logger = LoggerFactory.getLogger(ShellCommandUtils.class); /** * @Description: 执行shell * * @param scriptPath :脚本路径 * @param param 脚本参数 * @Return: void * @Date: 2019/3/22 */ public static int execShell(String scriptPath, String... param) { logger.info("调用处理压缩包的shell脚本,params=" + param.toString()); Arrays.stream(param).forEach(item-> logger.info(item)); //执行结果 int result = 1; try { String[] cmd = new String[]{scriptPath}; //为了解决参数中包含空格 cmd = (String[]) ArrayUtils.addAll(cmd, param); logger.info("调用处理压缩包的shell脚本,cmd=" + cmd.toString()); Arrays.stream(cmd).forEach(item-> logger.info(item)); logger.info("解决脚本没有执行权限逻辑start"); //解决脚本没有执行权限 ProcessBuilder builder = new ProcessBuilder("/bin/chmod", "755", scriptPath); Process process = builder.start(); process.waitFor(); logger.info("解决脚本没有执行权限逻辑end"); logger.info("开始执行runtime的脚本start"); Process ps = Runtime.getRuntime().exec(cmd); logger.info("把缓冲区读出来打log start"); //处理InputStream的线程,获取进程的标准输入流 final InputStream is1 = ps.getInputStream(); //获取进城的错误流 final InputStream is2 = ps.getErrorStream(); //启动两个线程,一个线程负责读标准输出流,另一个负责读标准错误流 new Thread() { public void run() { BufferedReader br1 = new BufferedReader(new InputStreamReader(is1)); try { String line1 = null; while ((line1 = br1.readLine()) != null) { if (line1 != null){} } } catch (IOException e) { e.printStackTrace(); } finally{ try { is1.close(); } catch (IOException e) { e.printStackTrace(); } } } }.start(); new Thread() { public void run() { BufferedReader br2 = new BufferedReader(new InputStreamReader(is2)); try { String line2 = null ; while ((line2 = br2.readLine()) != null ) { if (line2 != null){} } } catch (IOException e) { e.printStackTrace(); } finally{ try { is2.close(); } catch (IOException e) { e.printStackTrace(); } } } }.start(); //等待shell脚本结果 int execStatus = ps.waitFor(); logger.info("执行runtime的脚本end"); logger.info("shell脚本执行结果--execStatus ="+execStatus); result = execStatus; logger.info("返回值为result=" + result); } catch (Exception e) { logger.error("调用处理压缩包的shell出现异常!", e); } return result; }}

 

  

shell脚本

#!/bin/sh#处理压缩包fileName=$1url=$2homePath=$3 #开始处理数据逻辑echo fileName=$fileName, url=$url, homePath=$homePath #判断参数不为空if [ -n "$fileName" ]; then if [ -n "$url" ]; then #0.cd到对应目录 cd $homePath #1.调用get方法获取zip包并下载到本地 wget -O $fileName.zip $url #2.解压zip包 unzip $fileName.zip #3.删除zip包 rm -f $fileName.zip #4.进入解压完的文件夹 cd $fileName #5.压缩当前文件夹下所有文件为指定文件名的zip zip -r ../$fileName.zip ./* #6.删除之前解压的文件夹 rm -rf $homePath$fileName fifi echo "deal package end"

以上为个人经验,希望能给大家一个参考,也希望大家多多支持盛行IT。

 

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: