使用java执行shell脚本踩的坑,共勉

背景

手上的项目属于数据库运维方面的项目,本人是属于java组,数据库DBA组,给了脚本,让执行

遇到的问题

问题1:不知道怎么写

以前没有在程序中执行过脚本,所以就到网上搜了搜,大部分给出的答案,基本都是以下两个答案

第一种,如下面这样的方法
Process  p=Runtime.getRuntime().exec("命令")
p.waitFor();
第二种
ProcessBuilder builder = new ProcessBuilder("命令");
Process process = builder.start();
process.waitFor();

这两种都有多种构造方法,具体怎么使用,网上有很多的例子,不一一介绍。

方案

在这里我选择了第一种,这里看别人帖子的时候,就知道会有一些问题,如脚本执行阻塞啊,所以直接就找了对应的解决办法,用两个流来解决,具体原因暂时没有研究过,但是这个方法是没有问题,最终也可以成功的执行。


@Component
public class ExShell {
    public void ex(String cmd){
        Runtime rt = Runtime.getRuntime();
        Process  p=null;

        try {
            System.out.println("start le");
            p = rt.exec(cmd);

            //获取进程的标准输入流
            final InputStream is1 = p.getInputStream();
            //获取进城的错误流
            final InputStream is2 = p.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();
//脚本执行完才可以执行下一步
            p.waitFor();
            System.out.println("zhi xing   wan  le ");
            p.destroy();
            System.out.println("guan   bi ");
        } catch (Exception e) {

            e.printStackTrace();
        }
        finally {

            if (p!=null)
            {
                try {
                    p.getErrorStream().close();
                    p.getInputStream().close();
                    p.getOutputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    }

问题2:脚本执行完没有预期的结果

虽然上面的方法没有问题,但是脚本有问题,在执行一个脚本之前,一定要知道这个脚本大概的耗时,所产生的结果,本人所执行的脚本大概需要几分钟,执行完会产生一些文件,但是在调用的时候几乎立刻就结束了,但是没有报异常,也没有结果产生,因为这个脚本的执行还需要一些外在条件,所以一度认为是外在条件的问题,但其实不是,实际上是因为脚本没有执行权限,但是我的程序里没有报错,所以,这里第一个答案就是,一定要去linux上,手动执行下这个脚本,看有没有什么问题;然后脚本可以执行了。

问题3:生成的文件找不到

DBA告诉我,会在脚本所在目录下,生成一个文件夹,但是我找不到,又是一个离奇事件,后来仔细看了脚本,脚本的意思应该是,在哪里执行这个脚本,就会在当前目录下生成一个文件夹,java调用shell脚本,默认就在根目录下‘/’,去执行你那个命令,所以生成的文件也放在根目录下,也就是与root等同级,当然这只是我这的问题,具体的要看脚本。

问题4:脚本的存放位置

最开始的想法,是想把脚本和生成文件放在项目的资源路径下,但是在项目打成jar包后,没有办法获取路径,虽然可以通过流的方式读取,但是我最后是需要动态的返回生成文件的路径让前端访问的,所以就把文件一起放到linux里,无奈之举。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java执行Shell脚本可以使用`Runtime`类或`ProcessBuilder`类。下面是使用`Runtime`类执行Shell脚本的示例代码: ```java import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class ShellScriptExecutor { public static void main(String[] args) { try { // 执行Shell脚本命令 String command = "sh /path/to/script.sh"; Process process = Runtime.getRuntime().exec(command); // 获取Shell脚本输出结果 BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } // 等待Shell脚本执行完成 int exitCode = process.waitFor(); System.out.println("Shell脚本执行完成,退出码:" + exitCode); } catch (IOException | InterruptedException e) { e.printStackTrace(); } } } ``` 上述代码中,`/path/to/script.sh`是你要执行Shell脚本的路径。你可以将实际Shell脚本路径替换到代码中。 使用`ProcessBuilder`类执行Shell脚本的示例代码如下: ```java import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class ShellScriptExecutor { public static void main(String[] args) { try { // 执行Shell脚本命令 ProcessBuilder processBuilder = new ProcessBuilder("sh", "/path/to/script.sh"); Process process = processBuilder.start(); // 获取Shell脚本输出结果 BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } // 等待Shell脚本执行完成 int exitCode = process.waitFor(); System.out.println("Shell脚本执行完成,退出码:" + exitCode); } catch (IOException | InterruptedException e) { e.printStackTrace(); } } } ``` 同样,你需要将实际Shell脚本路径替换到代码中。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值