61 lines
2.7 KiB
Bash
61 lines
2.7 KiB
Bash
START=$(state_get start)
|
|
cronline='^[[:space:]]*30[[:space:]]+14[[:space:]]+\*[[:space:]]+\*[[:space:]]+(1-5|mon-fri|Mon-Fri|MON-FRI|1,2,3,4,5)[[:space:]]+/usr/bin/logger[[:space:]]+hello[[:space:]]*$'
|
|
|
|
# Timers made since the lab started, enabled and running, as NAME.timer.
|
|
new_timers() {
|
|
local f
|
|
for f in /etc/systemd/system/*.timer; do
|
|
[ -f "$f" ] || continue
|
|
grep -qxF "$f" "$LAB_STATE/timers-before" 2>/dev/null && continue
|
|
f=${f##*/}
|
|
enabled "$f" && active "$f" && echo "$f"
|
|
done
|
|
}
|
|
every15() {
|
|
systemctl show -p TimersCalendar -p TimersMonotonic "$1" |
|
|
grep -Eq 'OnCalendar=\*-\*-\* \*:00/15:00|OnCalendar=\*-\*-\* \*:00,15,30,45:00|OnUnit(Active|Inactive)USec=15min ;'
|
|
}
|
|
# Seconds until the timer's next run.
|
|
next_in() {
|
|
systemctl list-timers --all -o json 2>/dev/null | python3 -c '
|
|
import json, sys, time
|
|
for t in json.load(sys.stdin):
|
|
if t["unit"] == sys.argv[1] and t.get("next"):
|
|
print(int(t["next"] / 1e6 - time.time())); break' "$1"
|
|
}
|
|
svc_of() { systemctl show -p Unit --value "$1"; }
|
|
ran() { journalctl -q -u "$(svc_of "$1")" --since "@$START" 2>/dev/null | grep -q .; }
|
|
# The first new timer that passes every test in turn.
|
|
pick() {
|
|
local t
|
|
for t in $(new_timers); do
|
|
every15 "$t" || continue
|
|
[ "$1" = interval ] && { echo "$t"; return; }
|
|
n=$(next_in "$t"); [ -n "$n" ] && [ "$n" -le 905 ] || continue
|
|
[ "$1" = next ] && { echo "$t"; return; }
|
|
ran "$t" && { echo "$t"; return; }
|
|
done
|
|
return 1
|
|
}
|
|
|
|
task 1 "alice's crontab runs /usr/bin/logger hello at 14:30 on weekdays"
|
|
need "crond is running" active crond
|
|
need "alice has a crontab" 'crontab -u alice -l'
|
|
need "alice's crontab has 30 14 * * 1-5 /usr/bin/logger hello" 'crontab -u alice -l | grep -Eq "$cronline"'
|
|
|
|
task 2 "A timer runs a script every 15 minutes, also after a reboot"
|
|
need "a new timer in /etc/systemd/system is enabled and active" '[ -n "$(new_timers)" ]'
|
|
need "the timer runs every 15 minutes" 'pick interval'
|
|
need "the timer's next run is at most 15 minutes away" 'pick next'
|
|
need "its service has run since the lab started (journalctl -u)" 'pick ran'
|
|
need "the service runs a script that exists" 'svc=$(svc_of "$(pick ran)"); p=$(systemctl show -p ExecStart --value "$svc" | sed -n "s/.*path=\([^ ;]*\).*/\1/p" | head -n1); [ -x "$p" ]'
|
|
|
|
task 3 "/tmp/at-ran made by an at job; a second job canceled"
|
|
need "atd is running" active atd
|
|
need "/tmp/at-ran exists" test -e /tmp/at-ran
|
|
need "/tmp/at-ran was made after the lab started" '[ "$(stat -c %Y /tmp/at-ran)" -ge "$START" ]'
|
|
need "at least two at jobs were made since the lab started" '
|
|
seq=$(head -n1 /var/spool/at/.SEQ 2>/dev/null)
|
|
[ -n "$seq" ] && [ $((16#$seq - $(state_get at-seq))) -ge 2 ]'
|
|
need "no at job is left in the queue (atq is empty)" '[ -z "$(atq 2>/dev/null)" ]'
|