Compare commits
No commits in common. "697e67c40658fed7038d7fbb55a9a0cac084d5b1" and "30a9fa9c0cfdbbc99777a410e8eee0bffc77124c" have entirely different histories.
697e67c406
...
30a9fa9c0c
311
cpulimit-all.sh
311
cpulimit-all.sh
|
@ -1,311 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
|
|
||||||
kill_child_jobs() {
|
|
||||||
# From https://stackoverflow.com/a/23336595
|
|
||||||
# Kills all child processes, not just jobs.
|
|
||||||
pkill -P $$
|
|
||||||
}
|
|
||||||
cleanup() {
|
|
||||||
kill_child_jobs
|
|
||||||
}
|
|
||||||
|
|
||||||
# From https://unix.stackexchange.com/a/240736
|
|
||||||
for sig in INT QUIT HUP TERM; do
|
|
||||||
trap "
|
|
||||||
cleanup
|
|
||||||
trap - $sig EXIT
|
|
||||||
kill -s $sig "'"$$"' "$sig"
|
|
||||||
done
|
|
||||||
trap cleanup EXIT
|
|
||||||
|
|
||||||
|
|
||||||
verbose=y
|
|
||||||
cpulimit_args="--lazy"
|
|
||||||
limit=""
|
|
||||||
pids=""
|
|
||||||
exes=""
|
|
||||||
paths=""
|
|
||||||
max_processes=100
|
|
||||||
max_depth=3
|
|
||||||
watch_interval=2
|
|
||||||
subprocess_watch_interval=0.5
|
|
||||||
while [ $# -gt 0 ]
|
|
||||||
do
|
|
||||||
opt="$1"
|
|
||||||
case "$opt" in
|
|
||||||
*=*)
|
|
||||||
arg="${1#*=}"
|
|
||||||
opt="${1%%=*}"
|
|
||||||
argshift=1
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
if [ "$#" -ge 2 ]
|
|
||||||
then
|
|
||||||
arg="$2"
|
|
||||||
else
|
|
||||||
arg=""
|
|
||||||
fi
|
|
||||||
argshift=2
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
case "$opt" in
|
|
||||||
--max-depth)
|
|
||||||
case $arg in
|
|
||||||
''|*[!0-9]*)
|
|
||||||
echo "Invalid max depth: $arg, must be a non-negative integer."
|
|
||||||
exit 5
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
max_depth=$arg
|
|
||||||
shift $argshift
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
--max-processes)
|
|
||||||
case $arg in
|
|
||||||
''|*[!0-9]*)
|
|
||||||
echo "Invalid max processes: $arg, must be a positive integer."
|
|
||||||
exit 5
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
max_processes=$arg
|
|
||||||
shift $argshift
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
--watch-interval)
|
|
||||||
watch_interval="$arg"
|
|
||||||
shift $argshift
|
|
||||||
;;
|
|
||||||
--subprocess-watch-interval)
|
|
||||||
subprocess_watch_interval="$arg"
|
|
||||||
shift $argshift
|
|
||||||
;;
|
|
||||||
-p|--pid)
|
|
||||||
if [ -z "$pids" ]
|
|
||||||
then
|
|
||||||
pids="$arg"
|
|
||||||
else
|
|
||||||
pids="$pids
|
|
||||||
$arg"
|
|
||||||
fi
|
|
||||||
shift $argshift
|
|
||||||
;;
|
|
||||||
-e|--exe)
|
|
||||||
if [ -z "$exes" ]
|
|
||||||
then
|
|
||||||
exes="$arg"
|
|
||||||
else
|
|
||||||
exes="$exes
|
|
||||||
$arg"
|
|
||||||
fi
|
|
||||||
shift $argshift
|
|
||||||
;;
|
|
||||||
-P|--path)
|
|
||||||
if [ -z "$paths" ]
|
|
||||||
then
|
|
||||||
paths="$arg"
|
|
||||||
else
|
|
||||||
paths="$paths
|
|
||||||
$arg"
|
|
||||||
fi
|
|
||||||
shift $argshift
|
|
||||||
;;
|
|
||||||
-l|--limit)
|
|
||||||
limit="$arg"
|
|
||||||
cpulimit_args="$cpulimit_args --limit=$arg"
|
|
||||||
shift $argshift
|
|
||||||
;;
|
|
||||||
-c|--cpu)
|
|
||||||
cpulimit_args="$cpulimit_args --cpu=$arg"
|
|
||||||
shift $argshift
|
|
||||||
;;
|
|
||||||
-v|--verbose)
|
|
||||||
cpulimit_args="$cpulimit_args --verbose"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-q|--quiet)
|
|
||||||
verbose=""
|
|
||||||
cpulimit_args="$cpulimit_args --quiet"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-k|--kill)
|
|
||||||
cpulimit_args="$cpulimit_args --kill"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-r|--restore)
|
|
||||||
cpulimit_args="$cpulimit_args --restore"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-s|--signal)
|
|
||||||
cpulimit_args="$cpulimit_args --signal=$arg"
|
|
||||||
shift $argshift
|
|
||||||
;;
|
|
||||||
--)
|
|
||||||
shift
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Programming error: unexpected argument \"$1\" (opt=\"$opt\", arg=\"$arg\")"
|
|
||||||
exit 3
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -z "$limit" ]
|
|
||||||
then
|
|
||||||
echo "Must specify a CPU percentage to limit to (-l/--limit)."
|
|
||||||
exit 4
|
|
||||||
fi
|
|
||||||
if [ -z "$pids" ] && [ -z "$exes" ] && [ -z "$paths" ] && [ "$#" -eq 0 ]
|
|
||||||
then
|
|
||||||
echo "Must specify at least one PID, executable file, path, or command line to limit."
|
|
||||||
exit 5
|
|
||||||
fi
|
|
||||||
|
|
||||||
watched_pids=""
|
|
||||||
limit_pid() {
|
|
||||||
if echo "$watched_pids" | grep --silent -F "$1"
|
|
||||||
then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
if [ "$(echo "$watched_pids" | wc -l)" -ge "$max_processes" ]
|
|
||||||
then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$verbose" ]
|
|
||||||
then
|
|
||||||
if [ -n "$3" ]
|
|
||||||
then
|
|
||||||
echo "Limiting $3: "
|
|
||||||
fi
|
|
||||||
echo "cpulimit --pid=$1 $cpulimit_args"
|
|
||||||
fi
|
|
||||||
# shellcheck disable=SC2086 # $cpulimit_args really is the intended args.
|
|
||||||
cpulimit --pid="$1" $cpulimit_args &
|
|
||||||
cpulimit_pid=$!
|
|
||||||
new_watched="$1:$2:$cpulimit_pid"
|
|
||||||
if [ -z "$watched_pids" ]
|
|
||||||
then
|
|
||||||
watched_pids="$new_watched"
|
|
||||||
else
|
|
||||||
watched_pids="$watched_pids
|
|
||||||
$new_watched"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
limit_pids() {
|
|
||||||
pids="$1"
|
|
||||||
depth="$2"
|
|
||||||
while read -r pid
|
|
||||||
do
|
|
||||||
# From https://stackoverflow.com/a/3951175
|
|
||||||
case $pid in
|
|
||||||
''|*[!0-9]*)
|
|
||||||
# PID is not a number
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
limit_pid "$pid" "$depth" "$3"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done <<EOF
|
|
||||||
$pids
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
limit_by_executable() {
|
|
||||||
if [ -n "$exes" ]
|
|
||||||
then
|
|
||||||
while read -r exe
|
|
||||||
do
|
|
||||||
limit_pids "$(pgrep -x "$exe")" 0 "$exe"
|
|
||||||
done <<EOF
|
|
||||||
$exes
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$paths" ]
|
|
||||||
then
|
|
||||||
while read -r path
|
|
||||||
do
|
|
||||||
limit_pids "$(pgrep -xf "$path")" 0 "$path"
|
|
||||||
done <<EOF
|
|
||||||
$paths
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
limit_by_subprocess() {
|
|
||||||
if [ -z "$watched_pids" ]
|
|
||||||
then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
while read -r watched
|
|
||||||
do
|
|
||||||
depth="$(echo "$watched" | cut -d: -f2)"
|
|
||||||
if [ "$max_depth" -gt "$depth" ]
|
|
||||||
then
|
|
||||||
# Make sure the parent is still alive.
|
|
||||||
if ps -p "$(echo "$watched" | cut -d: -f3)" >/dev/null
|
|
||||||
then
|
|
||||||
ppid="$(echo "$watched" | cut -d: -f1)"
|
|
||||||
limit_pids "$(pgrep -P "$ppid")" "$((depth + 1))" "Child of $ppid"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done <<EOF
|
|
||||||
$watched_pids
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
clean_dead_cpulimit() {
|
|
||||||
if [ -z "$watched_pids" ]
|
|
||||||
then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
tmp="$(echo "$watched_pids" | while read -r watched
|
|
||||||
do
|
|
||||||
if ps -p "$(echo "$watched" | cut -d: -f3)" >/dev/null
|
|
||||||
then
|
|
||||||
echo "$watched"
|
|
||||||
fi
|
|
||||||
done)"
|
|
||||||
watched_pids="$tmp"
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ "$#" -gt 0 ]
|
|
||||||
then
|
|
||||||
"$@" &
|
|
||||||
limit_pid "$!" 0 "program run on command line: $*"
|
|
||||||
fi
|
|
||||||
|
|
||||||
limit_pids "$pids" 0
|
|
||||||
while true
|
|
||||||
do
|
|
||||||
clean_dead_cpulimit
|
|
||||||
if [ -z "$exes" ] && [ -z "$paths" ] && [ -z "$watched_pids" ]
|
|
||||||
then
|
|
||||||
# If there's nothing left to wait for, then exit.
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
limit_by_executable
|
|
||||||
num_watched_before="$(echo "$watched_pids" | wc -l)"
|
|
||||||
limit_by_subprocess
|
|
||||||
num_watched_after="$(echo "$watched_pids" | wc -l)"
|
|
||||||
if [ "$num_watched_before" -eq "$num_watched_after" ]
|
|
||||||
then
|
|
||||||
if [ "$watch_interval" = "0" ]
|
|
||||||
then
|
|
||||||
wait
|
|
||||||
else
|
|
||||||
sleep "$watch_interval"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
sleep "$subprocess_watch_interval"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user