LINUX.ORG.RU

спасибо за статью!

забукмаркал, пригодится :)

vilfred ☆☆
()

Гы... Давайте ясли откроем.

anonymous
()

Может я и круворукий, но cron - демон дебильный и староватый...
Поэтому пользуюсь sheduler-ом. Он не впаивается в систему и исходники его меньше...

anonymous
()

о шедулере можно подробней

anonymous
()

Можно (компилить с помощью cc)

/*
* scheduler.c, v0.1.1
*
* This program executes a program at a specific time.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>

#define TRUE 1
#define FALSE 0

#define CONFIG "/etc/scheduler.conf"

#define PROGRAM_TITLE "scheduler 0.1.1"
#define PROGRAM_NAME "scheduler"

#define OPTIONS_NONE 0
#define OPTIONS_ONCE 1
#define OPTIONS_DAILY 2
#define OPTIONS_WEEKLY 3
#define OPTIONS_MONTHLY 4
#define OPTIONS_YEARLY 5

#define STATUS_IDLE 0
#define STATUS_RUNNING 1

#define EXIT_OK 0
#define EXIT_NOMEM 10
#define EXIT_NOFORK 15
#define EXIT_NOREAD 20
#define EXIT_NOPARAM 50
#define EXIT_NOEXEC 60

#define CONFIG_LINE_SIZE 65536

struct execution {
int options; /* See OPTIONS_ defines. */
int status; /* See STATUS_ defines. */
int day, month, year;
int hour, minute, second;
int argc;
char **args;
struct execution *next;
} *e, *be = NULL;

struct parameters {
char *param;
struct parameters *next;
} ;

int verbose = FALSE;
char *config_fname = NULL;
FILE *config_file = NULL;

int flag_exit = FALSE;

/* Close the configuration file and check for errors. */
void fclose_check(void) {

if (fclose(config_file) != 0) {
fprintf(stderr, "Error closing '%s': %s.\n", config_fname, strerror(errno));
exit(EXIT_NOREAD);
}
return;

}

/* Deallocate execution structure list. */
void dealloc_execution(struct execution *exc) {

struct execution *tmp;
int i;

while (exc != NULL) {
tmp = exc;
exc = exc->next;
if (tmp->args != NULL) {
for (i = 0; i < tmp->argc; i++)
if (tmp->args[i] != NULL) free(tmp->args[i]);
free(tmp->args);
}
free(tmp);
}

}

/* Allocate memory checking for errors. */
void *cmalloc(size_t size) {

void *ptr;
if ((ptr = malloc(size)) == NULL) {
fprintf(stderr, "Error allocating memory: %s.\n", strerror(errno));
if (config_file != NULL) {
fclose_check();
}
dealloc_execution(be);
exit(EXIT_NOMEM);
}
return ptr;

}

/* Check if str is a value (recursive). */
int is_digit(char *str) {
int response = FALSE;
if (strlen(str) == 0) response = TRUE; else
if ((str[0] >= '0') && (str[0] <= '9')) {
str++;
response = is_digit(str);
}
return response;
}

/* Get parameters from string (recursive).
* Uses ' ' and TAB as separators.
* Ignores stuff after '<separator>#'. */
struct parameters *get_parameters(char *str) {

char *right, *left, *tab, *space;
struct parameters *par;

par = (struct parameters *) cmalloc(sizeof(struct parameters));
bzero(par, sizeof(struct parameters));

/* Assume as separator the nearest space or tab */
tab = strchr(str, 9);
space = strchr(str, 32);
if (tab > space) right = space; else right = tab;
if (right == NULL) {
if (tab == NULL) right = space; else right = tab;
}

if (right == NULL) {

/* Ignore all after '#' */
if (str[0] == '#') {
free(par);
par = NULL;
} else {
if (strlen(str) == 0) {
free(par);
par = NULL;
} else {
par->param = (char *) cmalloc(strlen(str) + 1);
strcpy(par->param, str);
}
}

} else {

/* Separate line in two parts and store the left part. */
left = str;
right[0] = 0;
do right++; while ((right[0] == 32) || (right[0] == 9));

/* If left side of separator is null, don't store it. */
if (strlen(left) == 0) {

free(par);
if (strlen(right) > 0) par = get_parameters(right); else
par = NULL;

} else {

/* Ignore all after '#' */
if (left[0] == '#') {
free(par);
par = NULL;
} else {
par->param = (char *) cmalloc(strlen(left) + 1);
strcpy(par->param, left);
/* Acquire parameters of the remaining string. */
if (strlen(right) > 0) par->next = get_parameters(right);
}

}
}

return par;

}

/* Read and acquire data in config file. */
void read_config(void) {

char *config_line;
struct parameters *p, *bp;
int line_number;
int flag_correct = FALSE;
int flag_missing = FALSE;

if ((config_file = fopen(config_fname, "r")) == NULL) {
fprintf(stderr, "Error opening '%s': %s.\n", config_fname, strerror(errno));
exit(EXIT_NOREAD);
}

/* Allocate the first execution structure. */
be = (struct execution *) cmalloc(sizeof(struct execution));
e = be; bzero(e, sizeof(struct execution));

/* Allocate the line string. */
config_line = cmalloc(CONFIG_LINE_SIZE);

/* Read configuration file. */
line_number = 0;
while (feof(config_file) == 0) {

if (fgets(config_line, CONFIG_LINE_SIZE, config_file) == NULL) {
if (feof(config_file) == 0) {
fprintf(stderr, "Error reading '%s': %s\n", config_fname, strerror(errno));
free(config_line);
fclose_check();
exit(EXIT_NOREAD);
} else config_line[0] = 0;
}
line_number++;

/* Parse configuration file line. */
if (strlen(config_line) > 0) {
char *trailing;
do {
trailing = (char *) ((int) config_line + strlen(config_line) - 1);
if ((trailing[0] == 13) || (trailing[0] == 10))
trailing[0] = 0; else trailing = NULL;
} while (trailing != NULL);

if (strlen(config_line) > 0) {
bp = get_parameters(config_line);

p = bp;
/* Check configuration file parameters */
if ((p != NULL) && (p->param != NULL)) {
if (strcmp(p->param, "daily") == 0)
/* Process 'daily' line */
e->options = OPTIONS_DAILY; else

if (strcmp(p->param, "monthly") == 0)
/* Process 'monthly' line */
e->options = OPTIONS_MONTHLY; else

if (strcmp(p->param, "yearly") == 0)
/* Process 'yearly' line */
e->options = OPTIONS_YEARLY; else

if (strcmp(p->param, "once") == 0)
/* Process 'once' line */
e->options = OPTIONS_ONCE; else {

fprintf(stderr, "Unknown parameter '%s' in '%s'.\n", p->param, config_fname);
}

/* Process following parameters */
if (e->options != OPTIONS_NONE) {

p = p->next;
if ((p != NULL) && (p->param != NULL)) {

char *left, *middle, *right;

int is_day(char *day) {
int response = FALSE;
if (is_digit(day)) {
int val = atoi(day);
if ((val >= 1) && (val <= 31))
response = TRUE;
}
return response;
}

int is_month(char *month) {
int response = FALSE;
if (is_digit(month)) {
int val = atoi(month);
if ((val >= 1) && (val <= 12))
response = TRUE;
}
return response;
}

int is_year(char *year) {
int response = FALSE;
if (is_digit(year)) {
int val = atoi(year);
if ((val >= 1970) && (val <= 65535))
response = TRUE;
}
return response;
}

int is_hour(char *hour) {
int response = FALSE;
if (is_digit(hour)) {
int val = atoi(hour);
if ((val >= 0) && (val <= 23))
response = TRUE;
}
return response;
}

int is_minsec(char *minsec) {
int response = FALSE;
if (is_digit(minsec)) {
int val = atoi(minsec);
if ((val >= 0) && (val <= 60))
response = TRUE;
}
return response;
}

flag_correct = FALSE;
switch(e->options) {
case OPTIONS_DAILY:
if (strcmp(p->param, "-") != 0) {
fprintf(stderr, "Bad parameter '%s' in line %d: must be '-'.\n", p->param, line_number);
} else flag_correct = TRUE;
break;
case OPTIONS_MONTHLY:
if (is_day(p->param)) {
e->day = atoi(p->param);
flag_correct = TRUE;
}
if (! flag_correct)
fprintf(stderr, "Bad parameter '%s' in line %d: must be a value in the range of 1-31.\n", p->param, line_number);
break;
case OPTIONS_YEARLY:
if ((right = strchr(p->param, '/')) != NULL) {
left = p->param;
right[0] = 0;
right++;
if ((is_day(left)) && (is_month(right))) {
e->day = atoi(left);
e->month = atoi(right);
flag_correct = TRUE;
} else {
right--;
right[0] = '/';
}
}
if (! flag_correct)
fprintf(stderr, "Bad parameter '%s' in line %d: must be a date in the format 'dd/mm'.\n", p->param, line_number);
break;
case OPTIONS_ONCE:
if ((middle = strchr(p->param, '/')) != NULL) {
left = p->param;
middle[0] = 0;
middle++;
if ((right = strchr(middle, '/')) != NULL) {
right[0] = 0;
right++;
if ((is_day(left)) && (is_month(middle)) && (is_year(right))) {
e->day = atoi(left);
e->month = atoi(middle);
e->year = atoi(right);
flag_correct = TRUE;
} else {
right--;
right[0] = '/';
middle--;
middle[0] = '/';
}
} else {
middle--;
middle[0] = '/';
}
}
if (! flag_correct)
fprintf(stderr, "Bad parameter '%s' in line %d: must be a date in the format 'dd/mm/yyyy'.\n", p->param, line_number);
break;
}
/* Date acquired. */

/* Acquire time. */
if (flag_correct) {
flag_correct = FALSE;
p = p->next;
if ((p != NULL) && (p->param != NULL)) {
if ((middle = strchr(p->param, ':')) != NULL) {
left = p->param;
middle[0] = 0;
middle++;
if ((right = strchr(middle, ':')) != NULL) {
right[0] = 0;
right++;
if ((is_hour(left)) && (is_minsec(middle)) && (is_minsec(right))) {
e->hour = atoi(left);
e->minute = atoi(middle);
e->second = atoi(right);
flag_correct = TRUE;
} else {
right--;
right[0] = ':';
middle--;
middle[0] = ':';
}
} else {
middle--;
middle[0] = ':';
}
}

if (flag_correct) {

/* Acquire command line. */
p = p->next;
if ((p != NULL) && (p->param != NULL)) {

struct parameters *pp;
int c;

pp = p;
while (p != NULL) {
e->argc++;
p = p->next;
}
e->argc++;

e->args = (char **) cmalloc(e->argc * sizeof(char **));
p = pp; c = 0;
while (p != NULL) {
e->args[c] = p->param;
p = p->next;
c++;
}
e->args[c] = NULL;

e->next = (struct execution *) cmalloc(sizeof(struct execution));
e = e->next;
bzero(e, sizeof(struct execution));

} else flag_missing = TRUE;

} else {
fprintf(stderr, "Bad parameter '%s' in line %d: must be a time in the format 'hh:mm:ss'.\n", p->param, line_number);
bzero(e, sizeof(struct execution));
}

} else flag_missing = TRUE;

} else
bzero(e, sizeof(struct execution));

} else flag_missing = TRUE;

if (flag_missing) {
bzero(e, sizeof(struct execution));
fprintf(stderr, "Missing parameter in line %d.\n", line_number);
}

}

}

}
}


}

/* Close configuration file and check for errors. */
fclose_check();

}

/* Main function. */
int main(int argc, char **args, char **envs) {

struct tm *now_tm;
time_t now_time_t;

int daemon = FALSE;
int nodashed = 0;
int i;

/* Evaluate parameters. */
for (i = 1; i < argc; i++) {

switch (args[i][0]) {

case '-': /* Dashed parameters. */
if ((strcmp(args[i], "-c") == 0) || (strcmp(args[i], "--config") == 0)) {
if ((i + 1 < argc) && (args[i + 1][0] != '-')) {
i++;
config_fname = args[i];
} else {
fprintf(stderr, "Invalid use of '%s'. Try '%s --help' to know more.\n", args[i], PROGRAM_NAME);
exit(EXIT_NOPARAM);
}
} else
if ((strcmp(args[i], "-d") == 0) || (strcmp(args[i], "--daemon") == 0)) {
daemon = TRUE;
} else
if ((strcmp(args[i], "-h") == 0) || (strcmp(args[i], "--help") == 0)) {
printf("%s\n", PROGRAM_TITLE);
printf("Usage: %s [OPTIONS]\n\n", PROGRAM_NAME);
printf("OPTIONS\n");
printf(" -c, --config file read 'file' for configuration\n");
printf(" instead of '/etc/scheduler.conf'.\n");
printf(" -d, --daemon fork in background.\n");
printf(" -h, --help display this text.\n");
printf(" -v, --verbose run in verbose mode.\n\n");
printf("Report bugs to <nngodinh@tiscalinet.it>.\n");
} else
if ((strcmp(args[i], "-v") == 0) || (strcmp(args[i], "--verbose") == 0)) {
verbose = TRUE;
} else {
fprintf(stderr, "Illegal parameter '%s'. Try '%s --help' to know more.\n", args[i], PROGRAM_NAME);
exit(EXIT_NOPARAM);
}
break;

default: /* Non-dashed parameters. */
nodashed++;
switch (nodashed) {
default:
fprintf(stderr, "Illegal parameter '%s'. Try '%s --help', to know more.\n", args[i], PROGRAM_NAME);
exit(EXIT_NOPARAM);
break;
}
break;

}

}

if (verbose) printf("%s\n", PROGRAM_TITLE);

/* If not specified use default configuration file. */
if (config_fname == NULL) {
config_fname = cmalloc(strlen(CONFIG) + 1);
strcpy(config_fname, CONFIG);
}

/* Read and acquire data in config file. */
read_config();
if (verbose) {
printf("Configuration file acquired, showing content.\n\n");
e = be;
if (e != NULL)
while (e->next != NULL) {
printf("Record type: ");
switch (e->options) {
case OPTIONS_DAILY:
printf("daily.\n");
break;
case OPTIONS_MONTHLY:
printf("monthly.\n");
printf("Start in day: %02d\n", e->day);
break;
case OPTIONS_YEARLY:
printf("yearly.\n");
printf("Start in date: %02d/%02d\n", e->day, e->month);
break;
case OPTIONS_ONCE:
printf("once.\n");
printf("Start in date: %02d/%02d/%04d\n", e->day, e->month, e->year);
break;
}
printf("Start in time: %02d:%02d:%02d\n", e->hour, e->minute, e->second);
printf("Command line: ");

i = 0;
while (e->args[i] != NULL) {
printf("%s ", e->args[i]);
i++;
}
printf("\n\n");

e = e->next;
}
}

/* If specified, fork in background. */
if (daemon) {
pid_t pid;
pid = fork();

switch (pid) {
case -1: /* Error while forking. */
fprintf(stderr, "Can't fork in background: %s.\n", strerror(errno));
exit(EXIT_NOFORK);
break;
case 0: /* Child. */
if (verbose) printf("Program forked in background (%d).\n", getpid());
break;
default: /* Main: should terminate to fork in background. */
exit(EXIT_OK);
break;
}
}

/* Main loop */
while (! flag_exit) {

int flag_execute;

/* Get current date/time. */
now_time_t = time(NULL);
now_tm = localtime(&now_time_t);

e = be;
if (e != NULL) while (e->next != NULL) {
flag_execute = FALSE;
if ((now_tm->tm_hour == e->hour) &&
(now_tm->tm_min == e->minute) &&
(now_tm->tm_sec == e->second))
switch (e->options) {
case OPTIONS_DAILY:
flag_execute = TRUE;
break;
case OPTIONS_MONTHLY:
if (now_tm->tm_mday == e->day)
flag_execute = TRUE;
break;
case OPTIONS_YEARLY:
if ((now_tm->tm_mon == e->month) &&
(now_tm->tm_mday == e->day))
flag_execute = TRUE;
break;
case OPTIONS_ONCE:
if ((now_tm->tm_year == e->year) &&
(now_tm->tm_mon == e->month) &&
(now_tm->tm_mday == e->day))
flag_execute = TRUE;
break;
}

if (flag_execute) {
flag_execute = FALSE;
if (e->status != STATUS_RUNNING) {
pid_t run;
run = fork();
switch (run) {
case -1: /* Error forking. */
fprintf(stderr, "Can't fork to run scheduled program '%s': %s.\n", e->args[0], strerror(errno));
break;
case 0: /* Child, run program. */
setsid();
execv(e->args[0], args);
/* Should not return */
fprintf(stderr, "Error executing '%s': %s.\n", e->args[0], strerror(errno));
exit(EXIT_NOEXEC);
break;
default: /* Main program, continue running. */
if (verbose) printf("Program '%s': execution started.\n", e->args[0]);
e->status = STATUS_RUNNING;
break;
}
}
} else
if (e->status == STATUS_RUNNING) e->status = STATUS_IDLE;

e = e->next;
}

/* Sleep a while */
usleep(300000);

}

/* Exit correctly. */
if (verbose) printf("Process terminates correctly.\n");
return EXIT_OK;

}




Файл /etc/scheduler.conf

# scheduler.conf
# This is a sample file
#
daily - 09:00:00 /usr/sbin/ppp-on
daily - 21:00:00 /usr/sbin/ppp-off
monthly 10 05:45:00 /usr/sbin/maint.sh
yearly 01/01 00:00:00 /usr/sbin/syscheck.sh
once 01/01/2038 00:00:00 /usr/sbin/timecheck.sh

Доволен? Отличная штука..

anonymous
()

Ну ты монстр ))))) Спасибо

anonymous
()

а этот шедулер висит демоном или его нужно кем то пускать всемя от времени ??

helpless
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.