From owner-freebsd-hackers Thu Aug 31 12:55: 4 2000 Delivered-To: freebsd-hackers@freebsd.org Received: from clever.visp-europe.psi.com (clever.visp-europe.psi.com [212.222.105.4]) by hub.freebsd.org (Postfix) with ESMTP id D86A337B423 for ; Thu, 31 Aug 2000 12:54:50 -0700 (PDT) Received: from ip168.berlin68.pub-ip.de.psi.net ([154.15.68.168] helo=goting.jn.berlin.snafu.de) by clever.visp-europe.psi.com with esmtp (Exim 3.14 #1) id 13UaQC-0003vb-00 for freebsd-hackers@freebsd.org; Thu, 31 Aug 2000 21:54:49 +0200 Received: by goting.jn.berlin.snafu.de (Postfix, from userid 100) id 7A8402263; Thu, 31 Aug 2000 21:54:46 +0200 (CEST) To: freebsd-hackers@freebsd.org Subject: New script to run a number of jobs (also in the background) From: Juergen Nickelsen Date: 31 Aug 2000 21:54:46 +0200 Message-ID: Lines: 202 X-Mailer: Gnus v5.6.45/XEmacs 21.1 - "Canyonlands" Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG Hello all, a while ago I wrote yet another script to run a number of programs on a certain occasion which is similar to periodic(8). My main goal was to run jobs (fetching mail and news) in parallel when I go online with my dial-up account. These should be finished, though, before the time is set with ntpdate. (ntpdate should have a minimum round-trip time.) The script reads a directory (the only argument is the path name) of arbitrary programs and executes them in ASCII order. It executes programs with names *.bg in the background and waits for their termination either before it terminates or when it encounters a program with a name *.wait (which is then also executed). Usage: run-jobs [-v [-v]] [-p argv0] jobs-directory-path I'd like to see someone like this in the standard OS. If anyone thinks it is worth including, please do; I would then take suggestions for improvement and write a manpage. The program is deliberately not plug-compatible with periodic(8) -- I think it is more flexible to just take a pathname as an argument. The pathname may, of course, have a descriptive name like /etc/periodic/daily. Well, also if no one thinks this should be in FreeBSD, I'll gladly take suggestions, of course. I just might not feel compelled to write a manpage. :-) Greetings, Juergen. #!/usr/bin/perl -w # -*- perl -*- # # Run a number of job scripts (actually arbitrary programs) in the # specified directory. Source a file env.pl, if it exists. Run # programs with names matching *.bg in the background. On program # names matching *.wait, wait until all background processes are # finished before continuing with the *.wait program. # #- # Copyright (c) 2000 Juergen Nickelsen # All rights reserved. # # Redistribution and use in source form, with or without modification, are # permitted provided that the following conditions are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $Id: run-jobs.pl,v 1.3 2000/06/27 07:04:33 ni Exp $ # use strict ; my $verbose = 0 ; # verbosity flag may be 0, 1, 2, ... my $progname = "run-jobs" ; # name of program (argv[0] doesn't work) my $ls = "/bin/ls" ; # need them sorted my $envfile = "env.pl" ; # read and evaluated at startup my $verbarg = "" ; # argument for jobs if $verbose my $nprocs = 0 ; # Number of background jobs running $| = 1 ; # due to fork() my %procs = () ; # processes indexed by pid my $jobsdir ; # directory containing job scripts # return local time in iso format sub isodate { my ($sec, $min, $hour, $mday, $mon, $year, undef, undef, undef) = localtime(time); return sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec) ; } # print something if $verbose sub vprint { print "$progname: @_\n" if $verbose ; } # print something if $verbose >= 2 sub vvprint { print "$progname: @_\n" if $verbose >= 2 ; } # run job in background sub run_bg { my ($cmd) = @_ ; my $pid = 0 ; if ($pid = fork()) { vprint "started process $pid with $cmd @ARGV" ; $procs{$pid} = $cmd ; $nprocs++ ; } else { if (!defined($pid)) { warn "fork failed ($!)" ; } else { exec "./$cmd @ARGV" ; } } } # wait for all background jobs sub wait_for_children { my $pid ; my $status ; if ($nprocs > 0) { vprint sprintf("waiting for $nprocs child process%s", $nprocs != 1 ? "es" : "") ; while (($pid = wait) != -1) { $nprocs-- ; $status = $? >> 8 ; vprint sprintf "child process $pid exits with $status" . " ($procs{$pid}), $nprocs left" ; } } } MAIN: do { # check commandline for verbose flag and program name argument FLAGS: while ($ARGV[0]) { if ($ARGV[0] =~ /^-/) { if ($ARGV[0] eq "-v") { $verbose++ ; $verbarg = "-v" ; shift ; } elsif ($ARGV[0] eq "-p") { shift ; $progname = shift ; } } else { last FLAGS ; } } $jobsdir = shift ; # directory containing job scripts if (!defined($jobsdir)) { die "usage: $progname [-v] [-p progname] directory [args...]\n" ; } # change to directory with jobs chdir $jobsdir || die "$progname: can't chdir to $jobsdir ($!)\n" ; # read file with enviroment variables etc. if present if (open (ENVF, $envfile)) { my $savenl ; my $env ; vprint "eval $envfile" ; $savenl = $/ ; $/ = undef ; # Slurp whole file $env = ; $/ = $savenl ; eval $env ; warn $@ if $@ ; } # read job file names my @jobs = `$ls` ; vprint "start jobs at " . isodate() ; # run jobs LOOP: for (@jobs) { chomp ; vvprint "check $_" ; if (-x $_ && ! -d $_) { if (/~$/) { # Skip Emacs backup files next LOOP ; } elsif (/\.bg$/) { # run *.bg in background run_bg $_ ; } else { if (/\.wait$/) { # wait for children on all *.wait` vprint "waiting on $_" ; wait_for_children() ; } vprint "run $_ @ARGV" ; system "./$_ @ARGV" ; } } } wait_for_children() ; vprint "finished at " . isodate() ; } # EOF To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message