Last active
August 29, 2015 14:10
-
-
Save arkq/8e09028d00da0d485336 to your computer and use it in GitHub Desktop.
Run given command at random time intervals
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* rundom.c - Run given command at random time intervals | |
* Copyright (c) 2014 Arkadiusz Bokowy | |
* | |
* This projected is licensed under the terms of the MIT license. | |
* | |
* Compilation: | |
* gcc -Wall -Wextra -o rundom rundom.c | |
* | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <getopt.h> | |
#include <time.h> | |
/* Run given system command and wait for the process exit. */ | |
static void runcommand(const char *cmd) { | |
/* in case someone would like to use some fancy bash syntax, | |
* just pass the command to the standard system call */ | |
system(cmd); | |
} | |
/* Return uniform and random number within the given range [min, max). */ | |
static unsigned int randrange(unsigned int min, unsigned int max) { | |
int base_random = rand(); /* in [0, RAND_MAX] */ | |
if (base_random == RAND_MAX) | |
return randrange(min, max); | |
/* now guaranteed to be in [0, RAND_MAX) */ | |
int range = max - min; | |
int remainder = RAND_MAX % range; | |
int bucket = RAND_MAX / range; | |
/* there are range buckets, plus one smaller interval within | |
* a remainder of RAND_MAX */ | |
if (base_random < RAND_MAX - remainder) | |
return min + base_random / bucket; | |
return randrange(min, max); | |
} | |
int main(int argc, char *argv[]) { | |
int opt; | |
struct option longopts[] = { | |
{"help", no_argument, NULL, 'h'}, | |
{"background", no_argument, NULL, 'b'}, | |
{"startup-run", no_argument, NULL, 'r'}, | |
{"max-count", required_argument, NULL, 'c'}, | |
{"interval", required_argument, NULL, 'i'}, | |
{"deviation", required_argument, NULL, 'd'}, | |
{0, 0, 0, 0}, | |
}; | |
int background = 0; | |
int startup = 0; | |
int counter = -1; | |
int interval = 60; | |
int deviation = 30; | |
while ((opt = getopt_long(argc, argv, "hbrc:i:d:", longopts, NULL)) != -1) | |
switch (opt) { | |
case 'h': | |
return_usage: | |
printf("usage: %s [options] <command>\n" | |
" -b, --background\tfork to background after startup\n" | |
" -r, --startup-run\trun command on startup\n" | |
" -c, --max-count=NUM\texit after NUM intervals\n" | |
" -i, --interval=NUM\tinterval (NUM seconds)\n" | |
" -d, --deviation=NUM\tinterval deviation (NUM seconds)\n", | |
argv[0]); | |
return EXIT_SUCCESS; | |
case 'b': | |
background = 1; | |
break; | |
case 'r': | |
startup = 1; | |
break; | |
case 'c': | |
counter = atoi(optarg); | |
break; | |
case 'i': | |
interval = atoi(optarg); | |
break; | |
case 'd': | |
deviation = atoi(optarg); | |
break; | |
default: | |
printf("Try `%s -h` for more informations.\n", argv[0]); | |
return EXIT_FAILURE; | |
} | |
if (counter == 0) { | |
printf("error: counter value must be != 0\n"); | |
return EXIT_FAILURE; | |
} | |
if (interval <= 0) { | |
printf("error: interval value must be >= 1\n"); | |
return EXIT_FAILURE; | |
} | |
if (deviation <= 0) { | |
printf("error: deviation value must be >= 1\n"); | |
return EXIT_FAILURE; | |
} | |
if (optind == argc) | |
/* we want to run some command, don't we? */ | |
goto return_usage; | |
/* initialize random number generator */ | |
srand(time(NULL)); | |
if (startup) { | |
runcommand(argv[optind]); | |
if (counter > 0) | |
counter--; | |
} | |
if (background) { | |
/* run main loop as a background process */ | |
if (fork() != 0) | |
return EXIT_SUCCESS; | |
} | |
int correction = 0; | |
while (counter) { | |
time_t start = time(NULL); | |
int sleeptime = correction + interval - | |
deviation / 2 + randrange(0, deviation); | |
if (sleeptime > 0) | |
sleep(sleeptime); | |
runcommand(argv[optind]); | |
if (counter > 0) | |
counter--; | |
correction = interval - (time(NULL) - start); | |
} | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment