|
| 1 | +#!/bin/sh |
| 2 | +# vim:sw=2:ts=2:sts=2:et |
| 3 | + |
| 4 | +set -eu |
| 5 | + |
| 6 | +LC_ALL=C |
| 7 | +ME=$( basename "$0" ) |
| 8 | +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin |
| 9 | + |
| 10 | +[ "${NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE:-}" ] || exit 0 |
| 11 | + |
| 12 | +touch /etc/nginx/nginx.conf 2>/dev/null || { echo >&2 "$ME: error: can not modify /etc/nginx/nginx.conf (read-only file system?)"; exit 0; } |
| 13 | + |
| 14 | +ceildiv() { |
| 15 | + num=$1 |
| 16 | + div=$2 |
| 17 | + echo $(( (num + div - 1) / div )) |
| 18 | +} |
| 19 | + |
| 20 | +get_cpuset() { |
| 21 | + cpusetroot=$1 |
| 22 | + cpusetfile=$2 |
| 23 | + ncpu=0 |
| 24 | + [ -f "$cpusetroot/$cpusetfile" ] || return |
| 25 | + for token in $( tr ',' ' ' < "$cpusetroot/$cpusetfile" ); do |
| 26 | + case "$token" in |
| 27 | + *-*) |
| 28 | + count=$( seq $(echo "$token" | tr '-' ' ') | wc -l ) |
| 29 | + ncpu=$(( ncpu+count )) |
| 30 | + ;; |
| 31 | + *) |
| 32 | + ncpu=$(( ncpu+1 )) |
| 33 | + ;; |
| 34 | + esac |
| 35 | + done |
| 36 | + echo "$ncpu" |
| 37 | +} |
| 38 | + |
| 39 | +get_quota() { |
| 40 | + cpuroot=$1 |
| 41 | + ncpu=0 |
| 42 | + [ -f "$cpuroot/cpu.cfs_quota_us" ] || return |
| 43 | + [ -f "$cpuroot/cpu.cfs_period_us" ] || return |
| 44 | + cfs_quota=$( cat "$cpuroot/cpu.cfs_quota_us" ) |
| 45 | + cfs_period=$( cat "$cpuroot/cpu.cfs_period_us" ) |
| 46 | + [ "$cfs_quota" = "-1" ] && return |
| 47 | + [ "$cfs_period" = "0" ] && return |
| 48 | + ncpu=$( ceildiv "$cfs_quota" "$cfs_period" ) |
| 49 | + [ "$ncpu" -gt 0 ] || return |
| 50 | + echo "$ncpu" |
| 51 | +} |
| 52 | + |
| 53 | +get_quota_v2() { |
| 54 | + cpuroot=$1 |
| 55 | + ncpu=0 |
| 56 | + [ -f "$cpuroot/cpu.max" ] || return |
| 57 | + cfs_quota=$( cut -d' ' -f 1 < "$cpuroot/cpu.max" ) |
| 58 | + cfs_period=$( cut -d' ' -f 2 < "$cpuroot/cpu.max" ) |
| 59 | + [ "$cfs_quota" = "max" ] && return |
| 60 | + [ "$cfs_period" = "0" ] && return |
| 61 | + ncpu=$( ceildiv "$cfs_quota" "$cfs_period" ) |
| 62 | + [ "$ncpu" -gt 0 ] || return |
| 63 | + echo "$ncpu" |
| 64 | +} |
| 65 | + |
| 66 | +get_cgroup_v1_path() { |
| 67 | + needle=$1 |
| 68 | + found= |
| 69 | + foundroot= |
| 70 | + mountpoint= |
| 71 | + |
| 72 | + [ -r "/proc/self/mountinfo" ] || return |
| 73 | + [ -r "/proc/self/cgroup" ] || return |
| 74 | + |
| 75 | + while IFS= read -r line; do |
| 76 | + case "$needle" in |
| 77 | + "cpuset") |
| 78 | + case "$line" in |
| 79 | + *cpuset*) |
| 80 | + found=$( echo "$line" | cut -d ' ' -f 4,5 ) |
| 81 | + ;; |
| 82 | + esac |
| 83 | + ;; |
| 84 | + "cpu") |
| 85 | + case "$line" in |
| 86 | + *cpuset*) |
| 87 | + ;; |
| 88 | + *cpu,cpuacct*|*cpuacct,cpu|*cpuacct*|*cpu*) |
| 89 | + found=$( echo "$line" | cut -d ' ' -f 4,5 ) |
| 90 | + ;; |
| 91 | + esac |
| 92 | + esac |
| 93 | + done << __EOF__ |
| 94 | +$( grep -F -- '- cgroup ' /proc/self/mountinfo ) |
| 95 | +__EOF__ |
| 96 | + |
| 97 | + while IFS= read -r line; do |
| 98 | + controller=$( echo "$line" | cut -d: -f 2 ) |
| 99 | + case "$needle" in |
| 100 | + "cpuset") |
| 101 | + case "$controller" in |
| 102 | + cpuset) |
| 103 | + mountpoint=$( echo "$line" | cut -d: -f 3 ) |
| 104 | + ;; |
| 105 | + esac |
| 106 | + ;; |
| 107 | + "cpu") |
| 108 | + case "$controller" in |
| 109 | + cpu,cpuacct|cpuacct,cpu|cpuacct|cpu) |
| 110 | + mountpoint=$( echo "$line" | cut -d: -f 3 ) |
| 111 | + ;; |
| 112 | + esac |
| 113 | + ;; |
| 114 | + esac |
| 115 | +done << __EOF__ |
| 116 | +$( grep -F -- 'cpu' /proc/self/cgroup ) |
| 117 | +__EOF__ |
| 118 | + |
| 119 | + case "${found%% *}" in |
| 120 | + "/") |
| 121 | + foundroot="${found##* }$mountpoint" |
| 122 | + ;; |
| 123 | + "$mountpoint") |
| 124 | + foundroot="${found##* }" |
| 125 | + ;; |
| 126 | + esac |
| 127 | + echo "$foundroot" |
| 128 | +} |
| 129 | + |
| 130 | +get_cgroup_v2_path() { |
| 131 | + found= |
| 132 | + foundroot= |
| 133 | + mountpoint= |
| 134 | + |
| 135 | + [ -r "/proc/self/mountinfo" ] || return |
| 136 | + [ -r "/proc/self/cgroup" ] || return |
| 137 | + |
| 138 | + while IFS= read -r line; do |
| 139 | + found=$( echo "$line" | cut -d ' ' -f 4,5 ) |
| 140 | + done << __EOF__ |
| 141 | +$( grep -F -- '- cgroup2 ' /proc/self/mountinfo ) |
| 142 | +__EOF__ |
| 143 | + |
| 144 | + while IFS= read -r line; do |
| 145 | + mountpoint=$( echo "$line" | cut -d: -f 3 ) |
| 146 | +done << __EOF__ |
| 147 | +$( grep -F -- '0::' /proc/self/cgroup ) |
| 148 | +__EOF__ |
| 149 | + |
| 150 | + case "${found%% *}" in |
| 151 | + "") |
| 152 | + return |
| 153 | + ;; |
| 154 | + "/") |
| 155 | + foundroot="${found##* }$mountpoint" |
| 156 | + ;; |
| 157 | + "$mountpoint") |
| 158 | + foundroot="${found##* }" |
| 159 | + ;; |
| 160 | + esac |
| 161 | + echo "$foundroot" |
| 162 | +} |
| 163 | + |
| 164 | +ncpu_online=$( getconf _NPROCESSORS_ONLN ) |
| 165 | +ncpu_cpuset= |
| 166 | +ncpu_quota= |
| 167 | +ncpu_cpuset_v2= |
| 168 | +ncpu_quota_v2= |
| 169 | + |
| 170 | +cpuset=$( get_cgroup_v1_path "cpuset" ) |
| 171 | +[ "$cpuset" ] && ncpu_cpuset=$( get_cpuset "$cpuset" "cpuset.effective_cpus" ) |
| 172 | +[ "$ncpu_cpuset" ] || ncpu_cpuset=$ncpu_online |
| 173 | + |
| 174 | +cpu=$( get_cgroup_v1_path "cpu" ) |
| 175 | +[ "$cpu" ] && ncpu_quota=$( get_quota "$cpu" ) |
| 176 | +[ "$ncpu_quota" ] || ncpu_quota=$ncpu_online |
| 177 | + |
| 178 | +cgroup_v2=$( get_cgroup_v2_path ) |
| 179 | +[ "$cgroup_v2" ] && ncpu_cpuset_v2=$( get_cpuset "$cgroup_v2" "cpuset.cpus.effective" ) |
| 180 | +[ "$ncpu_cpuset_v2" ] || ncpu_cpuset_v2=$ncpu_online |
| 181 | + |
| 182 | +[ "$cgroup_v2" ] && ncpu_quota_v2=$( get_quota_v2 "$cgroup_v2" ) |
| 183 | +[ "$ncpu_quota_v2" ] || ncpu_quota_v2=$ncpu_online |
| 184 | + |
| 185 | +ncpu=$( printf "%s\n%s\n%s\n%s\n%s\n" \ |
| 186 | + "$ncpu_online" \ |
| 187 | + "$ncpu_cpuset" \ |
| 188 | + "$ncpu_quota" \ |
| 189 | + "$ncpu_cpuset_v2" \ |
| 190 | + "$ncpu_quota_v2" \ |
| 191 | + | sort -n \ |
| 192 | + | head -n 1 ) |
| 193 | + |
| 194 | +sed -i.bak -r 's/^(worker_processes)(.*)$/# Commented out by '"$ME"' on '"$(date)"'\n#\1\2\n\1 '"$ncpu"';/' /etc/nginx/nginx.conf |
0 commit comments