-
Notifications
You must be signed in to change notification settings - Fork 2
/
waitforjobs
executable file
·114 lines (98 loc) · 3.34 KB
/
waitforjobs
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
#!/usr/bin/env bash
# reimplement waitforjobs as a shell script to avoid having to source stuff
# 20230119WF - init
# this script will be among those. %a is command with arguements
parent_processes(){ ps --no-headers -o "%a" --ppid $PPID; }
dt_msg(){ echo "$(date +%FT%H:%M): $*"; }
waitforjobs_usage(){
cat <<HERE
USAGE:
waitforjobs [-j numjobs] [-s sleeptimesecs] [-c "auto"] [-h|--help]"
SYNOPSIS:
wait until fewer than MAXJOBS are running.
check the number of jobs every SLEEPTIME
useful when not using SLURM/TORQUE but just bash forks with '&'
sleep 3 &
sleep 3 &
waitforjobs -j 1 -s 1
will wait until all jobs are finished
# 2023-03-15T13:45: sleep 1 on 2/1 procs: sleep 3; sleep 3;
OPTIONS:
-j --maxjobs set number of threads before waiting
-s --sleeptime set time for 'sleep' command
-c/--config config file that can be resourced to update jobs and sleep
--nightjobs set njobs to run after work hours
if "auto", uses /tmp/host-user-basename.jobcfg
-h --help this message
ENVIRONMENT:
MAXJOBS if -j not specified
SLEEPTIME if -s not specified
DEFAULTS:
2 jobs and 60s sleeps
EXAMPLES
waitforjobs -j 2 -s 60s
waitforfjobs --maxjobs 2 --sleeptime 60s
export SLEEPTIME=60s MAXJOBS=2
waitforjobs
MAXJOBS=2 waitforjobs
HERE
}
initial_config(){
echo "maxjobs=${maxjobs:-2}"
echo "nightjobs=${nightjobs:-2}"
echo "sleeptime=${sleeptime:-60s}"
}
reload_config(){
config="$1"
if [[ $config = "auto" ]]; then
parent_name=$(ps -cq $PPID -o command=|sed 's/[^a-zA-Z0-9@_-]//')
config="${TMPDIR:-/tmp}/$HOSTNAME-$USER-$parent_name.jobcfg"
[ ! -r "$config" ] &&
initial_config > "$config" &&
warn "# wrote waitforjobs config to $config"
fi
if [ ! -r "$config" ]; then
echo "warn 'watiforjobs config $config does not exist!' && exit 2"
return 2
fi
# only grab lines that look like things we care about
# in case file has something accidentally malicious
grep -P '^(maxjobs|sleeptime|nightjobs)=' "$config"
}
is_after_hours() {
# after 6 or before 8
[ $# -gt 0 ] && hour="${1}" || hour=$(date +%H)
test "$hour" -gt 18 -o "$hour" -lt 8
}
waiting(){
sleeptime=${SLEEPTIME:-60s}
maxjobs=${MAXJOBS:-2}
nightjobs=${maxjobs}
config=""
while [ $# -gt 0 ]; do
case "$1" in
-j|--maxjobs) maxjobs=$2; shift 2;;
-s|--sleeptime) sleeptime=$2; shift 2;;
-c|--config) config="$2"; shift 2;;
--nightjobs) nightjobs="$2"; shift 2;;
-h|--help) waitforjobs_usage; exit 0;;
*) warn "'$1' is bad option! see 'waitforjobs --help'"; exit 1;;
esac
done
while mapfile -t procs < <(parent_processes) &&
# greater (not equal) b/c expect parent process (waitforjobs itself) to be in the count
# min $#procs is 1
nproc=${#procs[@]}
[ -n "$config" ] && eval "$(reload_config "$config")"
# job limit based on time of day
# nightjobs default to maxjobs when not expliclty set
njoblimit="$maxjobs"
is_after_hours && njoblimit="$nightjobs"
[ "$nproc" -gt "$njoblimit" ]; do
max_disp=$(("$nproc" - 1))
# assume last is always parent
dt_msg "sleep $sleeptime on ${nproc}/$max_disp procs: $(printf "%s; " "${procs[@]::$nproc-1}")"
sleep "$sleeptime"
done
}
eval "$(iffmain waiting)"