O script a seguir pode ser usado como o wrapper que você descreve. Ele salva a saída padrão e os fluxos de erro padrão do comando especificado em um diretório de estado ( $HOME/states
) e também armazena o número de execuções com falha.
Se o número de execuções com falha do comando exceder 10 (ou o número que for atribuído ao sinalizador de linha de comando -t
), ele fornecerá alguma saída (em seu fluxo de erro padrão). Em todos os outros casos, nenhuma saída será fornecida. O script sai com o mesmo status de saída que o comando fornecido.
Exemplo de uso:
$ sh ./script.sh -t 2 sh -c 'echo "this will fail"; cd /nowhere'
$ sh ./script.sh -t 2 sh -c 'echo "this will fail"; cd /nowhere'
FAILED 2 times: sh -c echo "this will fail"; cd /nowhere
f88eff95bba49f6dd35a2e5ba744718d
stdout --------------------
this will fail
stderr --------------------
sh: cd: /nowhere - No such file or directory
END
O script em si (depende de md5sum
do GNU coreutils):
#!/bin/sh
statedir="$HOME/states"
if ! mkdir -p "$statedir"; then
printf 'Failed creating "%s"\n' "$statedir" >&2
exit 1
fi
max_tries=10
while getopts 't:' opt; do
case "$opt" in
t) max_tries=$OPTARG ;;
*) echo 'error' >&2
exit 1
esac
done
shift "$(( OPTIND - 1 ))"
hash=$( printf '%s\n' "$@" | md5sum | cut -d ' ' -f 1 )
"$@" >"$statedir/$hash".out 2>"$statedir/$hash".err
code=$?
if [ -f "$statedir/$hash" ]; then
read tries <"$statedir/$hash"
else
tries=0
fi
if [ "$code" -eq 0 ]; then
echo 0 >"$statedir/$hash"
exit 0
fi
tries=$(( tries + 1 ))
printf '%d\n' "$tries" >"$statedir/$hash"
if [ "$tries" -ge "$max_tries" ]; then
cat >&2 <<END_MESSAGE
FAILED $tries times: $@
stdout --------------------
$(cat "$statedir/$hash".out)
stderr --------------------
$(cat "$statedir/$hash".err)
END
END_MESSAGE
fi
exit "$code"