forked from epety/100-shell-script-examples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
053-verifycron.sh
executable file
·144 lines (115 loc) · 3.43 KB
/
053-verifycron.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/bin/sh
# verifycron - script checks a crontab file to ensure that it's
# formatted properly. Expects standard cron notation of
# min hr dom mon dow CMD
# where min is 0-59, hr 0-23, dom is 1-31, mon is 1-12 (or names)
# and dow is 0-7 (or names). Fields can have ranges (a-e), lists
# separated by commas (a,c,z), or an asterisk. Note that the step
# value notation of Vixie cron is not supported (e.g., 2-6/2).
validNum()
{
# return 0 if valid, 1 if not. Specify number and maxvalue as args
num=$1 max=$2
if [ "$num" = "X" ] ; then
return 0
elif [ ! -z $(echo $num | sed 's/[[:digit:]]//g') ] ; then
return 1
elif [ $num -lt 0 -o $num -gt $max ] ; then
return 1
else
return 0
fi
}
validDay()
{
# return 0 if a valid dayname, 1 otherwise
case $(echo $1 | tr '[:upper:]' '[:lower:]') in
sun*|mon*|tue*|wed*|thu*|fri*|sat*) return 0 ;;
X) return 0 ;; # special case - it's an "*"
*) return 1
esac
}
validMon()
{
# return 0 if a valid month name, 1 otherwise
case $(echo $1 | tr '[:upper:]' '[:lower:]') in
jan*|feb*|mar*|apr*|may|jun*|jul*|aug*) return 0 ;;
sep*|oct*|nov*|dec*) return 0 ;;
X) return 0 ;; # special case, it's an "*"
*) return 1 ;;
esac
}
fixvars()
{
# translate all '*' into 'X' to bypass shell expansion hassles
# save original as "sourceline" for error messages
sourceline="$min $hour $dom $mon $dow $command"
min=$(echo "$min" | tr '*' 'X')
hour=$(echo "$hour" | tr '*' 'X')
dom=$(echo "$dom" | tr '*' 'X')
mon=$(echo "$mon" | tr '*' 'X')
dow=$(echo "$dow" | tr '*' 'X')
}
if [ $# -ne 1 ] || [ ! -r $1 ] ; then
echo "Usage: $0 usercrontabfile" >&2; exit 1
fi
lines=0 entries=0 totalerrors=0
while read min hour dom mon dow command
do
lines="$(( $lines + 1 ))"
errors=0
if [ -z "$min" -o "${min%${min#?}}" = "#" ] ; then
continue # nothing to check
elif [ ! -z $(echo ${min%${min#?}} | sed 's/[[:digit:]]//') ] ; then
continue # first char not digit: skip!
fi
entries="$(($entries + 1))"
fixvars
#### Broken into fields, all '*' replaced with 'X'
# minute check
for minslice in $(echo "$min" | sed 's/[,-]/ /g') ; do
if ! validNum $minslice 60 ; then
echo "Line ${lines}: Invalid minute value \"$minslice\""
errors=1
fi
done
# hour check
for hrslice in $(echo "$hour" | sed 's/[,-]/ /g') ; do
if ! validNum $hrslice 24 ; then
echo "Line ${lines}: Invalid hour value \"$hrslice\""
errors=1
fi
done
# day of month check
for domslice in $(echo $dom | sed 's/[,-]/ /g') ; do
if ! validNum $domslice 31 ; then
echo "Line ${lines}: Invalid day of month value \"$domslice\""
errors=1
fi
done
# month check
for monslice in $(echo "$mon" | sed 's/[,-]/ /g') ; do
if ! validNum $monslice 12 ; then
if ! validMon "$monslice" ; then
echo "Line ${lines}: Invalid month value \"$monslice\""
errors=1
fi
fi
done
# day of week check
for dowslice in $(echo "$dow" | sed 's/[,-]/ /g') ; do
if ! validNum $dowslice 7 ; then
if ! validDay $dowslice ; then
echo "Line ${lines}: Invalid day of week value \"$dowslice\""
errors=1
fi
fi
done
if [ $errors -gt 0 ] ; then
echo ">>>> ${lines}: $sourceline"
echo ""
totalerrors="$(( $totalerrors + 1 ))"
fi
done < $1
echo "Done. Found $totalerrors errors in $entries crontab entries."
exit 0