Package: moreutils
Version: 0.47
Severity: wishlist

I've written a small tool, called splay.  It sleeps for a random number
of seconds, up to the number given on the command line.  It can also
seed the random number generator from the host name or the
/etc/machine-id file, which allows you to have consistent delays for
each host.  This is useful to prevent the thundering herd effect
network-using tools can have when you have lots of machines running the
same script out of cron.

I've attached splay.c, it just needs -lcrypt to link.

-- System Information:
Debian Release: wheezy/sid
  APT prefers testing
  APT policy: (500, 'testing'), (50, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 3.4.0 (SMP w/4 CPU cores)
Locale: LANG=nb_NO.UTF-8, LC_CTYPE=nb_NO.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages moreutils depends on:
ii  libc6            2.13-35
ii  libipc-run-perl  0.92-1
ii  perl             5.14.2-14

moreutils recommends no packages.

Versions of packages moreutils suggests:
pn  libtime-duration-perl  <none>
ii  libtimedate-perl       1.2000-1

-- no debconf information

-- 
Tollef Fog Heen
UNIX is user friendly, it's just picky about who its friends are
/*
 *  splay.c - sleep for up to a defined interval, with the ability to
 *  be consistent per host name or for a given string.
 *
 *  Copyright © 2012 Tollef Fog Heen <[email protected]>
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  version 2 as published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 *
 */

#define _XOPEN_SOURCE
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

void usage(char *argv0) {
	fprintf(stderr, "Usage: %s [-h] [-m] [-s string] delay\n", argv0);
	exit(EXIT_FAILURE);
}

int main(int argc, char **argv) {
	char *hash = NULL;
	char hostname[HOST_NAME_MAX];
	char c;
	int delay, splay;
	FILE *f;

	while ((c = getopt(argc, argv, "hms:")) != -1) {
		switch (c) {
		case 'h':
			gethostname(hostname, HOST_NAME_MAX);
			hash = hostname;
			break;
		case 'm':
			f = fopen("/etc/machine-id", "r");
			if (!f) {
				fprintf(stderr, "Failed to open /etc/machine-id: %s\n", strerror(errno));
				exit(EXIT_FAILURE);
			}
			fgets(hostname, HOST_NAME_MAX, f);
			hash = hostname;
			break;
		case 's':
			hash = optarg;
			break;
		default:
			usage(argv[0]);
		}
	}

	if (optind != argc - 1) {
		usage(argv[0]);
	} else {
		errno = 0;
		splay =  strtol(argv[optind], NULL, 0);
		/* XXX error handling */
	}

	if (hash) {
		/* consistent hashing for host name or string given */
		char *cs;
		int v = 0, shift = 0;
		cs = crypt(hash, hash);
		while (*cs) {
			v ^= ((*cs) << CHAR_BIT * shift);

			shift = (shift + 1) % sizeof v;
			cs++;
		}
		srand(v);
	} else {
		srand(time(NULL));
	}
	delay = rand() % splay;
	sleep(delay);
	exit(EXIT_SUCCESS);
}

Reply via email to