]> ruderich.org/simon Gitweb - config/dotfiles.git/commitdiff
bin/chronic: add, patched chronic with -l option
authorSimon Ruderich <simon@ruderich.org>
Fri, 14 Mar 2014 14:35:55 +0000 (15:35 +0100)
committerSimon Ruderich <simon@ruderich.org>
Sun, 16 Mar 2014 14:59:56 +0000 (15:59 +0100)
bin/chronic [new file with mode: 0755]

diff --git a/bin/chronic b/bin/chronic
new file mode 100755 (executable)
index 0000000..a9fa47b
--- /dev/null
@@ -0,0 +1,84 @@
+#!/usr/bin/perl
+
+=head1 NAME
+
+chronic - runs a command quietly unless it fails
+
+=head1 SYNOPSIS
+
+chronic COMMAND...
+
+=head1 DESCRIPTION
+
+chronic runs a command, and arranges for its standard out and standard
+error to only be displayed if the command fails (exits nonzero or crashes).
+If the command succeeds, any extraneous output will be hidden.
+
+A common use for chronic is for running a cron job. Rather than
+trying to keep the command quiet, and having to deal with mails containing
+accidental output when it succeeds, and not verbose enough output when it
+fails, you can just run it verbosely always, and use chronic to hide
+the successful output.
+
+       0 1 * * * chronic backup # instead of backup >/dev/null 2>&1
+
+=head1 AUTHOR
+
+Copyright 2010 by Joey Hess <joey@kitenet.net>
+
+Original concept and "chronic" name by Chuck Houpt.
+
+Licensed under the GNU GPL version 2 or higher.
+
+=cut
+
+use warnings;
+use strict;
+use IPC::Run qw( start pump finish timeout );
+
+if (! @ARGV) {
+       die "usage: chronic [-l LOGFILE] COMMAND...\n";
+}
+
+my $logfile;
+if (@ARGV >= 3 and $ARGV[0] eq '-l') {
+       $logfile = $ARGV[1];
+       shift @ARGV;
+       shift @ARGV;
+}
+
+my ($out, $err);
+my $h = IPC::Run::start \@ARGV, \*STDIN, \$out, \$err;
+$h->finish;
+my $ret=$h->full_result;
+
+if (defined $logfile) {
+       open my $fh, '>', $logfile
+               or showout_and_die("failed to open logfile '$logfile'");
+       print $fh $err; # stderr is more interesting, show it first
+       print $fh $out;
+       close $fh
+               or showout_and_die("failed to close logfile '$logfile'");
+}
+
+if ($ret >> 8) { # child failed
+       showout();
+       exit ($ret >> 8);
+}
+elsif ($ret != 0) { # child killed by signal
+       showout();
+       exit 1;
+}
+else {
+       exit 0;
+}
+
+sub showout {
+       print STDOUT $out;
+       print STDERR $err;
+}
+sub showout_and_die {
+       my $errno = $!;
+       showout();
+       die "chronic: $_[0]: $errno\n";
+}