--- /dev/null
+#!/usr/bin/perl
+# Batch EXecutor 2.0 -- Run Queued Jobs
+# (c) 2011 Martin Mares <mj@ucw.cz>
+
+use strict;
+use warnings;
+use Getopt::Long;
+
+use lib 'lib';
+use BEX;
+
+my $queue_name;
+
+GetOptions(
+ "q|queue=s" => \$queue_name,
+) or die <<AMEN ;
+Usage: brun [<options>] [[!]<machine-or-class> ...]
+
+Options:
+-q, --queue=<name> Run jobs in the given queue
+AMEN
+
+sub ping_machine($) {
+ my ($mach) = @_;
+ `ping -c1 -n $mach >/dev/null 2>/dev/null`;
+ return !$?;
+}
+
+sub run_job($$$) {
+ my ($job, $queue, $mach) = @_;
+ # FIXME: rsyncing, rsync-only jobs
+ # FIXME: Locking
+
+ my $tmp = $queue->temp_file($mach, $job->{'ID'});
+ open T, '>', $tmp or die;
+ if (defined $BEX::Config::job_prolog) {
+ open P, $BEX::Config::job_prolog or return "Cannot open prolog: $!";
+ while (<P>) { print T; }
+ close P;
+ } else {
+ print T "#!/bin/sh\n";
+ }
+ print T "# BEX job ", $job->{'ID'}, "\n";
+ print T $job->{'body'};
+ if (defined $BEX::Config::job_epilog) {
+ open E, $BEX::Config::job_epilog or return "Cannot open epilog: $!";
+ while (<E>) { print T; }
+ close E;
+ }
+ close T;
+
+ my $cmd = 't=$(mktemp -t bex-XXXXXXXX) && cat >$t && chmod u+x $t && echo $t';
+ my $rtmp = `ssh <$tmp $mach '$cmd'`;
+ !$? && defined($rtmp) && $rtmp ne '' or return "Transfer failed";
+ chomp $rtmp;
+
+ system 'ssh', '-t', $mach, "$rtmp ; e=\$? ; rm -f $rtmp ; exit \$e";
+ if ($?) {
+ return 'Failed';
+ } else {
+ return 'OK';
+ }
+}
+
+my @machines = BEX::Config::parse_machine_list(@ARGV ? @ARGV : '*');
+my $queue = BEX::Queue->new($queue_name);
+for my $mach (@machines) {
+ my @q = $queue->scan($mach) or next;
+ my $ping;
+ for my $jid (@q) {
+ my $job = BEX::Job->new_from_file($queue->job_file($jid));
+ my $stat = {
+ 'Time' => time,
+ };
+ print "### Running $jid (", $job->attr('Subject'), ") on $mach ###\n";
+ $ping //= ping_machine($mach);
+ my $s;
+ if (!$ping) {
+ $s = 'No ping';
+ } else {
+ $s = run_job($job, $queue, $mach);
+ }
+
+ BEX::log("$mach $jid $s");
+ if ($s eq 'OK') {
+ print "+++ OK\n";
+ $queue->remove($mach, $jid);
+ } else {
+ print "--- $s\n";
+ $stat->{'Status'} = $s;
+ $queue->write_job_status($mach, $jid, $stat);
+ }
+ }
+}