Skip to content

Instantly share code, notes, and snippets.

@arkq
Last active August 29, 2015 14:10
Show Gist options
  • Save arkq/8e09028d00da0d485336 to your computer and use it in GitHub Desktop.
Save arkq/8e09028d00da0d485336 to your computer and use it in GitHub Desktop.
Run given command at random time intervals
/*
* 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