初写定时压缩日志任务总结

来源:互联网 发布:尚观云计算课程 编辑:程序博客网 时间:2024/06/06 05:34

本博文仅仅是最近学习的总结,不喜勿喷。如有误导之处,烦请指出,非常感谢。

1、前期准备:现成的脚本文件Log.sh
2、定时任务需求:要求每天晚上00:00:00调用一次Log.sh
3、设计思想:项目已有执行定时任务的相关代码,只需要编写一个调用脚本文件的类即可
首先,这个类要实现名为org.quartz.Job接口;
然后,创建一个进程去执行(调用)脚本文件。

4、创建一个本机进程的两种方法: ProcessBulider.start()和Runtime.exec(),二者都返回Process子类的一个实例。该实例可以用来控制进程并获得相关信息。
Process类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。
5、在API写到创建进程的方法可能无法针对某些平台上的特定进程很好地工作,如shell脚本。创建的子进程没有自己的终端或控制台。它的所有标准 io(即 stdin、stdout
和 stderr)操作都将通过三个流 (getOutputStream()、getInputStream() 和 getErrorStream()) 重定向到父进程。父进程使用这些流来提供到子进程的输入和获得从子进程的输出。
因为有些本机平台仅针对标准输入和输出流提供有限的缓冲区大小,如果读写子进程的输出流或输入流迅速出现失败,则可能导致子进程阻塞,甚至产生死锁。

6、我的理解是,由于创建的子进程没有自己的终端或控制台,就需要父进程来通过流提供子进程的输入、获得从子进程的输出,然而有些平台对输入流输出流提供的缓冲区大小有限,
如果读写子进程的输出流或输入流出现失败,则可能导致子进程阻塞,甚至产生死锁。因此,要把缓冲区读一下。

7、这个问题也在这里https://yq.aliyun.com/articles/2362说到,java进行一直等待shell返回,“原因是, shell脚本中有echo或者print输出, 导致缓冲区被用完了! 为了避免这种情况, 一定要把缓冲区读一下”。
总的来说,应该是这样的。可执行程序的输出可能比较多,而运行窗口的输出缓冲区大小有限,会造成waitFor()一直阻塞。
解决的方法是,利用Jav中的Process类提供的getInputStream(),getErrorStream()方法让java虚拟机截获被调用程序的标准输出、错误输出,在waitFor()命令之前读掉输出缓冲区的内容。

8、什么是waitFor()?waitFor()表示当前Process所在的子进程处于等待状态,如有必要,一直要等到由该 Process 对象表示的进程已经终止。如果已终止该子进程,此方法立即返回。
如果没有终止该子进程,调用的线程将被阻塞,直到退出子进程。 在调用waitFor()时,要向主进程上报子进程当前所处的状态。这时候就需要清空缓冲区,否则,很容易出现主线程阻塞, Process也挂起的情况。

9、不明白这句话的意思“当没有 Process 对象的更多引用时,不是删掉子进程,而是继续异步执行子进程。 ”;
“对于带有 Process 对象的 Java 进程,没有必要异步或并发执行由 Process 对象表示的进程。 ”也不明白。

10、如何读出缓冲区的内容呢?在网上大量查阅发现[例如:http://ferreousbox.iteye.com/blog/141606][http://xdwangiflytek.iteye.com/blog/1595686],众多的解决方案就是“使用两个线程来同时清空process获取的两个输入流”。即,
启动一个单独的线程来清空process.getInputStream()的缓冲区,使用另外一个线程来获取process.getErrorStream()的输出流。

如下代码所示,代码中有部分没有catch IO异常。

package com.job;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class LogTimedJob implements Job {    private static final Logger log = LoggerFactory.getLogger(LogTimedJob.class);    private String cmd = "sh /aa/bb/Log.sh";    private BufferedReader stdInput = null;    private BufferedReader stdError = null;    private Process process = null;    @Override    public void execute(JobExecutionContext arg0) throws JobExecutionException {        process = Runtime.getRuntime().exec(cmd);        new Thread(new Runnable() {            public void run(){                stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));                while (stdInput.readLine() != null);            }           }).start();        try {            stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));            String string = stdError.readLine();            while(string != null) {                log.error(string);                string = stdError.readLine();            }            int runningStatus = process.waitFor();            if (runningStatus != 0) {                log.error("Execute Cmd Error: " + cmd);                return;            }            log.info("Execute Cmd Success: " + cmd);        } catch (InterruptedException ie) {            log.warn("InterruptedException while excuting waitFor() ",ie);        } finally {            try {                stdInput.close();            } catch (IOException e) {                log.warn("Error while closing the input stream ", e);            }            try {                stdError.close();            } catch (IOException e) {                log.warn("Error while closing the error stream ", e);            }            process.destroy();        }   
原创粉丝点击