Scenario : I want to create a scheduler application which should run shell scripts as per the defined schedule. To keep it simple, I want the user to add script name and execution timings in some external file (properties/xml) which will be used by my application. For now, I am planning to run this application as a background process on Linux server. In future may be we'll make it as a web-app.
What I've tried till now:
xmlschedulingdataprocessorplugin
for this purpose but it requires user to write jobs as Java code and then add it in XML file. Please suggest some helpful quartz API which can help me in fulfilling this purpose.
UPDATE:
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("=======================");
}
}
}
My HelloJob class:
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);
}
}
OUTPUT:
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
What am I missing? I tried to create new Job for each iteration and assign script names as JobExecutionContext
The below tutorial help you to schedule shell script.
http://www.mkyong.com/java/how-to-run-a-task-periodically-in-java/
By using
Runtime.getRuntime().exec("sh shellscript.sh");
You can run shell script.
I would take the following approach :
You create a class JobShellRunner which will implement Job interface from quartz :
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
}
}
read properties files (i suppose here it will be available information about which shell script to run and it's schedule information). For each information needed you will create it's context and it's trigger:
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();
Then the trigger (note that on the cron expression you should complete with the one that you read from properties file):
Trigger trigger = TriggerBuilder .newTrigger() .withIdentity("dummyTriggerName1", "group1") .withSchedule( CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) .build();
Then schedule the job
scheduler.scheduleJob(jobA, trigger);
you can do something like as following way,
First of need to go likewise,
- 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.
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.
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).
this above step repeatedly does untill whole information read by this job and every time will generate one newer job.
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,
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With