basalt/scripts/batch/list-jobs.sh

140 lines
3.8 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
##
## BSD 3-Clause License
##
## This file is part of the Basalt project.
## https://gitlab.com/VladyslavUsenko/basalt.git
##
## Copyright (c) 2019-2021, Vladyslav Usenko and Nikolaus Demmel.
## All rights reserved.
##
#
# Usage:
# list-jobs.sh DIRNAME [DIRNAME ...] [-s|--short] [-o|--only STATUS]
#
# Lists all batch jobs found in DIRNAME. If the optional argument
# STATUS is passed, only lists jobs with that status. Multiple
# statuses can be passed in a space-separated string.
#
# Possible status arguments: queued, running, completed, failed, unknown
# You can also use 'active' as a synonym for 'queued running unknown'
# exit on error
set -o errexit -o pipefail
# we need GNU getopt...
GETOPT=getopt
if [[ "$OSTYPE" == "darwin"* ]]; then
if [ -f /usr/local/opt/gnu-getopt/bin/getopt ]; then
GETOPT="/usr/local/opt/gnu-getopt/bin/getopt"
fi
fi
# option parsing, see: https://stackoverflow.com/a/29754866/1813258
usage() { echo "Usage: `basename $0` DIRNAME [DIRNAME ...] [-s|--short] [-o|--only STATUS]" ; exit 1; }
# -allow a command to fail with !s side effect on errexit
# -use return value from ${PIPESTATUS[0]}, because ! hosed $?
! "$GETOPT" --test > /dev/null
if [[ ${PIPESTATUS[0]} -ne 4 ]]; then
echo 'Im sorry, `getopt --test` failed in this environment.'
exit 1
fi
OPTIONS=hsjo:
LONGOPTS=help,short,jobids,only:
# -regarding ! and PIPESTATUS see above
# -temporarily store output to be able to check for errors
# -activate quoting/enhanced mode (e.g. by writing out “--options”)
# -pass arguments only via -- "$@" to separate them correctly
! PARSED=$("$GETOPT" --options=$OPTIONS --longoptions=$LONGOPTS --name "`basename $0`" -- "$@")
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
# e.g. return value is 1
# then getopt has complained about wrong arguments to stdout
usage
fi
# read getopts output this way to handle the quoting right:
eval set -- "$PARSED"
SHORT=n
ONLY=""
JOBIDS=n
# now enjoy the options in order and nicely split until we see --
while true; do
case "$1" in
-h|--help) usage ;;
-s|--short) SHORT=y; shift ;;
-j|--jobids) JOBIDS=y; shift ;;
-o|--only) ONLY="$2"; shift 2 ;;
--) shift; break ;;
*) echo "Programming error"; exit 3 ;;
esac
done
# handle non-option arguments --> directories
if [[ $# -lt 1 ]]; then
echo "Error: Pass at least one folder"
usage
fi
DIRS=("$@")
# status aliases:
ONLY="${ONLY/active/queued running unknown}"
ONLY="${ONLY/notcompleted/queued running failed unknown}"
contains() {
[[ $1 =~ (^| )$2($| ) ]] && return 0 || return 1
}
display() {
if [ -z "$ONLY" ] || contains "$ONLY" $2; then
if [ $SHORT = y ]; then
echo "$1"
else
echo -n "$1 : $2"
if [ -n "$3" ]; then
echo -n " - $3"
fi
echo ""
fi
fi
}
for d in "${DIRS[@]}"; do
for f in `find "$d" -name status.log | sort`; do
DIR=`dirname "$f"`
# ignore backup folder from "rerun" scripts
if [[ `basename $DIR` = results-backup* ]]; then
continue
fi
if ! grep Started "$f" > /dev/null; then
display "$DIR" unknown "not started"
continue
fi
# job has started:
if grep Completed "$f" > /dev/null ; then
display "$DIR" completed ""
continue
fi
# job has started, but not completed (cleanly)
# check signs of termination
if [ -f "$DIR"/output.log ] && grep "Command terminated by signal" "$DIR"/output.log > /dev/null; then
display "$DIR" failed killed "`grep -oP 'Command terminated by \Ksignal .+' "$DIR"/output.log`"
continue
fi
# might be running or aborted
display "$DIR" unknown started
done
done