使用Quartz中的property / xml文件作为作业动态添加脚本

时间:2016-04-07 04:21:18

标签: java quartz-scheduler

  

场景:我想创建一个调度程序应用程序,它应该按照定义的计划运行shell脚本。为了简单起见,我希望用户在我的应用程序将使用的一些外部文件( properties / xml )中添加脚本名称和执行时间。目前,我计划在Linux服务器上运行此应用程序作为后台进程。将来我们可能会将其作为网络应用程序。

到目前为止我一直在尝试:

  1. 出于此目的,我遇到xmlschedulingdataprocessorplugin,但它要求用户将作业编写为Java代码,然后将其添加到XML文件中。
  2. 我发现some examples for scheduling目前无效。
  3. 请建议一些有用的石英API,它可以帮助我实现这个目的。

    更新:

    public class CronTriggerExample {
    public static void main(String[] args) throws Exception {
    
      String[] a = {"script1.sh:0/10 * * * * ?", "script2.sh:0/35 * * * * ?"};
    
        for (String config : a) {
    
            String[] attr = config.split(":");
            System.out.println("Iterating for : "+attr[0]);
    
            JobKey jobKey = new JobKey(attr[0], attr[0]);
    
            Trigger trigger = TriggerBuilder
                    .newTrigger()
                    .withIdentity(attr[0], attr[0])
                    .withSchedule(CronScheduleBuilder.cronSchedule(attr[1]))
                    .build();
    
            Scheduler scheduler = new StdSchedulerFactory().getScheduler();
    
            scheduler.getContext().put("val", config);
            JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity(jobKey).build();
    
            scheduler.start();
            scheduler.scheduleJob(job, trigger);
            System.out.println("=======================");
          }
      }
    }
    

    我的 HelloJob 类:

    public class HelloJob implements Job {
    
    public void execute(JobExecutionContext context) throws JobExecutionException {
        String objectFromContext = null;
        Date date = new Date();
        try {
            SchedulerContext schedulerContext = context.getScheduler().getContext();
            objectFromContext = (String) schedulerContext.get("val");
    
        } catch (SchedulerException ex) {
            ex.printStackTrace();
        }
    
        System.out.println("Triggered "+objectFromContext+" at: "+date);
    
      }
    }
    

    输出:

    Iterating for : script1.sh
    log4j:WARN No appenders could be found for logger    (org.quartz.impl.StdSchedulerFactory).
    log4j:WARN Please initialize the log4j system properly.
    log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    =======================
    Iterating for : script2.sh
    =======================
    Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:21:50 IST 2016
    Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:22:00 IST 2016
    Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:22:00 IST 2016
    Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:22:10 IST 2016
    Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:22:20 IST 2016
    Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:22:30 IST 2016
    Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:22:35 IST 2016
    Triggered script2.sh:0/35 * * * * ? at: Mon Apr 18 12:22:40 IST 2016
    

    我错过了什么?我尝试为每次迭代创建新Job,并将脚本名称指定为JobExecutionContext

3 个答案:

答案 0 :(得分:2)

以下教程可帮助您安排shell脚本。

http://www.mkyong.com/java/how-to-run-a-task-periodically-in-java/

使用

Runtime.getRuntime().exec("sh shellscript.sh");

您可以运行shell脚本。

答案 1 :(得分:2)

我会采取以下方法:

  • 您创建了一个JobShellRunner类,它将从quartz实现 Job 接口:

    public class JobShellRunner implements Job {
    
    @Override
    public void execute(JobExecutionContext context)
        throws JobExecutionException {
        // here you take need information about the shell script you need to run, from the context and run the shell script 
    }
    

    }

  • 读取属性文件(我想这里将提供有关运行哪个shell脚本及其计划信息的可用信息)。对于所需的每个信息,您将创建它的上下文及其触发器:

    JobKey jobKey = new JobKey("jobShellRunner", "group1");
    // put in the job key need information about shell script (path, etc)
    JobDetail jobA = JobBuilder.newJob(JobShellRunner.class)
    .withIdentity(jobKey).build();
    
  • 然后是触发器(请注意,您应该使用从属性文件中读取的那个来完成cron表达式):

    触发器触发器= TriggerBuilder     .newTrigger()     .withIdentity(" dummyTriggerName1"," group1")     .withSchedule(         CronScheduleBuilder.cronSchedule(" 0/5 * * * *?"))     .build();

  • 然后安排工作

    scheduler.scheduleJob(jobA,trigger);

答案 2 :(得分:1)

you can do something like as following way,

First of need to go likewise,

  1. create your java application which has one scheduled-job which will read at some time interval one propery/xml file which will provide an information for which shell_file needs to execute and at what time.
  2. While your program's scheduled-job read that property/xml file and getting information as following,

     2.1. Shell-Script-File-Name
     2.2. Timing at what time that script needs to be execute.
    
  3. This information which is read by above(step-2), with help of it, this job will create newer independent-job which is fully responsible for execute shell script at particular time.(that time will be your job-time which is read from your propery/xml file). also take care of it to it should be one time only(as per your requirement).

  4. this above step repeatedly does untill whole information read by this job and every time will generate one newer job.

  5. in case after some time user edit/updated/added new line into property/xml file this java program's scheduled job will read only that newer changes and accordingly does as like above explained.

you can see below image for better understanding purpose,

enter image description here

For scheduling purpose you can set-up spring-quartz API for schedule job.

here, I am going to give you little bit pseudo code,

public class JobA implements Job {

    @Override
    public void execute(JobExecutionContext context)
            throws JobExecutionException {

        // continues read property/xml file untill while file not read
        // based upon above read info. generate new job(one time only) at runtime which has capability to execute shell script
// shell script can be execute by java program by this ,
//  Runtime.getRuntime().exec("sh /full-path/shell_script_name.sh"); 

    }

}
............
public class CronTriggerExample {
    public static void main( String[] args ) throws Exception
    {

        JobKey jobKeyA = new JobKey("jobA", "group1");
        JobDetail jobA = JobBuilder.newJob(JobA.class)
                .withIdentity(jobKeyA).build();

        Trigger trigger1 = TriggerBuilder
                .newTrigger()
                .withIdentity("dummyTriggerName1", "group1")
                .withSchedule(
                        CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) // you can set here your comfortable job time...
                .build();

        Scheduler scheduler = new StdSchedulerFactory().getScheduler();

        scheduler.start();
        scheduler.scheduleJob(jobA, trigger1);
    }
}

So, this is an idea what I believe and represent over here, which is top-most suitable as per your requirement.