-
Notifications
You must be signed in to change notification settings - Fork 3
/
showcron.sh
executable file
·75 lines (61 loc) · 2.71 KB
/
showcron.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
#!/usr/bin/env bash
set -eu pipefail
# Displays cron jobs for all users and directories on a system.
# Usage: ./showcron.sh
# System-wide crontab file and cron job directory. Change these for your system.
CRONTAB='/etc/crontab'
CRONDIR='/etc/cron.d'
# Single tab character. Annoyingly necessary.
tab=$(echo -en "\t")
# Given a stream of crontab lines, exclude non-cron job lines, replace
# whitespace characters with a single space, and remove any spaces from the
# beginning of each line.
clean_cron_lines() {
while read -r line; do
echo "${line}" | grep -E --invert-match '^($|\s*#|\s*[[:alnum:]_]+=)' | sed --regexp-extended "s/\s+/ /g" | sed --regexp-extended "s/^ //"
done
}
# Given a stream of cleaned crontab lines, echo any that don't include the
# run-parts command, and for those that do, show each job file in the run-parts
# directory as if it were scheduled explicitly.
lookup_run_parts() {
while read -r line; do
match=$(echo "${line}" | grep -E -o 'run-parts (-{1,2}\S+ )*\S+')
if [[ -z "${match}" ]]; then
echo "${line}"
else
cron_fields=$(echo "${line}" | cut -f1-6 -d' ')
cron_job_dir=$(echo "${match}" | awk '{print $NF}')
if [[ -d "${cron_job_dir}" ]]; then
for cron_job_file in "${cron_job_dir}"/*; do # */ <not a comment>
[[ -f "${cron_job_file}" ]] && echo "${cron_fields} ${cron_job_file}"
done
fi
fi
done
}
# Temporary file for crontab lines.
temp=$(mktemp) || exit 1
# Add all of the jobs from the system-wide crontab file.
clean_cron_lines <"$CRONTAB" | lookup_run_parts >"$temp"
# Add all of the jobs from the system-wide cron directory.
cat "$CRONDIR"/* | clean_cron_lines >>"$temp" # */ <not a comment>
# Add each user's crontab (if it exists). Insert the user's name between the
# five time fields and the command.
while read -r user; do
crontab -l -u "${user}" 2>/dev/null | clean_cron_lines | sed --regexp-extended "s/^((\S+ +){5})(.+)$/\1${user} \3/" >>"$temp"
done < <(cut --fields=1 --delimiter=: /etc/passwd)
# Output the collected crontab lines. Replace the single spaces between the
# fields with tab characters, sort the lines by hour and minute, insert the
# header line, and format the results as a table.
sed --regexp-extended "s/^(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(.*)$/\1\t\2\t\3\t\4\t\5\t\6\t\7/" "$temp" | sort --numeric-sort --field-separator="${tab}" --key=2,1 | sed "1i\mi\th\td\tm\tw\tuser\tcommand" | column -s"${tab}" -t
rm --force "$temp"
# List all files in the /etc/cron.* directories.
for dir in hourly daily weekly monthly; do
if [[ -d "/etc/cron.${dir}" ]]; then
if [[ "$(ls -A /etc/cron.${dir})" ]]; then
echo -e "\n[cron ${dir} files]"
readlink -f /etc/cron.${dir}/*
fi
fi
done