#!/bin/bash
-# Copyright (C) 2016 Ian Kelling
-
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-
-# http://www.apache.org/licenses/LICENSE-2.0
-
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# Copyright (C) 2019 Ian Kelling
+# SPDX-License-Identifier: AGPL-3.0-or-later
append() {
- cat >> "$1"
+ cat >> "$1"
}
log-once() {
- local cbase c log x i out file
- cbase=/var/local/cron-errors
- [[ $EUID == 0 ]] || cbase=$HOME/cron-errors
- local help="Usage: log-once [OPTION]... LOG_NAME [LOG_MESSAGE]
+ local cbase c log x i out file o tmp
+ cbase=/var/local/cron-errors
+ [[ $EUID == 0 ]] || cbase=$HOME/cron-errors
+ local help="Usage: log-once [OPTION]... LOG_NAME [LOG_MESSAGE...]
For cronjobs, email log on repeated failure and success after failure.
state in the same directory.
-ERRORS: ERRORS is the number of errors to accumulate before outputing the error"
- errors=3
- while true; do
- if [[ $1 == --help ]]; then
- echo "$help"
- return
- elif [[ $1 == -[0-9]* ]]; then
- errors=${1#-}
- shift
- elif [[ $1 == -- ]]; then
- shift
- break
- else
- break
- fi
- done
- log_name=$1
- # todo, make option & make them overridable based on command line or env variable
- [[ -d $cbase ]] || mkdir -p $cbase
- c=$cbase/$log_name
- # http://stackoverflow.com/questions/2456750/detect-presence-of-stdin-contents-in-shell-script
- log=false
- if [[ $2 ]]; then
- log=true
- # read stdin for anything which is not just a newline
- elif [[ ! -t 0 ]]; then
- while read -r x; do
- output+=( $x )
- [[ $x ]] && log=true
- done
- fi
- glob="$c[0-9]*"
- file=($glob); [[ $file != "$glob" ]] || file=
- if $log; then
- out=append
- if [[ $file ]]; then
- i="${file#$c}"
- if (( i < errors )); then
- new_file=$c$((i+1))
- mv $file $new_file
- file=$new_file
- if [[ $file == $c$errors ]]; then
- out="tee -a"
- fi
- fi
- else
- file=${c}1
- fi
- $out $file <<<"log-once: $(date "+%A, %B %d, %r")"
- if [[ $2 ]]; then
- $out $file <<<"$2"
- else
- $out $file <<<"${output[@]}"
- $out $file
- fi
- return 1
+ errors=3
+ while true; do
+ if [[ $1 == --help ]]; then
+ echo "$help"
+ return
+ elif [[ $1 == -[0-9]* ]]; then
+ errors=${1#-}
+ shift
+ elif [[ $1 == -- ]]; then
+ shift
+ break
+ else
+ break
fi
+ done
+ log_name=$1
+ # todo, make option & make them overridable based on command line or env variable
+ [[ -d $cbase ]] || mkdir -p $cbase
+ c=$cbase/$log_name
+ # http://stackoverflow.com/questions/2456750/detect-presence-of-stdin-contents-in-shell-script
+ log=false
+ if [[ $2 ]]; then
+ log=true
+ # read stdin for anything which is not just a newline
+ elif [[ ! -t 0 ]]; then
+ while read -r x; do
+ output+=( "$x" )
+ [[ $x ]] && log=true
+ done
+ fi
+ glob="$c[0-9]*"
+ # file is error file indicating previous error
+ tmp=($glob); file="${tmp[0]}"
+ if [[ $file == "$glob" ]]; then
+ file=
+ fi
+ if $log; then
+ out=append
if [[ $file ]]; then
- rm -f $file
+ i="${file#$c}"
+ if (( i < errors )); then
+ new_file=$c$((i+1))
+ mv $file $new_file
+ file=$new_file
if [[ $file == $c$errors ]]; then
- echo "log-once success after failure for $c"
+ out="tee -a"
fi
+ fi
+ else
+ file=${c}1
+ if (( errors == 1 )); then
+ out="tee -a"
+ fi
+ fi
+ $out $file <<<"log-once: $(date "+%A, %B %d, %r")"
+ if [[ $2 ]]; then
+ $out $file <<<"$*"
+ else
+ for o in "${output[@]}"; do
+ $out $file <<<"$o"
+ done
+ $out $file
fi
return 0
+ fi
+ if [[ $file ]]; then
+ rm -f $file
+ if [[ $file == $c$errors ]]; then
+ echo "log-once success after failure for $c"
+ fi
+ fi
+ return 0
}
log-once "$@"