Skip to content

Instantly share code, notes, and snippets.

@jollyroger
Created December 9, 2009 21:50
Show Gist options
  • Save jollyroger/252866 to your computer and use it in GitHub Desktop.
Save jollyroger/252866 to your computer and use it in GitHub Desktop.
"Fork, aggregate, log" script
#!/bin/bash
#
# NAME
# fal - wrapper script to run several concurrent commands and gather their
# output into one log file. fal is an abbreviation for "fork, aggregate, log"
#
# SYNOPSIS
# fal -c count [-l logfile] [-t] [-p pipe] [--] command [command_args]
#
# OPTIONS
# -c count
# Run command concurrently count times.
#
# -l logfile
# Store logs to the logfile. By default logfile is stored in current
# directory and called the same as the command to run but with ".log"
# extension. If such file exists, the output will be attached to the end
# of the file.
#
# -p pipe
# Create named pipe for aggregating stdout of processes. By default file
# is called command.pipe
#
# -t
# write output to both logfile and stdout
#
# The command will be run in a subshell with its arguments. If for some reason
# arguments are similar to those accepted by this script, use "--" to separate
# fal arguments and command to be run.
print_usage()
{
echo "Usage: $0 -c count [-l logfile] [-p pipe] [--] command [command_args]" >&2
exit 1;
}
# Parsing arguments
if [ "$#" -lt 3 ] ; then
print_usage;
fi
set -- `getopt "c:l:p:t" "$@"`
while [ ! -z "$1" ]
do
case $1 in
-c) COUNT=$2 ;;
-l) LOG_FILENAME=$2 ;;
-p) PIPE_FILENAME=$2 ;;
-t) ENABLE_STDOUT=1 ;;
--) break ;;
esac
shift
done
# Check variables and set default settings if needed
COMMAND_STRING=$@
COMMAND_STRING=${COMMAND_STRING#*-- }
COMMAND=${COMMAND_STRING%% *}
if [ -z "$COUNT" ] ; then
print_usage;
fi
if [ -z "$LOG_FILENAME" ] ; then
LOG_FILENAME="$COMMAND.log"
fi
if [ -z "$PIPE_FILENAME" ] ; then
PIPE_FILENAME="$COMMAND.pipe"
fi
# Some debugging info before actual work.
#echo "ARGV = $@"
#echo "COMMAND_STRING = $COMMAND_STRING"
#echo "COMMAND = $COMMAND"
#echo "LOG_FILENAME = $LOG_FILENAME"
#echo "PIPE_FILENAME = $PIPE_FILENAME"
#echo "COUNT = $COUNT"
if [ ! -p $PIPE_FILENAME ] ; then
mkfifo $PIPE_FILENAME
fi
for ((i=1 ; i <= COUNT ; i++ ))
do
eval $COMMAND_STRING >$PIPE_FILENAME 2>$PIPE_FILENAME &
done
# The next command will never exit until all PIDs who feed the pipe exit. After,
# command will exit with "broken pipe" message which will be suppressed.
if [ -z "$ENABLE_STDOUT" ] ; then
cat $PIPE_FILENAME >> $LOG_FILENAME 2>/dev/null
else
cat $PIPE_FILENAME | tee $LOG_FILENAME
fi
# Cleaning up before exit
rm $PIPE_FILENAME
exit 0;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment