blob: 09c45bca895356a56865e45d4894c18736e8583f (
plain)
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
|
#!/bin/bash
VERBOSE=y
command=firefox
memory_ratio=0.5
control_group=$command
as_root=sudo
total_memory() { free -b | (read line; read Mem total _; echo $total); }
out() { $as_root tee "$@" >/dev/null; }
die() { printf 'Error: %s\n' "$*" >&2; exit 1; }
verbose() { [ ! "$VERBOSE" ] || printf '%s\n' "$*" >&2; }
total_memory=$(total_memory) || die "could not ascertain total system memory; probable bug"
memory_limit_in_bytes=$(bc -q <<< "$total_memory * $memory_ratio / 1" ) || die "process 'bc' failed. Is it installed?"
init_control_group()
{
control_group_dir=/sys/fs/cgroup/"$1"/"$control_group"
[ -d "$control_group_dir" ] && return
$as_root mkdir "$control_group_dir" || die "mkdir failed"
set_memory_limit $memory_limit_in_bytes || die "set_memory_limit failed"
}
get_cpu_limit()
{
false
}
get_memory_limit()
{
cat "$control_group_dir"/memory.limit_in_bytes
}
set_memory_limit()
{
prev=$(get_memory_limit)
if [ "$1" -ne "$prev" ]; then
out "$control_group_dir"/memory.limit_in_bytes <<< $1
verbose "changed memory limit ($prev -> $1)"
else
verbose "memory limit unchanged ($prev)"
fi
}
join_control_group()
{
out "$control_group_dir"/cgroup.procs <<< $$
}
get_cgroup()
{
local key="$1" pid="${2:-$$}" line val
while read line; do
line=${line#*:}
val=${line#$key:}
[ "$val" != "$line" ] || continue
echo "$val"
return
done < /proc/"$pid"/cgroup
false
}
launch_command()
{
init_control_group memory || die "init_control_group failed"
cg=$(get_cgroup memory) || die "failed to ascertain current control group"
[ "$cg" = / ] || die "current control group should be '/', but is instead '$cg'"
join_control_group || die "join_control_group failed"
exec $command "$@"
}
pretty_show_memory_limit()
{
local memory_limit="$(get_memory_limit)"
printf "current memory limit: %d bytes (%d%%)\n" \
"$memory_limit" \
"$((memory_limit * 100 / total_memory))"
}
recpu_control_group()
{
init_control_group cpu
case "$1" in
[0-9]*%) set_cpu_limit $((total_cpu * "${1%\%}" / 100)) ;;
[0-9]*) set_cpu_limit "$1" ;;
[-+*/][0-9]*) set_cpu_limit $(( $(get_cpu_limit) "$1" )) ;;
esac
}
resize_control_group()
{
init_control_group memory
case "$1" in
'') pretty_show_memory_limit >&2 ;;
[0-9]*%) set_memory_limit $((total_memory * "${1%\%}" / 100)) ;;
[0-9]*) set_memory_limit "$1" ;;
[-+*/][0-9]*) set_memory_limit $(( $(get_memory_limit) "$1" )) ;;
esac
}
usage()
{
cat >&2 <<EOF
usage: ${0##*/} [--resize|--resize <bytes>|--resize=<bytes>] [--] [pass-through-options] [...]
${0##*/} --help
EOF
}
case "$1" in
--) shift; launch_command "$@" ;;
--resize) resize_control_group "$2" ;;
--resize=*) resize_control_group "${1#--resize=}" ;;
--cpu=*) recpu_control_group "${1#--cpu=}" ;;
--*) usage; [ "$1" = '--help' -o "$1" = '--usage' ] ;;
*) launch_command "$@" ;;
esac
|