email root instead of user. tends to work better
[log-quiet] / sysd-mail-once
1 #!/bin/bash
2 # Copyright (C) 2016 Ian Kelling
3
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7
8 # http://www.apache.org/licenses/LICENSE-2.0
9
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16
17 set -eE -o pipefail
18 trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
19
20 errors=3
21 cbase=$HOME/sysd-mail-once-state
22 case "$1" in
23 -h|--help)
24 cat <<EOF
25 Usage: sysd-log-once [-ERRORS] SERVICE COMMAND [ARGS...]
26 For systemd timers, email on repeated failure & success after failure.
27
28 In the service triggered by the timer, prepend this script to the ExecStart.
29 The email will contain the service's logs for the last ERRORS runs.
30
31
32 Stores error counts in $cbase
33
34 -ERRORS: ERRORS is the number of failurs to accumulate before mailing the error.
35 Default is 3.
36 EOF
37 exit 0
38 ;;
39 -[0-9]*)
40 errors=${1#-}
41 shift
42 ;;
43 esac
44 service=$1
45 shift
46
47 c=$cbase/$service # c for command file path base
48
49 glob="$c[0-9]*"
50 arr=($glob); file="${arr[0]}"; [[ $glob != "$file" ]] || file=
51 [[ -d $cbase ]] || mkdir -p $cbase
52
53 if [[ ! $file ]]; then
54 cursor=$(journalctl --show-cursor -qn0|sed 's/^\s*--\scursor:\s*//')
55 fi
56
57 code=0
58 "$@" || code=$?
59 if (( code )); then
60 send_mail=false
61 if [[ $file ]]; then
62 i=${file#$c}
63 if (( i < errors )); then
64 new_file=$c$((i+1))
65 mv $file $new_file
66 file=$new_file
67 if [[ $file == $c$errors ]]; then
68 send_mail=true
69 fi
70 fi
71 else
72 file=${c}1
73 printf "%s\n" "$cursor" >$file
74 if (( errors == 1 )); then
75 send_mail=true
76 fi
77 fi
78 if $send_mail; then
79 journalctl -u $service.service --after-cursor=$(<$file) | \
80 mail -s "$HOSTNAME: $service exit code: $code" root
81 fi
82 else
83 if [[ $file ]]; then
84 rm -f $file
85 if [[ $file == $c$errors ]]; then
86 echo | mail -s "$HOSTNAME: $service success" root
87 fi
88 fi
89 fi